Bash: call script with customized keyboard shortcuts?

后端 未结 3 1000
梦谈多话
梦谈多话 2021-02-03 15:45

Lets say I have a script, \"myscript.sh\", with contents being simply echo $PWD. I\'d like to bind somehow this script to a key combo in bash

相关标签:
3条回答
  • 2021-02-03 16:17

    Simple version:

    This command at a shell prompt:

    bind '"\ee": "${PWD##*/}\e\C-e"'
    

    or this line added to your ~/.inputrc:

    "\ee": "${PWD##*/}\e\C-e"
    

    will cause Alt-e to insert the basename of the current directory on the command line. It requires that the default binding of the readline function shell-expand-line which is \e\C-e be present (this could be adapted if it's different). I'm also making the assumption that you're using Bash's emacs mode.

    Unfortunately, it causes things that have already been typed to be expanded as well. One of the affects of this is that after having typed:

    svn ci -m "
    

    and pressing Alt-e, the quotation mark will have disappeared. There are a couple of ways to deal with this.

    One, assume that all you'll lose is the quote and either manually add it back or have the readline macro add it for you:

    bind '"\ee": "${PWD##*/}\e\C-e\eb\"\C-e"'
    

    which just isn't very satisfactory.

    Advanced version:

    Or, two, kill the line, do the insertion, then yank the line back:

    bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b"'
    

    or

    bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ef\C-f"'
    

    This leaves the rest of the line intact (nothing else is expanded or deleted), but it uses the kill ring, so it may leave it in a state that's different than you expect (if you're using it). It also inserts a space after the inserted directory name (the spaces in the macro are used to ensure that older kill-ring contents are not regurgitated if the macro is executed at the beginning or end of the line). The macro should work regardless of the position of the cursor in the line. The insertion will be made at the cursor's position, leaving the cursor in the same position [in the first version].

    Edit: The second version leaves the cursor after the dirname and space that are inserted.

    Edit 2:

    The readline function shell-forward-word (unbound) does a better job than forward-word (\ef) for this. You can make use of that like this:

    bind '"\ew":shell-forward-word'
    bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ew\C-f"'
    

    By the way, you should know that Bash keyboard shortcuts are not active in other programs such as nano.

    0 讨论(0)
  • 2021-02-03 16:31

    Ok, not really an answer, but I'd just like to summarize the comments I got so far, which are useful for my problem. However, the question as it stands - in respect to bash keyboard shortcuts running arbitrary scripts - is still not answered (I'd still prefer doing all this with a single key combo :))

     
    First, I can use a 'global' script like:

    $ sudo bash -c 'cat > /usr/bin/bpwd <<EOF
    #!/bin/bash
    basepwd=\$(basename \$(pwd))
    echo -n \$basepwd                 # suppress line ending
    # exec 1>/dev/null               # debug: redir stdout to null
    echo -n \$basepwd | xsel -i -b    # suppress LF, and make xsel read from stdin 
    # exec 1>/dev/tty                # debug: restore stdout
    EOF
    chmod +x /usr/bin/bpwd'
    

    Or, I can add bash functions to my .bashrc (note: make sure you reload bash after you add these lines to .bashrc - for example, simply by typing bash in your current terminal):

    $ echo '
    bpwd2() { basepwd=${PWD##*/} ; echo -n $basepwd | xsel -i -b ; echo -n $basepwd ; }
    svnci-test() { echo -n "$(bpwd2): $*" ; }
    svnci-m() { svn ci -m "$(bpwd2): $*" ; }' >> ~/.bashrc
    

     
    Basically, I misunderstood Reese Moore's suggestion originally - you can indeed use backticks - consider this command session (after the above commands have been ran):

    $ bpwd
    Desktop\
    $ bpwd2
    Desktop\
    $ echo `bpwd`
    Desktop
    $ echo "`bpwd2` 2"
    Desktop 2
    

    This is what I needed to understand Moore's "the output from the backticked commands will be used as input on the executed command" (however, one also needs to take care to clean the line endings from the output); or, in my case, I can call

    svn ci -m "`bpwd`: my message here"
    # svn ci -m "${PWD##*/}: my message here" # alternatively
    

    ... or, I could follow camh's suggestion, and use svnci-m as a function (in my case, I almost never use additional arguments to svn ci, and so my version is slightly different). And to test whether arguments are passed correctly, I can use the svnci-test function:

    $ svnci-test "my message"
    Desktop: my message\
    

     
    Thanks for the comments so far,
    Cheers!

    0 讨论(0)
  • 2021-02-03 16:33

    One way to do what you want with a single key press is to take advantage of programmable completion in bash. You possibly have some programmable completion set up with the bash_completion tool/package. If not, look into that to see the specifics of how it is done.

    The idea is to have the programmable completion recognise when you have hit at the start of a svn commit message and then have it return a single completion which is the text you want to insert (the basename of the current directory).

    I've only dabbled with programmable completion so I can't give you the details, but the above-mentioned bash_completion package or the subversion completion script may be a good start.

    0 讨论(0)
提交回复
热议问题