From c8403624a74348ba3537ded640cba8d0c746568e Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Sun, 2 Dec 2018 13:59:45 +0100 Subject: [PATCH 1/7] Expose a 'terminal' command for the various windowing systems It allows plugins to create generic terminal using the user's preferred windowing system For example, it can be used to run fzf, gdb or simply a shell. * 'new' commands are refactored to simply use the 'terminal' one * style and docstrings has been unified * all windowing systems go through "sh -c" for consistency purposes, even if unnecessary --- rc/base/screen.kak | 89 ++++++++++++++++++++++++++++++---------------- rc/base/tmux.kak | 75 ++++++++++++++++++++++++++------------ rc/base/x11.kak | 40 +++++++++++++-------- rc/extra/kitty.kak | 79 ++++++++++++++++++++++++++-------------- 4 files changed, 188 insertions(+), 95 deletions(-) diff --git a/rc/base/screen.kak b/rc/base/screen.kak index 66a8db5d..4d13c375 100644 --- a/rc/base/screen.kak +++ b/rc/base/screen.kak @@ -6,44 +6,70 @@ hook -group GNUscreen global KakBegin .* %sh{ echo " alias global focus screen-focus alias global new screen-new-vertical + alias global terminal screen-terminal-vertical " } -define-command screen-new-vertical -params .. -command-completion -docstring "Split the current pane into two, left and right" %{ - nop %sh{ - tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" - screen -X eval \ - 'split -h' \ - 'focus down' \ - "screen sh -c 'kak -c \"${kak_session}\" -e \"$*\" ; - screen -X remove'" \ - < "/dev/$tty" - } -} - -define-command screen-new-horizontal -params .. -command-completion -docstring "Split the current pane into two, top and bottom" %{ - nop %sh{ - tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" - screen -X eval \ - 'split -v' \ - 'focus right' \ - "screen sh -c 'kak -c \"${kak_session}\" -e \"$*\" ; - screen -X remove'" \ - < "/dev/$tty" - } -} - -define-command screen-new-window -params .. -command-completion -docstring "Create a new window" %{ +define-command screen-terminal-impl -hidden -params 3.. -command-completion %{ nop %sh{ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" - screen -X screen kak -c "${kak_session}" -e "$*" < "/dev/$tty" + screen -X eval "$1" "$2" + shift 2 + cmd=$(printf %s "$*") + screen -X screen sh -c "${cmd}; screen -X remove" < "/dev/$tty" } } -define-command -docstring %{screen-focus []: focus the given client -If no client is passed then the current one is used} \ - -params ..1 -client-completion \ - screen-focus %{ evaluate-commands %sh{ +define-command screen-terminal-vertical -params 1.. -command-completion -docstring ' +screen-terminal-vertical []: create a new terminal as a screen pane +The current pane is split into two, left and right +The program passed as argument will be executed in the new terminal' \ +%{ + screen-terminal-impl 'split -v' 'focus right' %arg{@} +} +define-command screen-terminal-horizontal -params 1.. -command-completion -docstring ' +screen-terminal-horizontal []: create a new terminal as a screen pane +The current pane is split into two, top and bottom +The program passed as argument will be executed in the new terminal' \ +%{ + screen-terminal-impl 'split -h' 'focus down' %arg{@} +} +define-command screen-terminal-window -params 1.. -command-completion -docstring ' +screen-terminal-window []: create a new terminal as a screen window +The program passed as argument will be executed in the new terminal' \ +%{ + nop %sh{ + tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" + screen -X screen sh -c "$*" < "/dev/$tty" + } +} + +define-command screen-new-vertical -params .. -command-completion -docstring ' +screen-new-vertical []: create a new kakoune client as a screen pane +The current pane is split into two, left and right +The optional arguments are passed as commands to the new client' \ +%{ + screen-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" +} +define-command screen-new-horizontal -params .. -command-completion -docstring ' +screen-new-horizontal []: create a new kakoune client as a screen pane +The current pane is split into two, top and bottom +The optional arguments are passed as commands to the new client' \ +%{ + screen-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" +} +define-command screen-new-window -params .. -command-completion -docstring ' +screen-new-window []: create a new kakoune client as a screen window +The optional arguments are passed as commands to the new client' \ +%{ + screen-terminal-window "kak -c '%val{session}' -e '%arg{@}'" +} + +define-command screen-focus -params ..1 -client-completion -docstring ' +screen-focus []: focus the given client +If no client is passed then the current one is used' \ +%{ + evaluate-commands %sh{ if [ $# -eq 1 ]; then printf %s\\n " evaluate-commands -client '$1' focus @@ -52,4 +78,5 @@ If no client is passed then the current one is used} \ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" screen -X select "${kak_client_env_WINDOW}" < "/dev/$tty" fi -} } + } +} diff --git a/rc/base/tmux.kak b/rc/base/tmux.kak index 3a17669d..c587cdb9 100644 --- a/rc/base/tmux.kak +++ b/rc/base/tmux.kak @@ -7,44 +7,75 @@ hook global KakBegin .* %sh{ echo " alias global focus tmux-focus alias global new tmux-new-horizontal + alias global terminal tmux-terminal-horizontal " fi } -## Temporarily override the default client creation command -define-command -hidden -params 1.. tmux-new-impl %{ +define-command -hidden -params 2.. tmux-terminal-impl %{ evaluate-commands %sh{ tmux=${kak_client_env_TMUX:-$TMUX} if [ -z "$tmux" ]; then - echo "echo -markup '{Error}This command is only available in a tmux session'" + echo "fail 'This command is only available in a tmux session'" exit fi tmux_args="$1" shift - if [ $# -ne 0 ]; then kakoune_params="-e '$@'"; fi - TMUX=$tmux tmux $tmux_args "env TMPDIR='${TMPDIR}' kak -c ${kak_session} ${kakoune_params}" < /dev/null > /dev/null 2>&1 & + TMUX=$tmux tmux $tmux_args env TMPDIR="$TMPDIR" sh -c "$*" < /dev/null > /dev/null 2>&1 & } } -define-command tmux-new-vertical -params .. -command-completion -docstring "Split the current pane into two, top and bottom" %{ - tmux-new-impl 'split-window -v' %arg{@} +define-command tmux-terminal-vertical -params 1.. -shell-completion -docstring ' +tmux-terminal-vertical []: create a new terminal as a tmux pane +The current pane is split into two, top and bottom +The program passed as argument will be executed in the new terminal' \ +%{ + tmux-terminal-impl 'split-window -v' %arg{@} +} +define-command tmux-terminal-horizontal -params 1.. -shell-completion -docstring ' +tmux-terminal-horizontal []: create a new terminal as a tmux pane +The current pane is split into two, left and right +The program passed as argument will be executed in the new terminal' \ +%{ + tmux-terminal-impl 'split-window -h' %arg{@} +} +define-command tmux-terminal-window -params 1.. -shell-completion -docstring ' +tmux-terminal-window []: create a new terminal as a tmux window +The program passed as argument will be executed in the new terminal' \ +%{ + tmux-terminal-impl 'new-window' %arg{@} } -define-command tmux-new-horizontal -params .. -command-completion -docstring "Split the current pane into two, left and right" %{ - tmux-new-impl 'split-window -h' %arg{@} +define-command tmux-new-vertical -params .. -command-completion -docstring ' +tmux-new-vertical []: create a new kakoune client as a tmux pane +The current pane is split into two, top and bottom +The optional arguments are passed as commands to the new client' \ +%{ + tmux-terminal-vertical "kak -c %val{session} -e '%arg{@}'" +} +define-command tmux-new-horizontal -params .. -command-completion -docstring ' +tmux-new-horizontal []: create a new kakoune client as a tmux pane +The current pane is split into two, left and right +The optional arguments are passed as commands to the new client' \ +%{ + tmux-terminal-horizontal "kak -c %val{session} -e '%arg{@}'" +} +define-command tmux-new-window -params .. -command-completion -docstring ' +tmux-new-window []: create a new kakoune client as a tmux window +The optional arguments are passed as commands to the new client' \ +%{ + tmux-terminal-window "kak -c %val{session} -e '%arg{@}'" } -define-command tmux-new-window -params .. -command-completion -docstring "Create a new window" %{ - tmux-new-impl 'new-window' %arg{@} +define-command tmux-focus -params ..1 -client-completion -docstring ' +tmux-focus []: focus the given client +If no client is passed then the current one is used' \ +%{ + evaluate-commands %sh{ + if [ $# -eq 1 ]; then + printf "evaluate-commands -client '%s' focus" "$1" + elif [ -n "${kak_client_env_TMUX}" ]; then + TMUX="${kak_client_env_TMUX}" tmux select-pane -t "${kak_client_env_TMUX_PANE}" > /dev/null + fi + } } - -define-command -docstring %{tmux-focus []: focus the given client -If no client is passed then the current one is used} \ - -params ..1 -client-completion \ - tmux-focus %{ evaluate-commands %sh{ - if [ $# -eq 1 ]; then - printf %s\\n "evaluate-commands -client '$1' focus" - elif [ -n "${kak_client_env_TMUX}" ]; then - TMUX="${kak_client_env_TMUX}" tmux select-pane -t "${kak_client_env_TMUX_PANE}" > /dev/null - fi -} } diff --git a/rc/base/x11.kak b/rc/base/x11.kak index 1c4f6df6..9d5ee82e 100644 --- a/rc/base/x11.kak +++ b/rc/base/x11.kak @@ -22,29 +22,39 @@ A shell command is appended to the one set in this option at runtime} \ done } -define-command -docstring %{x11-new []: create a new kak client for the current session -The optional arguments will be passed as arguments to the new client} \ - -params .. \ - -command-completion \ - x11-new %{ evaluate-commands %sh{ +define-command x11-terminal -params 1.. -shell-completion -docstring ' +x11-terminal []: create a new terminal as an x11 window +The program passed as argument will be executed in the new terminal' \ +%{ + evaluate-commands %sh{ if [ -z "${kak_opt_termcmd}" ]; then - echo "echo -markup '{Error}termcmd option is not set'" + echo "fail 'termcmd option is not set'" exit fi - if [ $# -ne 0 ]; then kakoune_params="-e '$@'"; fi - setsid ${kak_opt_termcmd} "kak -c ${kak_session} ${kakoune_params}" < /dev/null > /dev/null 2>&1 & -}} + setsid ${kak_opt_termcmd} "$*" < /dev/null > /dev/null 2>&1 & + } +} -define-command -docstring %{x11-focus []: focus a given client's window -If no client is passed, then the current client is used} \ - -params ..1 -client-completion \ - x11-focus %{ evaluate-commands %sh{ +define-command x11-new -params .. -command-completion -docstring ' +x11-new []: create a new kakoune client as an x11 window +The optional arguments are passed as commands to the new client' \ +%{ + x11-terminal "kak -c %val{session} -e '%arg{@}'" +} + +define-command x11-focus -params ..1 -client-completion -docstring ' +x11-focus []: focus a given client''s window +If no client is passed, then the current client is used' \ +%{ + evaluate-commands %sh{ if [ $# -eq 1 ]; then - printf %s\\n "evaluate-commands -client '$1' focus" + printf "evaluate-commands -client '%s' focus" "$1" else xdotool windowactivate $kak_client_env_WINDOWID > /dev/null fi -} } + } +} alias global focus x11-focus alias global new x11-new +alias global terminal x11-terminal diff --git a/rc/extra/kitty.kak b/rc/extra/kitty.kak index 8a640d3e..c8533312 100644 --- a/rc/extra/kitty.kak +++ b/rc/extra/kitty.kak @@ -5,6 +5,8 @@ hook -group kitty-hooks global KakBegin .* %sh{ echo " alias global new kitty-new alias global new-tab kitty-new-tab + alias global terminal kitty-terminal + alias global terminal-tab kitty-terminal-tab alias global focus kitty-focus alias global repl kitty-repl alias global send-text kitty-send-text @@ -12,42 +14,65 @@ hook -group kitty-hooks global KakBegin .* %sh{ fi } -define-command -docstring %{kitty-new []: create a new kak client for the current session -Optional arguments are passed as arguments to the new client} \ - -params .. \ - -command-completion \ - kitty-new %{ nop %sh{ - kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type "$(command -v kak 2>/dev/null)" -c "${kak_session}" -e "$*" -}} +define-command kitty-terminal -params 1.. -shell-completion -docstring ' +kitty-terminal []: create a new terminal as a kitty window +The program passed as argument will be executed in the new terminal' \ +%{ + nop %sh{ + kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type sh -c "$*" + } +} -define-command -docstring %{kitty-new-tab []: create a new tab -All optional arguments are forwarded to the new kak client} \ - -params .. \ - -command-completion \ - kitty-new-tab %{ nop %sh{ - kitty @ new-window --no-response --new-tab "$(command -v kak 2>/dev/null)" -c "${kak_session}" -e "$*" -}} +define-command kitty-new -params .. -command-completion -docstring ' +kitty-new []: create a new kakoune client as a kitty window +The optional arguments are passed as commands to the new client' \ +%{ + kitty-terminal "kak -c %val{session} -e '%arg{@}'" +} -define-command -params ..1 -client-completion \ - -docstring %{kitty-focus []: focus the given client -If no client is passed then the current one is used} \ - kitty-focus %{ evaluate-commands %sh{ +define-command kitty-terminal-tab -params 1.. -shell-completion -docstring ' +kitty-terminal-tab []: create a new terminal as kitty tab +The program passed as argument will be executed in the new terminal' \ +%{ + nop %sh{ + kitty @ new-window --no-response --new-tab sh -c "$*" + } +} + +define-command kitty-new-tab -params .. -command-completion -docstring ' +kitty-new-tab []: create a new terminal as kitty tab +The optional arguments are passed as commands to the new client' \ +%{ + kitty-terminal-tab "kak -c %val{session} -e '%arg{@}'" +} + +define-command kitty-focus -params ..1 -client-completion -docstring ' +kitty-focus []: focus the given client +If no client is passed then the current one is used' \ +%{ + evaluate-commands %sh{ if [ $# -eq 1 ]; then - printf %s\\n "evaluate-commands -client '$1' focus" + printf "evaluate-commands -client '%s' focus" "$1" else kitty @ focus-tab --no-response -m=id:$kak_client_env_KITTY_WINDOW_ID kitty @ focus-window --no-response -m=id:$kak_client_env_KITTY_WINDOW_ID fi -}} + } +} -define-command -docstring %{kitty-repl []: create a new window for repl interaction -All optional parameters are forwarded to the new window} \ - -params .. \ - -shell-completion \ - kitty-repl %{ evaluate-commands %sh{ - if [ $# -eq 0 ]; then cmd="${SHELL:-/bin/sh}"; else cmd="$*"; fi +define-command kitty-repl -params .. -shell-completion -docstring ' +kitty-repl []: create a new window for repl interaction +All optional parameters are forwarded to the new window' \ +%{ + nop %sh{ + if [ $# -eq 0 ]; then + cmd="${SHELL:-/bin/sh}" + else + cmd="$*" + fi kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type --title kak_repl_window --cwd "$PWD" $cmd < /dev/null > /dev/null 2>&1 & -}} + } +} define-command kitty-send-text -docstring "send the selected text to the repl window" %{ nop %sh{ From 74d1dc756ae9738877734aff562470e71c047a47 Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Mon, 3 Dec 2018 19:35:35 +0100 Subject: [PATCH 2/7] Only accept one parameter to 'terminal' commands Also explicitly state that they're executed in a shell scope --- rc/base/screen.kak | 24 +++++++++++------------- rc/base/tmux.kak | 33 ++++++++++++++++----------------- rc/base/x11.kak | 10 +++++----- rc/extra/kitty.kak | 16 ++++++++-------- 4 files changed, 40 insertions(+), 43 deletions(-) diff --git a/rc/base/screen.kak b/rc/base/screen.kak index 4d13c375..5bf4292c 100644 --- a/rc/base/screen.kak +++ b/rc/base/screen.kak @@ -10,33 +10,31 @@ hook -group GNUscreen global KakBegin .* %sh{ " } -define-command screen-terminal-impl -hidden -params 3.. -command-completion %{ +define-command screen-terminal-impl -hidden -params 3 %{ nop %sh{ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" screen -X eval "$1" "$2" - shift 2 - cmd=$(printf %s "$*") - screen -X screen sh -c "${cmd}; screen -X remove" < "/dev/$tty" + screen -X screen sh -c "$3; screen -X remove" < "/dev/$tty" } } -define-command screen-terminal-vertical -params 1.. -command-completion -docstring ' -screen-terminal-vertical []: create a new terminal as a screen pane +define-command screen-terminal-vertical -params 1 -shell-completion -docstring ' +screen-terminal-vertical : create a new terminal as a screen pane The current pane is split into two, left and right -The program passed as argument will be executed in the new terminal' \ +The shell program passed as argument will be executed in the new terminal' \ %{ screen-terminal-impl 'split -v' 'focus right' %arg{@} } -define-command screen-terminal-horizontal -params 1.. -command-completion -docstring ' -screen-terminal-horizontal []: create a new terminal as a screen pane +define-command screen-terminal-horizontal -params 1 -shell-completion -docstring ' +screen-terminal-horizontal : create a new terminal as a screen pane The current pane is split into two, top and bottom -The program passed as argument will be executed in the new terminal' \ +The shell program passed as argument will be executed in the new terminal' \ %{ screen-terminal-impl 'split -h' 'focus down' %arg{@} } -define-command screen-terminal-window -params 1.. -command-completion -docstring ' -screen-terminal-window []: create a new terminal as a screen window -The program passed as argument will be executed in the new terminal' \ +define-command screen-terminal-window -params 1 -shell-completion -docstring ' +screen-terminal-window : create a new terminal as a screen window +The shell program passed as argument will be executed in the new terminal' \ %{ nop %sh{ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" diff --git a/rc/base/tmux.kak b/rc/base/tmux.kak index c587cdb9..b1d6beb5 100644 --- a/rc/base/tmux.kak +++ b/rc/base/tmux.kak @@ -12,7 +12,7 @@ hook global KakBegin .* %sh{ fi } -define-command -hidden -params 2.. tmux-terminal-impl %{ +define-command -hidden -params 2 tmux-terminal-impl %{ evaluate-commands %sh{ tmux=${kak_client_env_TMUX:-$TMUX} if [ -z "$tmux" ]; then @@ -20,30 +20,29 @@ define-command -hidden -params 2.. tmux-terminal-impl %{ exit fi tmux_args="$1" - shift - TMUX=$tmux tmux $tmux_args env TMPDIR="$TMPDIR" sh -c "$*" < /dev/null > /dev/null 2>&1 & + TMUX=$tmux tmux $tmux_args env TMPDIR="$TMPDIR" sh -c "$2" < /dev/null > /dev/null 2>&1 & } } -define-command tmux-terminal-vertical -params 1.. -shell-completion -docstring ' -tmux-terminal-vertical []: create a new terminal as a tmux pane +define-command tmux-terminal-vertical -params 1 -shell-completion -docstring ' +tmux-terminal-vertical : create a new terminal as a tmux pane The current pane is split into two, top and bottom -The program passed as argument will be executed in the new terminal' \ +The shell program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'split-window -v' %arg{@} + tmux-terminal-impl 'split-window -v' %arg{1} } -define-command tmux-terminal-horizontal -params 1.. -shell-completion -docstring ' -tmux-terminal-horizontal []: create a new terminal as a tmux pane +define-command tmux-terminal-horizontal -params 1 -shell-completion -docstring ' +tmux-terminal-horizontal : create a new terminal as a tmux pane The current pane is split into two, left and right -The program passed as argument will be executed in the new terminal' \ +The shell program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'split-window -h' %arg{@} + tmux-terminal-impl 'split-window -h' %arg{1} } -define-command tmux-terminal-window -params 1.. -shell-completion -docstring ' +define-command tmux-terminal-window -params 1 -shell-completion -docstring ' tmux-terminal-window []: create a new terminal as a tmux window -The program passed as argument will be executed in the new terminal' \ +The shell program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'new-window' %arg{@} + tmux-terminal-impl 'new-window' %arg{1} } define-command tmux-new-vertical -params .. -command-completion -docstring ' @@ -51,20 +50,20 @@ tmux-new-vertical []: create a new kakoune client as a tmux pane The current pane is split into two, top and bottom The optional arguments are passed as commands to the new client' \ %{ - tmux-terminal-vertical "kak -c %val{session} -e '%arg{@}'" + tmux-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" } define-command tmux-new-horizontal -params .. -command-completion -docstring ' tmux-new-horizontal []: create a new kakoune client as a tmux pane The current pane is split into two, left and right The optional arguments are passed as commands to the new client' \ %{ - tmux-terminal-horizontal "kak -c %val{session} -e '%arg{@}'" + tmux-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" } define-command tmux-new-window -params .. -command-completion -docstring ' tmux-new-window []: create a new kakoune client as a tmux window The optional arguments are passed as commands to the new client' \ %{ - tmux-terminal-window "kak -c %val{session} -e '%arg{@}'" + tmux-terminal-window "kak -c '%val{session}' -e '%arg{@}'" } define-command tmux-focus -params ..1 -client-completion -docstring ' diff --git a/rc/base/x11.kak b/rc/base/x11.kak index 9d5ee82e..c6f298d8 100644 --- a/rc/base/x11.kak +++ b/rc/base/x11.kak @@ -22,16 +22,16 @@ A shell command is appended to the one set in this option at runtime} \ done } -define-command x11-terminal -params 1.. -shell-completion -docstring ' -x11-terminal []: create a new terminal as an x11 window -The program passed as argument will be executed in the new terminal' \ +define-command x11-terminal -params 1 -shell-completion -docstring ' +x11-terminal : create a new terminal as an x11 window +The shell program passed as argument will be executed in the new terminal' \ %{ evaluate-commands %sh{ if [ -z "${kak_opt_termcmd}" ]; then echo "fail 'termcmd option is not set'" exit fi - setsid ${kak_opt_termcmd} "$*" < /dev/null > /dev/null 2>&1 & + setsid ${kak_opt_termcmd} "$1" < /dev/null > /dev/null 2>&1 & } } @@ -39,7 +39,7 @@ define-command x11-new -params .. -command-completion -docstring ' x11-new []: create a new kakoune client as an x11 window The optional arguments are passed as commands to the new client' \ %{ - x11-terminal "kak -c %val{session} -e '%arg{@}'" + x11-terminal "kak -c '%val{session}' -e '%arg{@}'" } define-command x11-focus -params ..1 -client-completion -docstring ' diff --git a/rc/extra/kitty.kak b/rc/extra/kitty.kak index c8533312..5f0bb24c 100644 --- a/rc/extra/kitty.kak +++ b/rc/extra/kitty.kak @@ -14,12 +14,12 @@ hook -group kitty-hooks global KakBegin .* %sh{ fi } -define-command kitty-terminal -params 1.. -shell-completion -docstring ' -kitty-terminal []: create a new terminal as a kitty window -The program passed as argument will be executed in the new terminal' \ +define-command kitty-terminal -params 1 -shell-completion -docstring ' +kitty-terminal : create a new terminal as a kitty window +The shell program passed as argument will be executed in the new terminal' \ %{ nop %sh{ - kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type sh -c "$*" + kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type sh -c "$1" } } @@ -30,12 +30,12 @@ The optional arguments are passed as commands to the new client' \ kitty-terminal "kak -c %val{session} -e '%arg{@}'" } -define-command kitty-terminal-tab -params 1.. -shell-completion -docstring ' -kitty-terminal-tab []: create a new terminal as kitty tab -The program passed as argument will be executed in the new terminal' \ +define-command kitty-terminal-tab -params 1 -shell-completion -docstring ' +kitty-terminal-tab : create a new terminal as kitty tab +The shell program passed as argument will be executed in the new terminal' \ %{ nop %sh{ - kitty @ new-window --no-response --new-tab sh -c "$*" + kitty @ new-window --no-response --new-tab sh -c "$1" } } From 84da1911bec3a20997ac3cc4af67aebb42ff84c6 Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Mon, 3 Dec 2018 19:53:30 +0100 Subject: [PATCH 3/7] Attempt to create iterm-terminal commands --- rc/extra/iterm.kak | 83 +++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/rc/extra/iterm.kak b/rc/extra/iterm.kak index b7fe5003..59bbe9d0 100644 --- a/rc/extra/iterm.kak +++ b/rc/extra/iterm.kak @@ -12,12 +12,10 @@ hook global KakBegin .* %sh{ fi } -define-command -hidden -params 1.. iterm-new-split-impl %{ +define-command -hidden -params 2 iterm-terminal-split-impl %{ nop %sh{ direction="$1" - shift - if [ $# -gt 0 ]; then kakoune_params="-e \\\"$*\\\""; fi - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' kak -c '${kak_session}' ${kakoune_params}" + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$2'" osascript \ -e "tell application \"iTerm\"" \ -e " tell current session of current window" \ @@ -27,21 +25,27 @@ define-command -hidden -params 1.. iterm-new-split-impl %{ } } -define-command iterm-new-vertical -params .. -command-completion -docstring "Split the current pane into two, top and bottom" %{ - iterm-new-split-impl 'vertically' %arg{@} +define-command iterm-terminal-vertical -params 1 -shell-completion -docstring ' +iterm-terminal-vertical : create a new terminal as an iterm pane +The current pane is split into two, top and bottom +The shell program passed as argument will be executed in the new terminal'\ +%{ + iterm-terminal-split-impl 'vertically' %arg{1} +} +define-command iterm-terminal-horizontal -params 1 -shell-completion -docstring ' +iterm-terminal-horizontal : create a new terminal as an iterm pane +The current pane is split into two, left and right +The shell program passed as argument will be executed in the new terminal'\ +%{ + iterm-terminal-split-impl 'horizontally' %arg{1} } -define-command iterm-new-horizontal -params .. -command-completion -docstring "Split the current pane into two, left and right" %{ - iterm-new-split-impl 'horizontally' %arg{@} -} - -define-command -params .. -command-completion \ - -docstring %{iterm-new-tab []: create a new tab -All optional arguments are forwarded to the new kak client} \ - iterm-new-tab %{ +define-command iterm-terminal-tab -params 1 -shell-completion -docstring ' +iterm-terminal-tab : create a new terminal as an iterm tab +The shell program passed as argument will be executed in the new terminal'\ +%{ nop %sh{ - if [ $# -gt 0 ]; then kakoune_params="-e \\\"$*\\\""; fi - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' kak -c '${kak_session}' ${kakoune_params}" + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$1'" osascript \ -e "tell application \"iTerm\"" \ -e " tell current window" \ @@ -51,13 +55,12 @@ All optional arguments are forwarded to the new kak client} \ } } -define-command -params .. -command-completion \ - -docstring %{iterm-new-window []: create a new window -All optional arguments are forwarded to the new kak client} \ - iterm-new-window %{ +define-command iterm-terminal-window -params 1 -shell-completion -docstring ' +iterm-terminal-window : create a new terminal as an iterm window +The shell program passed as argument will be executed in the new terminal'\ +%{ nop %sh{ - if [ $# -gt 0 ]; then kakoune_params="-e \\\"$*\\\""; fi - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' kak -c '${kak_session}' ${kakoune_params}" + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$1'" osascript \ -e "tell application \"iTerm\"" \ -e " create window with default profile command \"${cmd}\"" \ @@ -65,10 +68,38 @@ All optional arguments are forwarded to the new kak client} \ } } -define-command -params ..1 -client-completion \ - -docstring %{iterm-focus []: focus the given client -If no client is passed then the current one is used} \ - iterm-focus %{ evaluate-commands %sh{ +define-command iterm-new-vertical -params .. -command-completion -docstring ' +iterm-new-vertical : create a new kakoune client as an iterm pane +The current pane is split into two, top and bottom +The optional arguments are passed as commands to the new client' \ +%{ + iterm-terminal-vertical "kak -c %val{session} -e '%arg{@}'" +} +define-command iterm-new-horizontal -params .. -command-completion -docstring ' +iterm-new-horizontal : create a new kakoune client as an iterm pane +The current pane is split into two, left and right +The optional arguments are passed as commands to the new client' \ +%{ + iterm-terminal-horizontal "kak -c %val{session} -e '%arg{@}'" +} +define-command iterm-new-tab -params .. -command-completion -docstring ' +iterm-new-tab : create a new kakoune client as an iterm tab +The optional arguments are passed as commands to the new client' \ +%{ + iterm-terminal-tab "kak -c %val{session} -e '%arg{@}'" +} +define-command iterm-new-window -params .. -command-completion -docstring ' +iterm-new-window : create a new kakoune client as an iterm window +The optional arguments are passed as commands to the new client' \ +%{ + iterm-terminal-window "kak -c %val{session} -e '%arg{@}'" +} + +define-command iterm-focus -params ..1 -client-completion -docstring ' +iterm-focus []: focus the given client +If no client is passed then the current one is used' \ +%{ + evaluate-commands %sh{ if [ $# -eq 1 ]; then printf %s\\n "evaluate-commands -client '$1' focus" else From 3e4f3ed9d27dcc3abbf908f850ad59764fe47a6f Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Sat, 8 Dec 2018 16:57:30 +0100 Subject: [PATCH 4/7] Better handling of escaping in iterm.kak Thanks eraserhd --- rc/extra/iterm.kak | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/rc/extra/iterm.kak b/rc/extra/iterm.kak index 59bbe9d0..135de775 100644 --- a/rc/extra/iterm.kak +++ b/rc/extra/iterm.kak @@ -14,8 +14,10 @@ hook global KakBegin .* %sh{ define-command -hidden -params 2 iterm-terminal-split-impl %{ nop %sh{ + # replace ' with '\\'' in the command + escaped=$(printf %s "$2" | sed -e "s|'|'\\\\\\\\''|g") direction="$1" - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$2'" + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" osascript \ -e "tell application \"iTerm\"" \ -e " tell current session of current window" \ @@ -45,7 +47,8 @@ iterm-terminal-tab : create a new terminal as an iterm tab The shell program passed as argument will be executed in the new terminal'\ %{ nop %sh{ - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$1'" + escaped=$(printf %s "$1" | sed -e "s|'|'\\\\\\\\''|g") + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" osascript \ -e "tell application \"iTerm\"" \ -e " tell current window" \ @@ -60,7 +63,8 @@ iterm-terminal-window : create a new terminal as an iterm window The shell program passed as argument will be executed in the new terminal'\ %{ nop %sh{ - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$1'" + escaped=$(printf %s "$1" | sed -e "s|'|'\\\\\\\\''|g") + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" osascript \ -e "tell application \"iTerm\"" \ -e " create window with default profile command \"${cmd}\"" \ @@ -73,26 +77,26 @@ iterm-new-vertical : create a new kakoune client as an iterm pane The current pane is split into two, top and bottom The optional arguments are passed as commands to the new client' \ %{ - iterm-terminal-vertical "kak -c %val{session} -e '%arg{@}'" + iterm-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" } define-command iterm-new-horizontal -params .. -command-completion -docstring ' iterm-new-horizontal : create a new kakoune client as an iterm pane The current pane is split into two, left and right The optional arguments are passed as commands to the new client' \ %{ - iterm-terminal-horizontal "kak -c %val{session} -e '%arg{@}'" + iterm-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" } define-command iterm-new-tab -params .. -command-completion -docstring ' iterm-new-tab : create a new kakoune client as an iterm tab The optional arguments are passed as commands to the new client' \ %{ - iterm-terminal-tab "kak -c %val{session} -e '%arg{@}'" + iterm-terminal-tab "kak -c '%val{session}' -e '%arg{@}'" } define-command iterm-new-window -params .. -command-completion -docstring ' iterm-new-window : create a new kakoune client as an iterm window The optional arguments are passed as commands to the new client' \ %{ - iterm-terminal-window "kak -c %val{session} -e '%arg{@}'" + iterm-terminal-window "kak -c '%val{session}' -e '%arg{@}'" } define-command iterm-focus -params ..1 -client-completion -docstring ' From 02fa967476b0b38bfddea503e83a60ad7fe21bd9 Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Sun, 9 Dec 2018 10:03:30 +0100 Subject: [PATCH 5/7] Factor the 'new' commands out of their respective windowing systems --- rc/base/new-client.kak | 16 ++++++++++++++++ rc/base/screen.kak | 22 ---------------------- rc/base/tmux.kak | 22 ---------------------- rc/base/x11.kak | 8 -------- rc/extra/iterm.kak | 28 ---------------------------- rc/extra/kitty.kak | 16 ---------------- 6 files changed, 16 insertions(+), 96 deletions(-) create mode 100644 rc/base/new-client.kak diff --git a/rc/base/new-client.kak b/rc/base/new-client.kak new file mode 100644 index 00000000..4413d6e2 --- /dev/null +++ b/rc/base/new-client.kak @@ -0,0 +1,16 @@ +define-command new -params .. -command-completion -docstring ' +new []: create a new kakoune client +The ''terminal'' alias is being used to determine the user''s preferred terminal emulator +The optional arguments are passed as commands to the new client' \ +%{ + try %{ + terminal %sh{ + # double-up single-quotes + escaped=$(printf %s "$*" | sed -e "s|'|''|g") + printf "kak -c '%s' -e '%s'" "$kak_session" "$escaped" + } + } catch %{ + fail "The 'terminal' alias must be defined to use this command" + } +} + diff --git a/rc/base/screen.kak b/rc/base/screen.kak index 5bf4292c..dca8c5be 100644 --- a/rc/base/screen.kak +++ b/rc/base/screen.kak @@ -5,7 +5,6 @@ hook -group GNUscreen global KakBegin .* %sh{ [ -z "${STY}" ] && exit echo " alias global focus screen-focus - alias global new screen-new-vertical alias global terminal screen-terminal-vertical " } @@ -42,27 +41,6 @@ The shell program passed as argument will be executed in the new terminal' \ } } -define-command screen-new-vertical -params .. -command-completion -docstring ' -screen-new-vertical []: create a new kakoune client as a screen pane -The current pane is split into two, left and right -The optional arguments are passed as commands to the new client' \ -%{ - screen-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" -} -define-command screen-new-horizontal -params .. -command-completion -docstring ' -screen-new-horizontal []: create a new kakoune client as a screen pane -The current pane is split into two, top and bottom -The optional arguments are passed as commands to the new client' \ -%{ - screen-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" -} -define-command screen-new-window -params .. -command-completion -docstring ' -screen-new-window []: create a new kakoune client as a screen window -The optional arguments are passed as commands to the new client' \ -%{ - screen-terminal-window "kak -c '%val{session}' -e '%arg{@}'" -} - define-command screen-focus -params ..1 -client-completion -docstring ' screen-focus []: focus the given client If no client is passed then the current one is used' \ diff --git a/rc/base/tmux.kak b/rc/base/tmux.kak index b1d6beb5..23a381e2 100644 --- a/rc/base/tmux.kak +++ b/rc/base/tmux.kak @@ -6,7 +6,6 @@ hook global KakBegin .* %sh{ if [ -n "$TMUX" ]; then echo " alias global focus tmux-focus - alias global new tmux-new-horizontal alias global terminal tmux-terminal-horizontal " fi @@ -45,27 +44,6 @@ The shell program passed as argument will be executed in the new terminal' \ tmux-terminal-impl 'new-window' %arg{1} } -define-command tmux-new-vertical -params .. -command-completion -docstring ' -tmux-new-vertical []: create a new kakoune client as a tmux pane -The current pane is split into two, top and bottom -The optional arguments are passed as commands to the new client' \ -%{ - tmux-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" -} -define-command tmux-new-horizontal -params .. -command-completion -docstring ' -tmux-new-horizontal []: create a new kakoune client as a tmux pane -The current pane is split into two, left and right -The optional arguments are passed as commands to the new client' \ -%{ - tmux-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" -} -define-command tmux-new-window -params .. -command-completion -docstring ' -tmux-new-window []: create a new kakoune client as a tmux window -The optional arguments are passed as commands to the new client' \ -%{ - tmux-terminal-window "kak -c '%val{session}' -e '%arg{@}'" -} - define-command tmux-focus -params ..1 -client-completion -docstring ' tmux-focus []: focus the given client If no client is passed then the current one is used' \ diff --git a/rc/base/x11.kak b/rc/base/x11.kak index c6f298d8..fea97bbd 100644 --- a/rc/base/x11.kak +++ b/rc/base/x11.kak @@ -35,13 +35,6 @@ The shell program passed as argument will be executed in the new terminal' \ } } -define-command x11-new -params .. -command-completion -docstring ' -x11-new []: create a new kakoune client as an x11 window -The optional arguments are passed as commands to the new client' \ -%{ - x11-terminal "kak -c '%val{session}' -e '%arg{@}'" -} - define-command x11-focus -params ..1 -client-completion -docstring ' x11-focus []: focus a given client''s window If no client is passed, then the current client is used' \ @@ -56,5 +49,4 @@ If no client is passed, then the current client is used' \ } alias global focus x11-focus -alias global new x11-new alias global terminal x11-terminal diff --git a/rc/extra/iterm.kak b/rc/extra/iterm.kak index 135de775..65fdc3dc 100644 --- a/rc/extra/iterm.kak +++ b/rc/extra/iterm.kak @@ -6,7 +6,6 @@ hook global KakBegin .* %sh{ if [ "$TERM_PROGRAM" = "iTerm.app" ] && [ -z "$TMUX" ]; then echo " - alias global new iterm-new-vertical alias global focus iterm-focus " fi @@ -72,33 +71,6 @@ The shell program passed as argument will be executed in the new terminal'\ } } -define-command iterm-new-vertical -params .. -command-completion -docstring ' -iterm-new-vertical : create a new kakoune client as an iterm pane -The current pane is split into two, top and bottom -The optional arguments are passed as commands to the new client' \ -%{ - iterm-terminal-vertical "kak -c '%val{session}' -e '%arg{@}'" -} -define-command iterm-new-horizontal -params .. -command-completion -docstring ' -iterm-new-horizontal : create a new kakoune client as an iterm pane -The current pane is split into two, left and right -The optional arguments are passed as commands to the new client' \ -%{ - iterm-terminal-horizontal "kak -c '%val{session}' -e '%arg{@}'" -} -define-command iterm-new-tab -params .. -command-completion -docstring ' -iterm-new-tab : create a new kakoune client as an iterm tab -The optional arguments are passed as commands to the new client' \ -%{ - iterm-terminal-tab "kak -c '%val{session}' -e '%arg{@}'" -} -define-command iterm-new-window -params .. -command-completion -docstring ' -iterm-new-window : create a new kakoune client as an iterm window -The optional arguments are passed as commands to the new client' \ -%{ - iterm-terminal-window "kak -c '%val{session}' -e '%arg{@}'" -} - define-command iterm-focus -params ..1 -client-completion -docstring ' iterm-focus []: focus the given client If no client is passed then the current one is used' \ diff --git a/rc/extra/kitty.kak b/rc/extra/kitty.kak index 5f0bb24c..56931423 100644 --- a/rc/extra/kitty.kak +++ b/rc/extra/kitty.kak @@ -3,8 +3,6 @@ declare-option -docstring %{window type that kitty creates on new and repl calls hook -group kitty-hooks global KakBegin .* %sh{ if [ "$TERM" = "xterm-kitty" ] && [ -z "$TMUX" ]; then echo " - alias global new kitty-new - alias global new-tab kitty-new-tab alias global terminal kitty-terminal alias global terminal-tab kitty-terminal-tab alias global focus kitty-focus @@ -23,13 +21,6 @@ The shell program passed as argument will be executed in the new terminal' \ } } -define-command kitty-new -params .. -command-completion -docstring ' -kitty-new []: create a new kakoune client as a kitty window -The optional arguments are passed as commands to the new client' \ -%{ - kitty-terminal "kak -c %val{session} -e '%arg{@}'" -} - define-command kitty-terminal-tab -params 1 -shell-completion -docstring ' kitty-terminal-tab : create a new terminal as kitty tab The shell program passed as argument will be executed in the new terminal' \ @@ -39,13 +30,6 @@ The shell program passed as argument will be executed in the new terminal' \ } } -define-command kitty-new-tab -params .. -command-completion -docstring ' -kitty-new-tab []: create a new terminal as kitty tab -The optional arguments are passed as commands to the new client' \ -%{ - kitty-terminal-tab "kak -c %val{session} -e '%arg{@}'" -} - define-command kitty-focus -params ..1 -client-completion -docstring ' kitty-focus []: focus the given client If no client is passed then the current one is used' \ From 5146f7ba338801bff9bef9c4c89ffb59c5aca291 Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Fri, 21 Dec 2018 18:14:28 +0100 Subject: [PATCH 6/7] Rework 'terminal' commands * Arguments of the kakoune command are now preserved in the shell call * Escaping logic is moved from 'new' to 'terminal' --- rc/base/new-client.kak | 6 +--- rc/base/screen.kak | 35 ++++++++++++++------- rc/base/tmux.kak | 31 +++++++++--------- rc/base/x11.kak | 28 ++++++++++++++--- rc/extra/iterm.kak | 71 +++++++++++++++++++++++++++++++----------- rc/extra/kitty.kak | 16 +++++----- 6 files changed, 125 insertions(+), 62 deletions(-) diff --git a/rc/base/new-client.kak b/rc/base/new-client.kak index 4413d6e2..6ec538a9 100644 --- a/rc/base/new-client.kak +++ b/rc/base/new-client.kak @@ -4,11 +4,7 @@ The ''terminal'' alias is being used to determine the user''s preferred terminal The optional arguments are passed as commands to the new client' \ %{ try %{ - terminal %sh{ - # double-up single-quotes - escaped=$(printf %s "$*" | sed -e "s|'|''|g") - printf "kak -c '%s' -e '%s'" "$kak_session" "$escaped" - } + terminal kak -c %val{session} -e "%arg{@}" } catch %{ fail "The 'terminal' alias must be defined to use this command" } diff --git a/rc/base/screen.kak b/rc/base/screen.kak index dca8c5be..e4ddd2e9 100644 --- a/rc/base/screen.kak +++ b/rc/base/screen.kak @@ -9,35 +9,46 @@ hook -group GNUscreen global KakBegin .* %sh{ " } -define-command screen-terminal-impl -hidden -params 3 %{ +define-command screen-terminal-impl -hidden -params 3.. %{ nop %sh{ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" screen -X eval "$1" "$2" - screen -X screen sh -c "$3; screen -X remove" < "/dev/$tty" + shift 2 + # see x11.kak for what this achieves + args=$( + for i in "$@"; do + if [ "$i" = '' ]; then + printf "'' " + else + printf %s "$i" | sed -e "s|'|'\\\\''|g; s|^|'|; s|$|' |" + fi + done + ) + screen -X screen sh -c "${args} ; screen -X remove" < "/dev/$tty" } } -define-command screen-terminal-vertical -params 1 -shell-completion -docstring ' -screen-terminal-vertical : create a new terminal as a screen pane +define-command screen-terminal-vertical -params 1.. -shell-completion -docstring ' +screen-terminal-vertical [] []: create a new terminal as a screen pane The current pane is split into two, left and right -The shell program passed as argument will be executed in the new terminal' \ +The program passed as argument will be executed in the new terminal' \ %{ screen-terminal-impl 'split -v' 'focus right' %arg{@} } -define-command screen-terminal-horizontal -params 1 -shell-completion -docstring ' -screen-terminal-horizontal : create a new terminal as a screen pane +define-command screen-terminal-horizontal -params 1.. -shell-completion -docstring ' +screen-terminal-horizontal []: create a new terminal as a screen pane The current pane is split into two, top and bottom -The shell program passed as argument will be executed in the new terminal' \ +The program passed as argument will be executed in the new terminal' \ %{ screen-terminal-impl 'split -h' 'focus down' %arg{@} } -define-command screen-terminal-window -params 1 -shell-completion -docstring ' -screen-terminal-window : create a new terminal as a screen window -The shell program passed as argument will be executed in the new terminal' \ +define-command screen-terminal-window -params 1.. -shell-completion -docstring ' +screen-terminal-window []: create a new terminal as a screen window +The program passed as argument will be executed in the new terminal' \ %{ nop %sh{ tty="$(ps -o tty ${kak_client_pid} | tail -n 1)" - screen -X screen sh -c "$*" < "/dev/$tty" + screen -X screen "$@" < "/dev/$tty" } } diff --git a/rc/base/tmux.kak b/rc/base/tmux.kak index 23a381e2..acc5c097 100644 --- a/rc/base/tmux.kak +++ b/rc/base/tmux.kak @@ -11,7 +11,7 @@ hook global KakBegin .* %sh{ fi } -define-command -hidden -params 2 tmux-terminal-impl %{ +define-command -hidden -params 2.. tmux-terminal-impl %{ evaluate-commands %sh{ tmux=${kak_client_env_TMUX:-$TMUX} if [ -z "$tmux" ]; then @@ -19,29 +19,32 @@ define-command -hidden -params 2 tmux-terminal-impl %{ exit fi tmux_args="$1" - TMUX=$tmux tmux $tmux_args env TMPDIR="$TMPDIR" sh -c "$2" < /dev/null > /dev/null 2>&1 & + shift + # ideally we should escape single ';' to stop tmux from interpreting it as a new command + # but that's probably too rare to care + TMUX=$tmux tmux $tmux_args env TMPDIR="$TMPDIR" "$@" < /dev/null > /dev/null 2>&1 & } } -define-command tmux-terminal-vertical -params 1 -shell-completion -docstring ' -tmux-terminal-vertical : create a new terminal as a tmux pane +define-command tmux-terminal-vertical -params 1.. -shell-completion -docstring ' +tmux-terminal-vertical []: create a new terminal as a tmux pane The current pane is split into two, top and bottom -The shell program passed as argument will be executed in the new terminal' \ +The program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'split-window -v' %arg{1} + tmux-terminal-impl 'split-window -v' %arg{@} } -define-command tmux-terminal-horizontal -params 1 -shell-completion -docstring ' -tmux-terminal-horizontal : create a new terminal as a tmux pane +define-command tmux-terminal-horizontal -params 1.. -shell-completion -docstring ' +tmux-terminal-horizontal []: create a new terminal as a tmux pane The current pane is split into two, left and right -The shell program passed as argument will be executed in the new terminal' \ +The program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'split-window -h' %arg{1} + tmux-terminal-impl 'split-window -h' %arg{@} } -define-command tmux-terminal-window -params 1 -shell-completion -docstring ' -tmux-terminal-window []: create a new terminal as a tmux window -The shell program passed as argument will be executed in the new terminal' \ +define-command tmux-terminal-window -params 1.. -shell-completion -docstring ' +tmux-terminal-window [] []: create a new terminal as a tmux window +The program passed as argument will be executed in the new terminal' \ %{ - tmux-terminal-impl 'new-window' %arg{1} + tmux-terminal-impl 'new-window' %arg{@} } define-command tmux-focus -params ..1 -client-completion -docstring ' diff --git a/rc/base/x11.kak b/rc/base/x11.kak index fea97bbd..9885aa9b 100644 --- a/rc/base/x11.kak +++ b/rc/base/x11.kak @@ -22,16 +22,36 @@ A shell command is appended to the one set in this option at runtime} \ done } -define-command x11-terminal -params 1 -shell-completion -docstring ' -x11-terminal : create a new terminal as an x11 window -The shell program passed as argument will be executed in the new terminal' \ +define-command x11-terminal -params 1.. -shell-completion -docstring ' +x11-terminal []: create a new terminal as an x11 window +The program passed as argument will be executed in the new terminal' \ %{ evaluate-commands %sh{ if [ -z "${kak_opt_termcmd}" ]; then echo "fail 'termcmd option is not set'" exit fi - setsid ${kak_opt_termcmd} "$1" < /dev/null > /dev/null 2>&1 & + # join arguments into a single string, in which they're delimited + # by single quotes, and with single quotes inside transformed to '\'' + # so that sh -c "$args" will re-split the arguments properly + # example: + # $1 = ab + # $2 = foo bar + # $3 = + # $4 = foo'bar + # $args = 'ab' 'foo bar' '' 'foo'\''bar' + # would be nicer to do in a single sed/awk call but that's difficult + args=$( + for i in "$@"; do + # special case to preserve empty variables as sed won't touch these + if [ "$i" = '' ]; then + printf "'' " + else + printf %s "$i" | sed -e "s|'|'\\\\''|g; s|^|'|; s|$|' |" + fi + done + ) + setsid ${kak_opt_termcmd} "$args" < /dev/null > /dev/null 2>&1 & } } diff --git a/rc/extra/iterm.kak b/rc/extra/iterm.kak index 65fdc3dc..c7e7b961 100644 --- a/rc/extra/iterm.kak +++ b/rc/extra/iterm.kak @@ -11,12 +11,25 @@ hook global KakBegin .* %sh{ fi } -define-command -hidden -params 2 iterm-terminal-split-impl %{ +define-command -hidden -params 2.. iterm-terminal-split-impl %{ nop %sh{ - # replace ' with '\\'' in the command - escaped=$(printf %s "$2" | sed -e "s|'|'\\\\\\\\''|g") direction="$1" - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" + shift + # join the arguments as one string for the shell execution (see x11.kak) + args=$( + for i in "$@"; do + if [ "$i" = '' ]; then + printf "'' " + else + printf %s "$i" | sed -e "s|'|'\\\\''|g; s|^|'|; s|$|' |" + fi + done + ) + # go through another round of escaping for osascript + # \ -> \\ + # " -> \" + escaped=$(printf %s "$args" | sed -e 's|\|\\\\|g; s|"|\\"|g') + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' $escaped" osascript \ -e "tell application \"iTerm\"" \ -e " tell current session of current window" \ @@ -26,28 +39,38 @@ define-command -hidden -params 2 iterm-terminal-split-impl %{ } } -define-command iterm-terminal-vertical -params 1 -shell-completion -docstring ' -iterm-terminal-vertical : create a new terminal as an iterm pane +define-command iterm-terminal-vertical -params 1.. -shell-completion -docstring ' +iterm-terminal-vertical []: create a new terminal as an iterm pane The current pane is split into two, top and bottom -The shell program passed as argument will be executed in the new terminal'\ +The program passed as argument will be executed in the new terminal'\ %{ iterm-terminal-split-impl 'vertically' %arg{1} } -define-command iterm-terminal-horizontal -params 1 -shell-completion -docstring ' -iterm-terminal-horizontal : create a new terminal as an iterm pane +define-command iterm-terminal-horizontal -params 1.. -shell-completion -docstring ' +iterm-terminal-horizontal []: create a new terminal as an iterm pane The current pane is split into two, left and right -The shell program passed as argument will be executed in the new terminal'\ +The program passed as argument will be executed in the new terminal'\ %{ iterm-terminal-split-impl 'horizontally' %arg{1} } -define-command iterm-terminal-tab -params 1 -shell-completion -docstring ' -iterm-terminal-tab : create a new terminal as an iterm tab -The shell program passed as argument will be executed in the new terminal'\ +define-command iterm-terminal-tab -params 1.. -shell-completion -docstring ' +iterm-terminal-tab []: create a new terminal as an iterm tab +The program passed as argument will be executed in the new terminal'\ %{ nop %sh{ - escaped=$(printf %s "$1" | sed -e "s|'|'\\\\\\\\''|g") - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" + # see above + args=$( + for i in "$@"; do + if [ "$i" = '' ]; then + printf "'' " + else + printf %s "$i" | sed -e "s|'|'\\\\''|g; s|^|'|; s|$|' |" + fi + done + ) + escaped=$(printf %s "$args" | sed -e 's|\|\\\\|g; s|"|\\"|g') + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' $escaped" osascript \ -e "tell application \"iTerm\"" \ -e " tell current window" \ @@ -58,12 +81,22 @@ The shell program passed as argument will be executed in the new terminal'\ } define-command iterm-terminal-window -params 1 -shell-completion -docstring ' -iterm-terminal-window : create a new terminal as an iterm window -The shell program passed as argument will be executed in the new terminal'\ +iterm-terminal-window []: create a new terminal as an iterm window +The program passed as argument will be executed in the new terminal'\ %{ nop %sh{ - escaped=$(printf %s "$1" | sed -e "s|'|'\\\\\\\\''|g") - cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' sh -c '$escaped'" + # see above + args=$( + for i in "$@"; do + if [ "$i" = '' ]; then + printf "'' " + else + printf %s "$i" | sed -e "s|'|'\\\\''|g; s|^|'|; s|$|' |" + fi + done + ) + escaped=$(printf %s "$args" | sed -e 's|\|\\\\|g; s|"|\\"|g') + cmd="env PATH='${PATH}' TMPDIR='${TMPDIR}' $escaped" osascript \ -e "tell application \"iTerm\"" \ -e " create window with default profile command \"${cmd}\"" \ diff --git a/rc/extra/kitty.kak b/rc/extra/kitty.kak index 56931423..79583945 100644 --- a/rc/extra/kitty.kak +++ b/rc/extra/kitty.kak @@ -12,21 +12,21 @@ hook -group kitty-hooks global KakBegin .* %sh{ fi } -define-command kitty-terminal -params 1 -shell-completion -docstring ' -kitty-terminal : create a new terminal as a kitty window -The shell program passed as argument will be executed in the new terminal' \ +define-command kitty-terminal -params 1.. -shell-completion -docstring ' +kitty-terminal []: create a new terminal as a kitty window +The program passed as argument will be executed in the new terminal' \ %{ nop %sh{ - kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type sh -c "$1" + kitty @ new-window --no-response --window-type $kak_opt_kitty_window_type "$@" } } -define-command kitty-terminal-tab -params 1 -shell-completion -docstring ' -kitty-terminal-tab : create a new terminal as kitty tab -The shell program passed as argument will be executed in the new terminal' \ +define-command kitty-terminal-tab -params 1.. -shell-completion -docstring ' +kitty-terminal-tab []: create a new terminal as kitty tab +The program passed as argument will be executed in the new terminal' \ %{ nop %sh{ - kitty @ new-window --no-response --new-tab sh -c "$1" + kitty @ new-window --no-response --new-tab "$@" } } From eebc8c2f7d14b4500241bbdccd777b7839777c63 Mon Sep 17 00:00:00 2001 From: Olivier Perret Date: Sat, 22 Dec 2018 10:32:25 +0100 Subject: [PATCH 7/7] Fix a couple of mistakes in iterm.kak --- rc/extra/iterm.kak | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rc/extra/iterm.kak b/rc/extra/iterm.kak index c7e7b961..fe32f664 100644 --- a/rc/extra/iterm.kak +++ b/rc/extra/iterm.kak @@ -44,14 +44,14 @@ iterm-terminal-vertical []: create a new terminal as an ite The current pane is split into two, top and bottom The program passed as argument will be executed in the new terminal'\ %{ - iterm-terminal-split-impl 'vertically' %arg{1} + iterm-terminal-split-impl 'vertically' %arg{@} } define-command iterm-terminal-horizontal -params 1.. -shell-completion -docstring ' iterm-terminal-horizontal []: create a new terminal as an iterm pane The current pane is split into two, left and right The program passed as argument will be executed in the new terminal'\ %{ - iterm-terminal-split-impl 'horizontally' %arg{1} + iterm-terminal-split-impl 'horizontally' %arg{@} } define-command iterm-terminal-tab -params 1.. -shell-completion -docstring ' @@ -80,7 +80,7 @@ The program passed as argument will be executed in the new terminal'\ } } -define-command iterm-terminal-window -params 1 -shell-completion -docstring ' +define-command iterm-terminal-window -params 1.. -shell-completion -docstring ' iterm-terminal-window []: create a new terminal as an iterm window The program passed as argument will be executed in the new terminal'\ %{