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

Sublime-like changes #109

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open

Conversation

msirringhaus
Copy link

No description provided.

…t just handles the command supposed for itself and hands the rest down
…(with the exception of prompt commands with arguments).
Copy link
Collaborator

@little-dude little-dude left a comment

Choose a reason for hiding this comment

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

Thanks a lot for all this work @msirringhaus. I only looked at the first 3 9 commits (up to 0bc9269) for the moment but there may be enough so spark some discussions already. Since I'm reviewing commit by commit, there are probably things that are already addressed, so feel free to mark those comments as resolved with a link to the relevant commit if that's the case.

src/core/cmd.rs Outdated
"d" | "delete" => Ok(Command::Delete),
"bn" | "next-buffer" => Ok(Command::NextBuffer),
"bp" | "prev-buffer" => Ok(Command::PrevBuffer),
"q" | "quit" | "exit" => Ok(Command::Quit),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should refrain from adding more command aliases. We could discuss modifying the existing ones, but I think it will confusing to have too many commands that do the same thing.

Copy link
Author

Choose a reason for hiding this comment

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

Well, I never planned to do a full PR.
I switched to command names used by sublime texts keymap-file, but didn't want to remove the old names just yet.

@@ -0,0 +1,742 @@
[
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is kind of bike-sheddy but I'm not a fan of JSON as a configuration format, even though in this case JSON5 is a bit easier for humans to read. For something as simple as this configuration, something like toml may be a bit more concise and readable.

On another topic, this file contains lots of things that don't apply to xi. It would be nice to reduce it to what is currently supported.

Copy link
Author

Choose a reason for hiding this comment

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

Again, my goal, which I know is not compatible with xi-terms goal is to have compatibility with sublime. Thus, I used their keymap-files, so existing user-configs could just be copied in.

Copy link
Collaborator

Choose a reason for hiding this comment

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

which I know is not compatible with xi-terms goal is to have compatibility with sublime

Oh I had misunderstood that part. I thought you wanted to make something somewhat similar to Sublime, but not 100% compatible. In that case, would you mind if I took whatever I'm interested in from your changes, and adapt it to what I envision for xi-term?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, absolutely. That was my suggestion from the beginning :-)
To be clear: I don't have 100% compatibility as a hard requirement, although it would be nice and handy.
But since you are, as far as I understand, going for vim-like modular editing my editor (be it 100% sublime compatible or not) will definitely not be compatible with xi-term.
So i figured a hard fork is my only path.
It certainly would be nice join forces, though. But currently I don't really see how.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But since you are, as far as I understand, going for vim-like modular editing my editor

Oh I don't have a clear path actually. I don't really want to make a vim clone for multiple reasons (I don't like VimScript in the first place). It's true that I'd like to provide a way to do vim-like editing because that's what I'm used to, but I'd like to make that optional, and allow users to use their own keybindings. Emacs is doing that with evil mode for instance (which is what I use), and I really like that approach.

It certainly would be nice join forces, though. But currently I don't really see how.

As far as I can tell the only thing that is really specific to Sublime in this PR is the configuration format and the default bindings. To me, the Sublime bindings are fine, and it's easy to use different ones anyway. The only thing I'm not fond is using json for the config file but I think I can live with that for now and switch to something else in the future (there are solutions if we want to keep supporting json: having multiple parsers, or providing a tool to convert config files, etc.).

I've been using vim for a long time, but I'm not opposed to ideas from other editors because I'm not convinced that making re-implementing an existing editor is likely to succeed. First, it's hard to replicate the exact behavior of another editor. Second, there are behaviors don't want to keep (I don't like vim's registers I prefer emacs kill ring, and I don't like emacs undo system, I prefer vim's for instance). Finally, users won't switch to something new if it's exactly the same thing.

So yeah, I'm open to non-vim-like behavior :)

Copy link
Author

Choose a reason for hiding this comment

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

Finally, users won't switch to something new if it's exactly the same thing.

Absolutely. The only reason I started this was because there simply is no terminal editor like sublime at all. There is one without multiple cursors and such, but that is abandoned (and written in JS. Of course...).

So yeah, I'm open to non-vim-like behavior :)

Ok, cool! So maybe we could join forces after all. That would be nice.

Yes the only really sublime-specific stuff is the json-format (including structs for parsing it).
Once we have the translated map of Temion-Keyevents and Command, it doesn't matter anymore.

And since the Command-structs for parsing the json could get different names with the serde-macros, we can hide sublime heritage there as well.

Only, in the prompt, I currently expose sublimes names to the user as well. There could of course be another layer in there as well. Tried to keep it simple for now.

The only blocker I see would be the modal editing (insert mode, vs. command mode), if you envision that for your editor.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So maybe we could join forces after all.

I hope so!

Once we have the translated map of Temion-Keyevents and Command, it doesn't matter anymore.

Yeah, that's why I'm not to worried about using JSON for now. It should be easy to change in the future.

The only blocker I see would be the modal editing (insert mode, vs. command mode), if you envision that for your editor.

Well for now no frontend has it, and it's unclear whether that requires support in xi-core or not. Plus there are tons of other features to add first, so it's not a priority for me right now.

Copy link
Author

Choose a reason for hiding this comment

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

Well for now no frontend has it, and it's unclear whether that requires support in xi-core or not. Plus there are tons of other features to add first, so it's not a priority for me right now.

Alright. Although I see (for the base functionality) no reason to involve xi-core. If editor.rs has a mode it can interpret a keypress-event like "w" as either Insert(w) or RelativeMove{by: word} and act accordingly.

}

impl KeybindingConfig {
pub fn parse(config_path: &Path) -> Result<KeybindingConfig, Box<std::error::Error + Sync + Send + 'static>> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should probably have an ConfigError error instead of using a trait object. Something like:

enum ConfigError {
    Parsing(...), // contains the inner error
    Invalid(....),
    .... // potentially a bunch of other variants.
}

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, error handling was pretty low on my list, to be honest. I basically just reused existing error types. This definetly needs a major cleanup (I actually think of removing "failure"-crate in the process, as its not really maintained anymore AFAIK)

src/core/config.rs Outdated Show resolved Hide resolved
src/core/tui.rs Outdated Show resolved Hide resolved
src/core/cmd.rs Outdated Show resolved Hide resolved
src/core/cmd.rs Outdated Show resolved Hide resolved
pub by: RelativeMoveDistance,
pub forward: bool,
#[serde(default)]
pub extend: bool
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does extend do?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, not a perfect name (taken from sublime). If true, it states that this movement should extend the current selection (e.g. move one word right with extend selects that word).
Works for all kinds of movements (page up down, go to beginning / end of file / line, and so on).

src/core/cmd.rs Outdated
/// Move to new word
words,
/// Move to end of word
word_ends,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are these all actually implemented in xi? I'd rather have only what's currently implemented, with maybe a comment explaining how this may be extended in the future.

Copy link
Author

Choose a reason for hiding this comment

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

words yes, word_ends no. I have it in there so that serde can parse the given keymap without choking

#[derive(Debug, Deserialize, Serialize, PartialEq, Clone)]
pub struct RelativeMove {
pub by: RelativeMoveDistance,
pub forward: bool,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure how I feel about forward. On one hand, I think enums are clearer: Direction::{Left,Up,Right,Down} is clearer than have to think: "horizontal move + not forward => left", "vertical move + forward => down", etc. On the other, having an enum with all 4 directions here would be partially redundant with the by attribute, because when moving by lines, we already know the direction is either up or down for instance.

Copy link
Author

Choose a reason for hiding this comment

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

This again comes from sublimes keymap. Thats how they specify it and I just went along. I agree that an enum would be nicer here (but I would actually just use Direction::{Forward, Backward}, so not to make by redundant). But I didn't have the time to hack that into the serde parsing.

src/widgets/editor.rs Outdated Show resolved Hide resolved
src/widgets/editor.rs Show resolved Hide resolved
src/widgets/editor.rs Outdated Show resolved Hide resolved
src/widgets/editor.rs Outdated Show resolved Hide resolved
Cargo.toml Show resolved Hide resolved
@little-dude
Copy link
Collaborator

@msirringhaus do you mind explaining a bit what you added in db5488b ? Where are the cursors rendered here? It seems like what this adds is the ability to select multiple regions corresponding to a search result, is that right?

@msirringhaus
Copy link
Author

msirringhaus commented Jul 1, 2019

It seems like what this adds is the ability to select multiple regions corresponding to a search result, is that right?

That is correct. Its the ctrl+d-feature of sublime. You either pre-select some text and press ctrl+d or you press ctrl+d twice to select the current word under the cursor and go from there. Luckily, that is xi-cores behavior too, when trying to "select under cursor" + "find next" with no selection.

Once you have something selected, repeated ctrl+d presses will search for the selected text and add a new cursor there.

Where are the cursors rendered here?

Indeed, they are currently not. xrl is hiding the annotations-part of the update notification from xi-core. In it would be the information of where the cursors are (albeit a bit clumsy to parse out of (see here )

Edit: To clarify: It works, but you can only see the main cursor at the moment

@little-dude
Copy link
Collaborator

little-dude commented Jul 1, 2019

Selecting lines suffers the same issue than #99 (comment)

Edit: Oh, I see you already commented on that issue here, sorry.

@@ -91,12 +96,22 @@ impl KeybindingConfig {
"delete" => Some(Event::Key(Key::Delete)),
"insert" => Some(Event::Key(Key::Insert)),
"escape" => Some(Event::Key(Key::Esc)),
"ctrl+right" => Some(Event::Unsupported(vec![27, 91, 49, 59, 53, 67])),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit confused: why are these named "ctrl+something" instead of an actual command name like "word-left" or "word-right"? Other question: what are ctrl+shift+up and ctrl+shift+down supposed to do? It seems that it's not doing anything visible at the moment.

Copy link
Author

Choose a reason for hiding this comment

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

I'm a bit confused: why are these named "ctrl+something" instead of an actual command name like "word-left" or "word-right"?

It looks different on HEAD. There its separated. a bit clearer.

But in principle there are two parsers: One is to parse a command name to Command-struct (e.g. select_all).

The other is to parse key-descriptions to Termion::Event, e.g. escape to Key::Esc.
Now a user can edit their JSON file to let pressing escape trigger select_all for example.

ctrl+right and others are not supported by Termion right now, as they differ from Terminal to Terminal, which...sucks. But to have the functionality, I basically used the Unsupported event to make it work with my terminal.
So this is already a "known bug" of this implementation. Another is, that Termion doesn't differentiate between ctrl+a and ctrl+shift+a. I have opened a bugreport there, but I fear its not really actively maintained anymore.

Other question: what are ctrl+shift+up and ctrl+shift+down supposed to do? It seems that it's not doing anything visible at the moment.

Try typing after doing that :-) It adds a cursor below or above the current cursor, which are unfortunately invisible at the moment. I have some screencasts showing of the features, just have to find a place to upload to

Copy link
Author

Choose a reason for hiding this comment

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

Ah, sorry. I confused ctrl+shift+up/down with alt+shift+up/down.
ctrl+shift+up/down is supposed to move the current line one line up or down (swap lines). But this is currently not supported by xi-core ( #793 ).

Either way, this part is not there to define functionality! Its there so that users can use ctrl+shift+up/down for whatever they want (They could map the function of alt+shift+up/down to ctrl+shift+up/down. Or they could for whatever reason map ctrl+shift+up to select_all and ctrl+shift+down to next buffer.).
This part of the code is only there to "know a key-combination exists". Not connect it to any functionality.

But for completeness, here are the screencasts I talked about (just "view raw" for each file):
https://gist.github.com/msirringhaus/83fbc1ef10ae93e56fe8d68dea1dd3b3

"switchcase" is what alt+shift+up/down is doing at the moment.
ctrlD obviously is what ctrl+d does.
And Palette is the CommandPrompt with suggestions. There is a crate to have sublime-like fuzzy-search, which I want to implement next. Then finally, the Prompt should handle up/down movements to select suggestions (at the moment it only shows them)

@little-dude
Copy link
Collaborator

@msirringhaus ctrl+d is pretty neat :D

@little-dude
Copy link
Collaborator

@msirringhaus I've looked at every commit at this point although I just glanced at some, and I played a bit with the editor. This is pretty awesome work, and I'd love to integrate it into xi-term. But as it stands, this PR a bit too big to review properly, and I won't be able to do a good job at merging it. Do you think you could try to split it into smaller PRs and rework the git history so that commits don't have some unrelated changes? (No pressure, I'm not in a hurry).

@msirringhaus
Copy link
Author

In principle yes. First off, it might be way less work to just review HEAD as it is. Most of the commits are me reworking my own features a bazillion times. Thus adding a lot of noise which is not visible on HEAD anymore.

But if that is still too big, I could in theory split it up. But do you require for those intermediate commits to actually work and compile? That would be a lot of work, and unfortunately my "work on whatever project you want"-week is now over :-( So time is again limited.

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

Successfully merging this pull request may close these issues.

None yet

2 participants