Search code examples
bashmacospipezshmagrittr

Use pipe ("|") as first symbol in bash or zsh command


I have two simple scripts:

./cpthat

BlueM/cliclick types on the keyboard: Shift+Cmd+A, then Cmd+C, to the active iTerm terminal:

#!/bin/zsh
cliclick kd:shift,cmd t:a ku:shift t:c ku:cmd
pbpaste>$THATF
  • Shift+Cmd+A selects the output from the previous command, and
  • Cmd+C copies "that" to the clipboard.
  • pbpaste then writes that to the file $THATF defined system-wide.

./that

#!/bin/zsh
cat $THATF

This prints out the output of the last command as stored by cpthat.

(I know I can run $ command > $THATF directly but for other reasons I need to act retroactively on the command output. Also, not thread safe.)

The challenge:

I'm trying to get to where I can start a zsh or bash command with a pipe:

$ |grep -i sometext

Where, in effect, this happens:

$ that|grep -i sometext

Would this be possible somehow?

  • Overriding the pipe operator?
  • zsh config magic?
  • I'm using zsh heavily but am open for any solution.

Solution

  • Animation showing that | alone at the beginning of command can be replaced automatically by the output of previous command:

    enter image description here

    Edit ~/.zshrc to override zsh's zle accept-line widget:

    
    readonly THATF="path/to/your/temporary/file"
    
    my-accept-line () {  
      if [[ "${BUFFER:0:1}" == '|' ]]; then    
        /usr/local/bin/cliclick kd:shift,cmd t:a ku:shift w:100 t:c ku:cmd
        pbpaste>"${THATF}"
        BUFFER='cat ${THATF} '${BUFFER}
      fi  
      zle .accept-line
    }
    
    zle -N accept-line my-accept-line
    

    Explanation

    • When you hit enter after entering a command, zsh runs the accept-line widget.
    • We override that widget, but before exiting we remember to call the original widget with zle .accept-line. With the dot prefix the factory widget is ran.
    • In iTerm2, shift+cmd+a selects all the output from the previous command, and cmd+c copies that to the system pasteboard.
    • We paste the contents of the pasteboard and redirects that to the temporary file declared earlier, pointed to by ${THATF}.
    • We prepend $BUFFER, the zsh special variable available within zle widget code, with the output of the previous command.

    Dependencies, caveats:

    This particular solution depends on:

    • cliclick dispatching macOS keyboard events. Perhaps a native solutions exist e.g. ANSI/escape sequence.
    • iTerm to handle the keybind for copying last commands output.
    • zsh for the zle widget.

    Xode snippet above is proof-of-concept only and is wildly insecure.