|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# Switch between emacs frame and its clients. Also support piping to emacs. |
| 4 | + |
| 5 | +EMACS_CLIENT=${EMACS_CLIENT:-emacsclient} |
| 6 | +# The server to use. |
| 7 | +EMACS_SERVER= |
| 8 | +# Additional arguments for emacsclient. |
| 9 | +EMACS_ARGS= |
| 10 | + |
| 11 | +usage() |
| 12 | +{ |
| 13 | + cat <<EOF |
| 14 | +usage: $(basename $0) [emacsclient options] |
| 15 | +
|
| 16 | +Focuses the emacs frame and switches bach to the client after dismissing its buffers. |
| 17 | +Supports the following additional options : |
| 18 | +
|
| 19 | + --do-switch Do focus the emacs frame (default, unless one of -[ect] is present). |
| 20 | + --dont-switch Don't focus the emacs frame. |
| 21 | + --do-return Do return to the client, if necessary (default, unless -n is present). |
| 22 | + --dont-return Don't return to the client. |
| 23 | + - Read stdin and append it as a file to the argument list. |
| 24 | +
|
| 25 | +If you want to be able to not switch, you need to put this in your init file : |
| 26 | +
|
| 27 | + (setq server-raise-frame nil) |
| 28 | +
|
| 29 | +emacslient --help output follows. |
| 30 | +--- |
| 31 | +
|
| 32 | +$($EMACS_CLIENT --help) |
| 33 | +EOF |
| 34 | +} |
| 35 | + |
| 36 | +emacs_windowid() |
| 37 | +{ |
| 38 | + $EMACS_CLIENT --eval "\ |
| 39 | +(and (eq window-system 'x) \ |
| 40 | + (string-to-number \ |
| 41 | + (frame-parameter nil 'outer-window-id)))" |
| 42 | +} |
| 43 | + |
| 44 | +if which which &>/dev/null; then |
| 45 | + which xprop >/dev/null || { echo "You need to install xprop."; exit 0; } |
| 46 | + which wmctrl >/dev/null || { echo "You need to install wmctrl."; exit 0; } |
| 47 | +fi |
| 48 | + |
| 49 | +# This avoids a bug in gtk, when emacs treats this DISPLAYs |
| 50 | +# differently. |
| 51 | +if [[ "$DISPLAY" == :? ]];then |
| 52 | + EMACS_ARGS="$EMACS_ARGS -d ${DISPLAY}.0" |
| 53 | +fi |
| 54 | + |
| 55 | +if [ -n "$EMACS_SERVER" ];then |
| 56 | + EMACS_ARGS="$EMACS_ARGS -f $EMACS_SERVER" |
| 57 | +fi |
| 58 | + |
| 59 | +EMACS_CLIENT="$EMACS_CLIENT $EMACS_ARGS" |
| 60 | + |
| 61 | +DO_SWITCH=true # Focus the frame ? |
| 62 | +DO_RETURN=false # Return to the client ? |
| 63 | +DO_PIPE=false # Read from stdin ? |
| 64 | + |
| 65 | +for arg; do |
| 66 | + case $arg in |
| 67 | + --) break ;; |
| 68 | + -[cte]|--eval) DO_SWITCH=false ;; |
| 69 | + -n) DO_RETURN=false ;; |
| 70 | + --help) usage; exit 0 ;; |
| 71 | + esac |
| 72 | +done |
| 73 | + |
| 74 | +# Handle and remove extra options. |
| 75 | +ARGS=() |
| 76 | +EOA=false # Handle -- special argument. |
| 77 | +for arg; do |
| 78 | + if [ "$EOA" = true ];then |
| 79 | + ARGS[${#ARGS[@]}]="$arg" |
| 80 | + continue |
| 81 | + fi |
| 82 | + case $arg in |
| 83 | + --do-switch) DO_SWITCH=true ;; |
| 84 | + --dont-switch) DO_SWITCH=false ;; |
| 85 | + --do-return) DO_RETURN=true ;; |
| 86 | + --dont-return) DO_RETURN=false ;; |
| 87 | + -) DO_PIPE=true ;; |
| 88 | + --) EOA=true ;& # fall through |
| 89 | + *) ARGS[${#ARGS[@]}]="$arg" ;; |
| 90 | + esac |
| 91 | +done |
| 92 | +set -- "${ARGS[@]}" |
| 93 | + |
| 94 | +# support piping to emacs |
| 95 | +if [ $# -eq 0 ] || { [ $# -eq 1 ] && [ "$1" = -n ]; }; then |
| 96 | + DO_PIPE=true |
| 97 | +fi |
| 98 | + |
| 99 | +if [ "$DO_PIPE" = true ];then |
| 100 | + TEMPFILE=$(mktemp --tmpdir stdin.XXX) |
| 101 | + cat > $TEMPFILE |
| 102 | + set -- "$@" $TEMPFILE; |
| 103 | +fi |
| 104 | + |
| 105 | +# Get the window IDs. |
| 106 | +CLIENTID=$(xprop -root | grep "^_NET_ACTIVE_WINDOW(WINDOW)" \ |
| 107 | + | sed -e 's/.* \([^ ]\+\)$/\1/') |
| 108 | +EMACSID=$(emacs_windowid 2>/dev/null | grep '^[0-9]\+$') |
| 109 | + |
| 110 | +# Now focus the emacsframe |
| 111 | +if [ "$DO_SWITCH" = "true" ] && \ |
| 112 | + [ -n "$EMACSID" ];then |
| 113 | + wmctrl -i -a $EMACSID |
| 114 | +fi |
| 115 | + |
| 116 | +# Install a exit hook, which returns to the client and does some cleanup. |
| 117 | +trap exit_hook EXIT |
| 118 | +exit_hook() |
| 119 | +{ |
| 120 | + # give focus back to the client |
| 121 | + if [ "$DO_SWITCH" = "true" ] \ |
| 122 | + && [ "$DO_RETURN" = "true" ] \ |
| 123 | + && [ -n "$CLIENTID" ] ; then |
| 124 | + wmctrl -i -a $CLIENTID |
| 125 | + fi |
| 126 | + |
| 127 | + [ -n "$TEMPFILE" ] && rm -f "$TEMPFILE" |
| 128 | +} |
| 129 | + |
| 130 | +$EMACS_CLIENT "$@" |
0 commit comments