elves / elvish

Powerful scripting language & versatile interactive shell
https://elv.sh/
BSD 2-Clause "Simplified" License
5.62k stars 300 forks source link

Add command to pause readline. #535

Open notramo opened 6 years ago

notramo commented 6 years ago

The command would save readline buffer content and cursor position, then make available the terminal for programs executed.

E.g. I would prefer to select files using ranger --choosefiles, instead of the builtin navigation mode, but it isn't possible while readline is used, because it captures the output of the program, and grabs the input. So, this would be a solution:

fn ranger-choose-files-readline {
  # Pause readline
  edit:pause-readline

  # Clean previously selected files
  put ?(rm /tmp/elvish-ranger-filechooser-$pid.txt) > /dev/null

  # Launch ranger
  ranger --choosefiles=/tmp/elvish-ranger-filechooser-$pid.txt

  # Restart readline
  edit:continue-readline

  # Insert the selected files to the command line
  edit:insert-at-dot (cat /tmp/elvish-ranger-filechooser-$pid.txt)
}

Another example: solve #393 in Elvish script:

fn external_edit_command {
  # Pause readline
  edit:pause-readline

  # Launch editor (my favourite is Kakoune)
  print $edit:current-command > /tmp/elvish-edit-command-$pid.elv
  kak /tmp/elvish-edit-command-$pid.elv

  # Restart readline
  edit:continue-readline

  # Read the modified command back
  edit:current-command = (cat /tmp/elvish-edit-command-$pid.elv)
}
xiaq commented 6 years ago

Nice! I like this proposal.

krader1961 commented 4 years ago

FWIW, It doesn't appear that edit:pause-readline is required; at least in the case of using an external editor to edit the command buffer on UNIX like systems. It appears to be sufficient to redirect stdin/out/err to /dev/tty. This seems to work for me:

fn external_edit_command {
  print $edit:current-command > /tmp/elvish-edit-command-$pid.elv
  $E:EDITOR /tmp/elvish-edit-command-$pid.elv </dev/tty >/dev/tty 2>&1
  edit:current-command = (cat /tmp/elvish-edit-command-$pid.elv | slurp)
}

edit:insert:binding[Alt-v] = $external_edit_command~

Having said that it would be better to implement the proposal in this issue since that would make this mechanism more portable; e.g., to MS Windows where /dev/tty isn't a thing.

aca commented 2 years ago
set edit:insert:binding[Alt-e] = {|| edit:replace-input (print $edit:current-command | e:vipe --suffix elv | slurp)}

You can use vipe which does same job in much simpler manner. It is included in moreutils.