3

I can not wrap my head finding a solution for this simple editing task in Readline. I just want to kill the characters forward until the end of a Big word, that is, (more or less) until the next space character (dE in vim).

Specially, when hitting a key sequence,

> 2234I567.890 32345678

would become

> 2234I 32345678

where the cursor position is indicated by I.

Here are what I've tried to add in ~/.inputrc to make it happen.

  1. First attempt:

    "\eF": vi-fWord
    "\eD": "\eF\C-w"
    

This does kill forward for a Big word, but it works incorrectly if the cursor is placed in word. In that case, the whole word is killed.

  1. Second attempt:

    "\eF": vi-fWord
    "\C-x1": kill-region
    "\eD": "\C-@\eF\C-x1 "
    

This should have worked, shouldn't it? At least it works if I manually kick the complete \C-@\eF\C-x1 key sequence myself on the commandline. However it was weird that nothing happened when I kicked \eD key sequence.

  1. I also thought about using vi mode command vi-delete-to and the likes, but not sure how to do it due to the complete lack of documentation relating to Readline vi mode.

So I'm here to seek help.

2

OK, I have got it work finally.

It turns out that I just have to remap set-mark function to another key sequence (say, \C-x2) and replace the default \C-@ with this new mapping. Then everything works just fine.

Maybe it's a bug that \C-@ doesn't function as expected when appearing in RHS of a Readline macro.

The following is my setup that makes Alt + D delete input forward to the next space or big WORD (in vim jargon).

"\C-x0": vi-eWord
"\C-x1": kill-region
"\C-x2": set-mark
"\eF": "\C-x0\C-f"
"\eD": "\C-x2\eF\C-x1"

Because we didn't use shell-specific Readline function such as shell-forward-word, the key binding works in all applications that utilize Readline library, for example, bash, (i)python, etc.

| improve this answer | |
2

The answer lies indeed in the poorly documented vi-delete-to (mapped to 'd' by default). This function works only when you prefix the subsequent movement command with a digit. The default mapping dE implicitly uses a count of 1 but remapping the movement command requires an explicit count.

For example in your case the key sequence "d1\C-x0" would delete one WORD. You could map that sequence so you do not have to specify the WORD-count/digit to delete 1 WORD:

"d\C-x0": "d1\C-x0"

Deleting multiple WORDs would still work.

Note that this applies to all movements. For example d1fe would delete to (including) the first occurrance of the letter 'e', c2to will change to (excluding) second occurance of the letter 'o'. All these actions can be repeated with '.', just like vi/vim.


As for your solution

Because you are using vi-functions I am assuming you are using vi editing mode. C-@ is an emacs mapping, therefore you had to explicitly map that functions as you did: it is not a bug.

You could replace the 'C-f' with 'x' (delete under cursor-function) so the command does not break at the end of a line (because the cursor cannot move forward)

"\C-x0": vi-eWord "\C-x1": kill-region "\C-x2": set-mark "\eD": "\C-x2\C-x0x\C-x1"

The downside to this/your solution can unfortunately not be prefixed with 'vi-arg-digit' to delete multiple WORDs in one go.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.