• 0 Posts
  • 7 Comments
Joined 2 years ago
cake
Cake day: June 13th, 2023

help-circle
  • It’s been a while, but my clumsy adding of a comment to the buffer is unnecessary, given zle -M, which will display a message outside of the buffer. So here’s an updated version:

    # -- Run input if single line, otherwise insert newline --
    # Key: enter
    # Credit: https://programming.dev/comment/2479198
    .zle_accept-except-multiline () {
      if [[ $BUFFER != *$'\n'* ]] {
        zle .accept-line
        return
      } else {
        zle .self-insert-unmeta
        zle -M 'Use alt+enter to submit this multiline input'
      }
    }
    zle -N       .zle_accept-except-multiline
    bindkey '^M' .zle_accept-except-multiline  # Enter
    
    # -- Run input if multiline, otherwise insert newline --
    # Key: alt+enter
    # Credit: https://programming.dev/comment/2479198
    .zle_accept-only-multiline () {
      if [[ $BUFFER == *$'\n'* ]] {
        zle .accept-line
      } else {
        zle .self-insert-unmeta
      }
    }
    zle -N         .zle_accept-only-multiline
    bindkey '^[^M' .zle_accept-only-multiline  # Enter
    


  • Thanks again for posting your improvements! I will have them!

    The idea here, checking for newline characters rather than counting lines, is to prevent it treating one line that is so long it wraps to the next as counting as a multiline input, right? So now I’m looking like

    EDIT: lemmy is at least mangling ampersands here. Hard to believe it doesn’t have proper code blocks yet…

    # -- Run input if single line, otherwise insert newline --
    # Key: enter
    # Assumes: setopt interactivecomments
    # Credit: https://programming.dev/comment/2479198
    .zle_accept-except-multiline () {
      if [[ $BUFFER != *$'\n'* ]] {
        zle accept-line
        return
      } else {
        zle self-insert-unmeta
        if [[ $BUFFER == *$'\n'*$'\n'* ]] {
          local hint="# Use alt+enter to submit this multiline input"
          if [[ $BUFFER != *${hint}* ]] {
            LBUFFER+=$hint
            zle self-insert-unmeta
          }
        }
      }
    }
    zle -N .zle_accept-except-multiline
    bindkey '^M' .zle_accept-except-multiline  # Enter
    
    # -- Run input if multiline, otherwise insert newline --
    # Key: alt+enter
    # Credit: https://programming.dev/comment/2479198
    .zle_accept_only_multiline () {
      if [[ $BUFFER == *$'\n'* ]] {
        zle accept-line
      } else {
        zle self-insert-unmeta
      }
    }
    zle -N .zle_accept_only_multiline
    bindkey '^[^M' .zle_accept_only_multiline  # Enter
    

    For pushing the line/multiline, I combine it with my clear function (ctrl+l):

    # -- Refresh prompt, rerunning any hooks --
    # Credit: romkatv/z4h
    .zle_redraw-prompt () {
      for 1 ( chpwd $chpwd_functions precmd $precmd_functions ) {
        if (( $+functions[$1] ))  $1 &>/dev/null
      }
      zle .reset-prompt
      zle -R
    }
    
    # -- Better Screen Clearing --
    # Clear line and redraw prompt, restore line at next prompt
    # Key: ctrl+l
    # Depends: .zle_redraw-prompt
    .zle_push-line-and-clear () { zle push-input; zle clear-screen; .zle_redraw-prompt }
    zle -N       .zle_push-line-and-clear
    bindkey '^L' .zle_push-line-and-clear  # ctrl+l
    

  • I started using this, it makes a lot of sense and I like it, thanks!

    I can imagine myself forgetting how to accept multiline input with alt+enter, so I added a help message to _zle_ml_enter in the multiline case after the second line. It assumes setopt interactivecomments is already set:

    EDIT: note that lemmy mangles the less-than symbol

    # -- Run input if single line, otherwise insert newline --
    # Key: enter
    # Assumes: setopt interactivecomments
    # Credit: https://programming.dev/comment/2479198
    .zle_accept-except-multiline () {
      if (( BUFFERLINES <= 1 )) {
        zle accept-line
      } else {
        zle self-insert-unmeta
        if (( BUFFERLINES == 2 )) {
          LBUFFER+="# Use alt+enter to submit this multiline input"
          zle self-insert-unmeta
        }
      }
    }
    zle -N .zle_accept-except-multiline
    bindkey '^M' .zle_accept-except-multiline  # Enter
    


  • OK, well FWIW in Zsh you can use a keybind to trigger ZLE functions that turn your already-entered lines back into in-progress lines.

    The most straightforward built-in function for this is push-line-or-edit:

    At the top-level (PS1) prompt, equivalent to push-line. At a secondary (PS2) prompt, move the entire current multiline construct into the editor buffer. The latter is equivalent to push-input followed by get-line.

    So let’s say you want to trigger this with ctrl+e, all you need is:

    bindkey '^e' push-line-or-edit