Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate ansi mod from alacritty_terminal #64

Closed
wants to merge 16 commits into from
Closed

Conversation

nw0
Copy link
Contributor

@nw0 nw0 commented Jul 29, 2020

This is from alacritty/alacritty#1063.

I've naively moved everything over, and put Line, Column, Rgb in a new file, term.rs. The new modules, ansi and term, are behind a feature flag ansi, which doesn't work with no_std (depends on std::io).

As this is separate from the main crate, not filing a PR to remove from there yet.

@nixpulvis
Copy link
Contributor

nixpulvis commented Jul 29, 2020

I'd love to see what this looks like integrated with Alacritty itself.

I'm also wondering if it makes sense to move more of the functionality of Rgb, for example, over here. I'm not sure I would want to wrap Rgb in another struct inside Alacritty. Serde stuff is perhaps another story...

Or do you already have a plan for this?

Copy link
Member

@chrisduerr chrisduerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd really like to see this work without std too, I don't think fundamentally there are a lot of things that require std just for the dispatch part.

Features like serde deserialization probably shouldn't be provided at all. I don't see how we can offer reasonable deserialization for the types of this crate. That said, types like Line and Column are probably better off as just raw numbers anyways. Since the complexity of handling another type here doesn't really have much of a benefit.

@nixpulvis
Copy link
Contributor

Yea, I'm just trying to imagine how the Rgb struct should be handled between alacritty_terminal and vte. Perhaps we end up with two structs (one wrapping the other), but if there's a clean way to avoid it, that would be nice.

@nw0
Copy link
Contributor Author

nw0 commented Jul 30, 2020

I'd really like to see this work without std too, I don't think fundamentally there are a lot of things that require std just for the dispatch part.

I believe all usages of Write are for replying, e.g. like "Cursor Position Report". This could be refactored into the Handler trait. What do you think?

I'm just trying to imagine how the Rgb struct should be handled between alacritty_terminal and vte.

I think it makes sense for Rgb struct in vte, since we do have to handle color parsing. If we don't want serde here, we can consider a remote derive in alacritty_terminal?

Line, Column: it does seem a bit silly to force implementers of Handler to use these newtypes. I'll remove them if there are no objections.

@chrisduerr
Copy link
Member

I believe all usages of Write are for replying, e.g. like "Cursor Position Report". This could be refactored into the Handler trait. What do you think?

That is correct, but I don't think it makes sense to have them as part of the handler trait since they are separate things. So it should probably be a separate trait.

I think it makes sense for Rgb struct in vte, since we do have to handle color parsing. If we don't want serde here, we can consider a remote derive in alacritty_terminal?

I've considered removing Rgb from vte and all associated parsing stuff, but this is really the kinda stuff why we want to move this to VTE. This isn't anything terminal specific, every terminal needs to behave the same here and if something is missing we want to benefit from contributions to vte in Alacritty. So really this should be part of vte. Because of that the only option is to have our Alacritty-specific derive in a wrapper type, which shouldn't be a problem.

Line, Column: it does seem a bit silly to force implementers of Handler to use these newtypes. I'll remove them if there are no objections.

I agree, using types for this with no methods on these types just makes things confusing. Properly naming the parameters should be sufficient and easier to handle downstream. Then people can wrap it in their types anyways.

@nw0 nw0 marked this pull request as draft July 31, 2020 05:52
@nw0
Copy link
Contributor Author

nw0 commented Jul 31, 2020

That is correct, but I don't think it makes sense to have them as part of the handler trait since they are separate things. So it should probably be a separate trait.

I've experimented with a trait for this. It seems that the Handler should be able to do whatever it wants with its "writer", rather than being constrained to io::Write. I've parameterised this as trait Handler<W>, with no constraints on W. Does this work?

I've removed the std dependencies, although I note that we can't use join (https://github.com/alacritty/vte/pull/64/files#diff-f20c875fb67cf4f8bc670d89d1d49db1R788) in 1.36.0 without the unstable SliceConcatExt trait (thus: updated build tests fail). From 1.38.0, join is provided by a stable SliceConcat trait, if that's at all helpful.

@nw0 nw0 marked this pull request as ready for review July 31, 2020 08:26
@chrisduerr
Copy link
Member

I've experimented with a trait for this. It seems that the Handler should be able to do whatever it wants with its "writer", rather than being constrained to io::Write. I've parameterised this as trait Handler, with no constraints on W. Does this work?

With how traits work in Rust, that would probably mean that the handler wouldn't be able to do anything with its writer. If a trait is passed as parameter unconstrained without any methods, you can't do anything with it.

I've removed the std dependencies, although I note that we can't use join (https://github.com/alacritty/vte/pull/64/files#diff-f20c875fb67cf4f8bc670d89d1d49db1R788) in 1.36.0 without the unstable SliceConcatExt trait (thus: updated build tests fail). From 1.38.0, join is provided by a stable SliceConcat trait, if that's at all helpful.

I don't think 1.38.0 would help, right? Since this is still using allocations like Strings and Vecs.

@nw0
Copy link
Contributor Author

nw0 commented Jul 31, 2020

I've experimented with a trait for this. It seems that the Handler should be able to do whatever it wants with its "writer", rather than being constrained to io::Write. I've parameterised this as trait Handler, with no constraints on W. Does this work?

With how traits work in Rust, that would probably mean that the handler wouldn't be able to do anything with its writer. If a trait is passed as parameter unconstrained without any methods, you can't do anything with it.

Actually, I'm thinking of something like impl Handler<std::fs::File> for Term. Parameterising on a trait would probably result in the scenario you state, yes.


I'm getting bogged down dealing with the Rgb issue at the same time as the trait one. Do you mind if I refactor this over a few PRs? I'll also work on changes to the main crate simultaneously so we're convinced the design works.

@chrisduerr
Copy link
Member

Do you mind if I refactor this over a few PRs?

I do mind, yes. I don't think it makes sense to merge this unless there's a complete package that makes sense. Just copy-pasting stuff over isn't really beneficial.

@nw0 nw0 marked this pull request as draft July 31, 2020 11:59
@nixpulvis
Copy link
Contributor

I'm getting bogged down dealing with the Rgb issue at the same time as the trait one. Do you mind if I refactor this over a few PRs?

@nw0 FWIW, it's completely possible to make a new set of branches which you merge into this branch. I'm not necessarily saying you should do that, since those PRs would be on your own fork, but it may help you personally. I know I often need a branch to keep my head on straight.

@nw0
Copy link
Contributor Author

nw0 commented Aug 1, 2020

I've straightened things out and have the following design as pushed above:

  • Parameterise Handler<W>. This means impl<...> Handler<W> for Term<T, W> in the main crate -- i.e. additional parameter for Term et al. I'd very much like to hear about better designs, though.
  • Removed serde, replace with remote derives in main crate. I had trouble with the CursorStyle remote deserialisation, but it doesn't seem like an issue with this design.
  • Line, Column typedef'ed to usize.
  • I do have a working (passes tests on x86-64 Linux) implementation of the main crate as a proof-of-concept.

The obvious questions:

  • Structure and documentation: hidden behind a feature flag? etc.
  • Remove log?

As regards 1.36:

I don't think 1.38.0 would help, right? Since this is still using allocations like Strings and Vecs.

The issue is really that the trait that provides join ( rust-lang/rust#62403) was only stabilised in 1.38.0, if one has no_std.

@chrisduerr
Copy link
Member

The issue is really that the trait that provides join ( rust-lang/rust#62403) was only stabilised in 1.38.0, if one has no_std.

Updating to 1.38.0 is not a problem, but even if you update you won't be able to call join here.

src/ansi.rs Outdated Show resolved Hide resolved
@nw0 nw0 marked this pull request as ready for review August 6, 2020 13:41
@nw0 nw0 requested a review from chrisduerr August 15, 2020 06:18
Copy link
Member

@chrisduerr chrisduerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be updated to the latest version of Alacritty's ansi.rs and vte.

Also please do not force-push this PR if possible; it's difficult to review changes if the entire file is just rewritten.

src/ansi.rs Outdated
@@ -0,0 +1,1625 @@
//! ANSI Terminal Stream Parsing.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of this file, this documentation and the feature isn't really great. That just describes all of this library basically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm not sure how you want to deal with this. To me, the obvious questions are:

  1. Should this be hidden behind a feature flag? (I think so)
  2. Should a module be exposed, or just the Processor, Handler, etc.? (I'm not sure. We aren't adding that much new functionality, are we?)

I've put in a slightly more descriptive docstring for now, but I think answering these sooner would be helpful.

src/ansi.rs Outdated
Comment on lines 11 to 12
type Line = usize;
type Column = usize;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these type aliases for?

src/ansi.rs Outdated
Comment on lines 34 to 37
#[cfg(feature = "no_std")]
let colors = str::from_utf8(color).ok()?.split('/').collect::<ArrayVec<[_; 4]>>();
#[cfg(not(feature = "no_std"))]
let colors = str::from_utf8(color).ok()?.split('/').collect::<Vec<_>>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this function can be easily rewritten to not require any of this Vec/ArrayVec?

src/ansi.rs Outdated
if params.len() >= 2 {
#[cfg(feature = "no_std")]
{
let mut title = ArrayString::<[_; crate::MAX_OSC_RAW]>::new();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with ArrayString, but we have ascii as input while ArrayString most likely handles unicode. That means that the size of MAX_OSC_RAW would not be enough to store the title.

Though I see no harm in just passing params downstream and letting them handle this. Then they can decide what they want to use, no need to try and convert this into a string for them when it's trivial to do for them, but difficult to do for us.

@nw0
Copy link
Contributor Author

nw0 commented Aug 22, 2020

Should I use merge commits to update to the latest vte?

(I ask because I've generally worked with people who insist on rebases which does mean force-pushing)

@chrisduerr
Copy link
Member

Should I use merge commits to update to the latest vte?

To update on top of VTE a rebase is usually easier, yes. That will keep the history consistent though, so I don't have to re-check everything.

@nw0 nw0 marked this pull request as draft February 1, 2021 13:30
@chrisduerr
Copy link
Member

#75

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants