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

Conditional Bind Sequences #293

Closed
wants to merge 17 commits into from
Closed

Conversation

gwenn
Copy link
Collaborator

@gwenn gwenn commented Oct 20, 2019

Make possible to return different command depending on input state.

Try to fix #269.
No breaking change but a Cmd enum with Custom(Action) entry which can return a Cmd looks bad...

Make possible to return different command depending on input state.
Copy link

@cchalmers cchalmers left a comment

Choose a reason for hiding this comment

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

Looks great, would like to see this get merged.

(Hope you don't mind, I've reviewed it like's it's my repo when really this is my first time looking at the project)

/// Takes the currently edited `line` with the cursor `pos`ition and
/// returns the command to be performed or `None` to perform the default
/// one.
pub action: fn(line: &str, pos: usize, ctx: &ActionContext) -> Option<Cmd>,

Choose a reason for hiding this comment

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

I feel like the line and pos should be part of the context.

An fn is pretty restrictive because it doesn't allow adding any of your own context. Having something like

Arc<Box<dyn Fn(&ActionContext) -> Option<Cmd>>>

would be much more flexible.

Also I think it would be better to not make this public to allow non-breaking changes in the future.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Most of the time, you just need to check line and/or pos. So if you can access them directly, it seems better/easier.
And could you provide a case where an action is not stateless ?

Choose a reason for hiding this comment

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

For example I've been playing around with having a key bindings to insert bits of text with skim. The bits of text can be dependent on the rest of the program.

Copy link
Contributor

Choose a reason for hiding this comment

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

We have just merged Validation where anyone would use line for sure, but it only has ValidationContext in the signature. Well, the reason for validator is probably because line is mutable there. But I think having similar signature is nice anyway.

}
}

pub struct ActionContext<'r> {

Choose a reason for hiding this comment

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

You've made the struct public but it's isn't exposed anywhere so no documentation gets generated for it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

My bad.

@@ -53,7 +53,9 @@ use crate::edit::State;
use crate::highlight::Highlighter;
use crate::hint::Hinter;
use crate::history::{Direction, History};
pub use crate::keymap::{Anchor, At, CharSearch, Cmd, Movement, RepeatCount, Word};
pub use crate::keymap::{
Action, Anchor, At, CharSearch, Cmd, InputMode, Movement, RepeatCount, Word,

Choose a reason for hiding this comment

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

Suggested change
Action, Anchor, At, CharSearch, Cmd, InputMode, Movement, RepeatCount, Word,
Action, ActionContext, Anchor, At, CharSearch, Cmd, InputMode, Movement, RepeatCount, Word,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Indeed.

/// Custom dynamic action
#[derive(Clone)]
pub struct Action {
pub name: String,

Choose a reason for hiding this comment

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

Can you say what this name is used for? It's not clear to me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is used only for tracing / debugging.

@gwenn
Copy link
Collaborator Author

gwenn commented Nov 24, 2019

@cchalmers We still need to support composite command. For example, clear whole line and interrupt.
Either by mutating the line buffer directly like linefeed.
Or by invoking multiple commands like replxx.

And last, we need to fix/move this

Copy link

@cchalmers cchalmers left a comment

Choose a reason for hiding this comment

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

Yeah, I hit the issue of only one command when playing around. In some ways it would be nice if we had access to the whole State when making a custom action.

And last, we need to fix/move this

I'm not sure this means.

@gwenn
Copy link
Collaborator Author

gwenn commented Nov 25, 2019

@cchalmers I mean that if your custom action replaces some text, we cannot just do a pattern matching anymore (Cmd::Custom doesn't match Cmd::Replace)...


if let Some(cmd) = self.custom_binding(wrt, key) {
return Ok(if cmd.is_repeatable() {
cmd.redo(Some(n), wrt)
Copy link
Contributor

Choose a reason for hiding this comment

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

This replaces number returned from the custom action. I.e. I can't return Move(BackwardChar(10).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right. This should not be done for Action, only for simple bindings.

/// Takes the currently edited `line` with the cursor `pos`ition and
/// returns the command to be performed or `None` to perform the default
/// one.
pub action: fn(line: &str, pos: usize, ctx: &ActionContext) -> Option<Cmd>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand why Action::action contains a function. Rather than Action being a trait.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mainly because Action is Sized.

Copy link
Contributor

Choose a reason for hiding this comment

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

Box<dyn Action> is also sized. And I don't think it can be a performance issue here.

tailhook added a commit to tailhook/rustyline that referenced this pull request Oct 16, 2020
Most commands are factored out to the function, except:

1. Commands that need extra input
2. Suspend, which needs access to the terminal

This should be enough to implement `ContextValidator::invoke`.

Also this commit brings `CompleteHint`, `SelfInsert`, `Insert` commands
to the `match` over `Cmd` instead of keeping them as separate `if`
statements as latter doesn't seem to change their behavior.

This is needed to implement kkawakam#453, and kkawakam#293 (although, latter might need
input-accepting commands too or another approach).
tailhook added a commit to tailhook/rustyline that referenced this pull request Nov 9, 2020
Most commands are factored out to the function, except:

1. Commands that need extra input
2. Suspend, which needs access to the terminal

This should be enough to implement `ContextValidator::invoke`.

Also this commit brings `CompleteHint`, `SelfInsert`, `Insert` commands
to the `match` over `Cmd` instead of keeping them as separate `if`
statements as latter doesn't seem to change their behavior.

This is needed to implement kkawakam#453, and kkawakam#293 (although, latter might need
input-accepting commands too or another approach).
@gwenn gwenn closed this Mar 7, 2021
@gwenn gwenn deleted the conditional_binding branch March 7, 2021 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Conditional Bind Sequences
3 participants