Merge branch 'sh-support' into develop

Closes #928
This commit is contained in:
ZyX 2014-07-20 02:07:20 +04:00
commit e72ca9d775
17 changed files with 439 additions and 13 deletions

View File

@ -132,3 +132,10 @@ To get rid of these lags there currently are two options:
the future.
* Compile and install ``libzpython`` module that lives in
https://bitbucket.org/ZyX_I/zpython. This variant is zsh-specific.
Prompt is spoiled after completing files in ksh
-----------------------------------------------
This is exactly why powerline has official mksh support, but not official ksh
support. If you know the solution feel free to share it in `powerline bug
tracker <https://github.com/Lokaltog/powerline/issues/new>`_.

View File

@ -166,6 +166,38 @@ is the absolute path to your Powerline installation directory:
.. _tmux-statusline:
Busybox (ash), mksh and dash prompt
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
After launching busybox run the following command:
.. code-block:: bash
. {repository_root}/powerline/bindings/shell/powerline.sh
Mksh users may put this line into ``~/.mkshrc`` file. Dash users may use the
following in ``~/.profile``:
.. code-block:: bash
if test "x$0" != "x${0#dash}" ; then
export ENV={repository_root}/powerline/bindings/shell/powerline.sh
fi
.. note::
Dash users that already have ``$ENV`` defined should either put the ``.
…/shell/powerline.sh`` line in the ``$ENV`` file or create a new file which
will source (using ``.`` command) both former ``$ENV`` file and
:file:`powerline.sh` files and set ``$ENV`` to the path of this new file.
.. warning::
Job count is using some weird hack that uses signals and temporary files for
interprocess communication. It may be wrong sometimes. Not the case in mksh.
.. warning::
Busybox has two shells: ``ash`` and ``hush``. Second is known to segfault in
busybox 1.22.1 when using :file:`powerline.sh` script.
Tmux statusline
---------------

View File

@ -0,0 +1,181 @@
_powerline_columns_fallback() {
if which stty >/dev/null ; then
# Ksh does not have “local” built-in
_powerline_cols="$(stty size 2>/dev/null)"
if ! test -z "$_powerline_cols" ; then
echo "${_powerline_cols#* }"
return 0
fi
fi
echo 0
return 0
}
_powerline_has_jobs_in_subshell() {
if test -n "$_POWERLINE_HAS_JOBS_IN_SUBSHELL" ; then
return $_POWERLINE_HAS_JOBS_IN_SUBSHELL
elif test -z "$1" ; then
sleep 1 &
# Check whether shell outputs anything in a subshell when using jobs
# built-in. Shells like dash will not output anything meaning that
# I have to bother with temporary files.
test "$(jobs -p|wc -l)" -gt 0
else
case "$1" in
dash|bb|ash) return 1 ;;
mksh|ksh|bash) return 0 ;;
*) _powerline_has_jobs_in_subshell ;;
esac
fi
_POWERLINE_HAS_JOBS_IN_SUBSHELL=$?
return $_POWERLINE_HAS_JOBS_IN_SUBSHELL
}
_powerline_set_append_trap() {
if _powerline_has_jobs_in_subshell "$@" ; then
_powerline_append_trap() {
# Arguments: command, signal
# Ksh does not have “local” built-in
_powerline_traps="$(trap)"
if echo "$_powerline_traps" | grep -cm1 $2'$' >/dev/null ; then
_powerline_traps="$(echo "$_powerline_traps" | sed "s/ $2/'\\n$1' $2/")"
eval "$_powerline_traps"
fi
}
else
_powerline_append_trap() {
# Arguments: command, signal
_powerline_create_temp
trap > $_POWERLINE_TEMP
if grep -cm1 $2'$' $_POWERLINE_TEMP >/dev/null ; then
sed -i -e "s/ $2/'\\n$1' $2/"
. $_POWERLINE_TEMP
else
trap "$1" $2
fi
echo -n > $_POWERLINE_TEMP
}
fi
_powerline_set_append_trap() {
return 0
}
}
_powerline_create_temp() {
if test -z "$_POWERLINE_TEMP" || ! test -e "$_POWERLINE_TEMP" ; then
_POWERLINE_TEMP="$(mktemp)"
_powerline_append_trap 'rm $_POWERLINE_TEMP' EXIT
fi
}
_powerline_set_set_jobs() {
if _powerline_has_jobs_in_subshell "$@" ; then
_powerline_set_jobs() {
_POWERLINE_JOBS="$(jobs -p|wc -l)"
}
else
_powerline_set_append_trap "$@"
_POWERLINE_PID=$$
_powerline_append_trap '_powerline_do_set_jobs' USR1
_powerline_do_set_jobs() {
_powerline_create_temp
jobs -p > $_POWERLINE_TEMP
}
# This command will always be launched from a subshell, thus a hack is
# needed to run `jobs -p` outside of the subshell.
_powerline_set_jobs() {
kill -USR1 $_POWERLINE_PID
# Note: most likely this will read data from the previous run. Tests
# show that it is OK for some reasons.
_POWERLINE_JOBS="$(wc -l < $_POWERLINE_TEMP)"
}
fi
_powerline_set_set_jobs() {
return 0
}
}
_powerline_set_command() {
if test -z "${POWERLINE_COMMAND}" ; then
if which powerline-client >/dev/null ; then
export POWERLINE_COMMAND=powerline-client
elif which powerline >/dev/null ; then
export POWERLINE_COMMAND=powerline
else
# `$0` is set to `-bash` when using SSH so that won't work
export POWERLINE_COMMAND="$(dirname "$BASH_SOURCE")/../../../scripts/powerline"
fi
fi
}
_powerline_tmux_setenv() {
TMUX="$_POWERLINE_TMUX" tmux setenv -g TMUX_"$1"_`tmux display -p "#D" | tr -d %` "$2"
TMUX="$_POWERLINE_TMUX" tmux refresh -S
}
_powerline_tmux_set_pwd() {
if test "x$_POWERLINE_SAVED_PWD" != "x$PWD" ; then
_POWERLINE_SAVED_PWD="$PWD"
_powerline_tmux_setenv PWD "$PWD"
fi
}
_powerline_tmux_set_columns() {
_powerline_tmux_setenv COLUMNS "${COLUMNS:-$(_powerline_columns_fallback)}"
}
_powerline_set_renderer_arg() {
case "$1" in
bb|ash) _POWERLINE_RENDERER_ARG="-rbash_prompt" ;;
mksh|ksh) _POWERLINE_RENDERER_ARG="-rksh_prompt" ;;
bash|dash) _POWERLINE_RENDERER_ARG= ;;
esac
}
_powerline_set_jobs() {
_powerline_set_set_jobs
_powerline_set_jobs
}
_powerline_prompt() {
# Arguments: side, exit_code
_powerline_set_jobs
$POWERLINE_COMMAND shell $1 -w "${COLUMNS:-$(_powerline_columns_fallback)}" $_POWERLINE_RENDERER_ARG --last_exit_code=$2 --jobnum=$_POWERLINE_JOBS
}
_powerline_setup_prompt() {
VIRTUAL_ENV_DISABLE_PROMPT=1
_powerline_set_append_trap "$@"
_powerline_set_set_jobs "$@"
_powerline_set_command "$@"
_powerline_set_renderer_arg "$@"
PS1='$(_powerline_prompt aboveleft $?)'
}
_powerline_init_tmux_support() {
# Dash does not have &>/dev/null
if test -n "$TMUX" && tmux refresh -S >/dev/null 2>/dev/null ; then
# TMUX variable may be unset to create new tmux session inside this one
_POWERLINE_TMUX="$TMUX"
_powerline_set_append_trap "$@"
# If _powerline_tmux_set_pwd is used before _powerline_prompt it sets $?
# to zero in ksh.
PS1="$PS1"'$(_powerline_tmux_set_pwd)'
_powerline_append_trap '_powerline_tmux_set_columns' WINCH
_powerline_tmux_set_columns
fi
}
# Strips the leading `-`: it may be present when shell is a login shell
_POWERLINE_USED_SHELL=${0#-}
_POWERLINE_USED_SHELL=${_POWERLINE_USED_SHELL#/usr}
_POWERLINE_USED_SHELL=${_POWERLINE_USED_SHELL#/bin/}
if test -z "$POWERLINE_NO_BB_PROMPT$POWERLINE_NO_SHELL_PROMPT" ; then
_powerline_setup_prompt $_POWERLINE_USED_SHELL
fi
if test -z "$POWERLINE_NO_BB_TMUX_SUPPORT$POWERLINE_NO_SHELL_TMUX_SUPPORT" ; then
_powerline_init_tmux_support $_POWERLINE_USED_SHELL
fi

View File

@ -0,0 +1,20 @@
# vim:fileencoding=utf-8:noet
from __future__ import absolute_import, unicode_literals
from powerline.renderers.shell import ShellRenderer
ESCAPE_CHAR = '\001'
class KshPromptRenderer(ShellRenderer):
'''Powerline bash prompt segment renderer.'''
escape_hl_start = '\001'
escape_hl_end = '\001'
def render(self, *args, **kwargs):
return '\001\r' + super(KshPromptRenderer, self).render(*args, **kwargs)
renderer = KshPromptRenderer

View File

@ -12,7 +12,7 @@ if python -c 'import sys; sys.exit(1 * (sys.version_info[0] != 2))' ; then
pip install unittest2 argparse
fi
fi
sudo apt-get install -qq screen zsh tcsh
sudo apt-get install -qq screen zsh tcsh mksh busybox
# Travis has too outdated fish. It cannot be used for tests.
# sudo apt-get install fish
true

View File

@ -20,7 +20,7 @@ for script in tests/*.vim ; do
FAILED=1
fi
done
if ! sh tests/test_shells/test.sh ; then
if ! bash tests/test_shells/test.sh ; then
echo "Failed shells"
if ${PYTHON} -c 'import platform, sys; sys.exit(1 * (platform.python_implementation() == "PyPy"))' ; then
FAILED=1

17
tests/test_shells/bb.ok Normal file
View File

@ -0,0 +1,17 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
[1]+ Terminated bash -c "echo \$\$>pid ; while true ; do sleep 0.1s ; done"
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  false

17
tests/test_shells/dash.ok Normal file
View File

@ -0,0 +1,17 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1s
[1] + Terminated bash -c "echo \$\$>pid ; while true ; do sleep 0.1s ; done"
cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1    HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  false

View File

@ -1,7 +1,7 @@
POWERLINE_COMMAND="$PWD/scripts/powerline -p $PWD/powerline/config_files"
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
VIRTUAL_ENV=
export VIRTUAL_ENV=
source powerline/bindings/bash/powerline.sh ; cd tests/shell/3rd
cd .git
cd ..

View File

@ -0,0 +1,23 @@
POWERLINE_COMMAND="$PWD/scripts/powerline -p $PWD/powerline/config_files"
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
export VIRTUAL_ENV=
. powerline/bindings/shell/powerline.sh ; cd tests/shell/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
VIRTUAL_ENV=
bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
false
kill `cat pid` ; sleep 1s
cd "$DIR1"
cd ../"$DIR2"
cd ../'\[\]'
cd ../'%%'
cd ../'#[bold]'
cd ../'(echo)'
cd ../'$(echo)'
cd ../'`echo`'
false
true is the last line
exit

View File

@ -0,0 +1,23 @@
POWERLINE_COMMAND="$PWD/scripts/powerline -p $PWD/powerline/config_files"
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
export VIRTUAL_ENV=
. powerline/bindings/shell/powerline.sh ; cd tests/shell/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
VIRTUAL_ENV=
bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
false
kill `cat pid` ; sleep 1s
cd "$DIR1"
cd ../"$DIR2"
cd ../'\[\]'
cd ../'%%'
cd ../'#[bold]'
cd ../'(echo)'
cd ../'$(echo)'
cd ../'`echo`'
false
true is the last line
exit

View File

@ -1,13 +1,13 @@
set POWERLINE_COMMAND "$PWD/scripts/powerline -p $PWD/powerline/config_files"
set POWERLINE_COMMAND "$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
set POWERLINE_COMMAND "$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
set VIRTUAL_ENV
setenv VIRTUAL_ENV
set fish_function_path $fish_function_path "$PWD/powerline/bindings/fish"
powerline-setup ; cd tests/shell/3rd
cd .git
cd ..
set VIRTUAL_ENV "$HOME/.virtenvs/some-virtual-environment"
set VIRTUAL_ENV
setenv VIRTUAL_ENV "$HOME/.virtenvs/some-virtual-environment"
setenv VIRTUAL_ENV
bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
false
kill (cat pid) ; sleep 1s

View File

@ -0,0 +1,23 @@
POWERLINE_COMMAND="$PWD/scripts/powerline -p $PWD/powerline/config_files"
POWERLINE_COMMAND="$POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false"
POWERLINE_COMMAND="$POWERLINE_COMMAND -c ext.shell.theme=default_leftonly"
export VIRTUAL_ENV=
. powerline/bindings/shell/powerline.sh ; cd tests/shell/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
VIRTUAL_ENV=
bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
false
kill `cat pid` ; sleep 1
cd "$DIR1"
cd ../"$DIR2"
cd ../'\[\]'
cd ../'%%'
cd ../'#[bold]'
cd ../'(echo)'
cd ../'$(echo)'
cd ../'`echo`'
false
true is the last line
exit

View File

@ -2,7 +2,12 @@ unsetopt promptsp transientrprompt
POWERLINE_COMMAND=( $PWD/scripts/powerline -p $PWD/powerline/config_files )
POWERLINE_COMMAND=( $POWERLINE_COMMAND -t default_leftonly.segment_data.hostname.args.only_if_ssh=false )
POWERLINE_COMMAND=( $POWERLINE_COMMAND -c ext.shell.theme=default_leftonly )
VIRTUAL_ENV=
setopt interactivecomments
# POWERLINE_CONFIG_PATH=$PWD/powerline/config_files
# POWERLINE_THEME_CONFIG=( default_leftonly.segment_data.hostname.args.only_if_ssh=false )
# POWERLINE_CONFIG=( ext.shell.theme=default_leftonly )
POWERLINE_NO_ZSH_ZPYTHON=1 # TODO: make tests work with zsh/zpython
export VIRTUAL_ENV=
source powerline/bindings/zsh/powerline.zsh ; cd tests/shell/3rd
cd .git
cd ..

19
tests/test_shells/mksh.ok Normal file
View File

@ -0,0 +1,19 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV=
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bash -c 'echo $$>pid ; while true ; do sleep 0.1s ; done' &
[1] PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `cat pid` ; sleep 1
[1] + Terminated bash -c ...
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd "$DIR1"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^[[32m  cd ../"$DIR2"
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  ^H  cd ../'\[\]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  \[\]  cd ../'%%'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  %%  cd ../'#[bold]'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  #[bold]  cd ../'(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  (echo)  cd ../'$(echo)'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  $(echo)  cd ../'`echo`'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  `echo`  false

View File

@ -48,4 +48,9 @@ with codecs.open(fname, 'r', encoding='utf-8') as R:
line = line[start:end] + '\033[0m\n'
except ValueError:
line = ''
elif shell == 'mksh':
# Output is different in travis: on my machine I see full
# command, in travis it is truncated just after `true`.
if line.startswith('[1] + Terminated'):
line = '[1] + Terminated bash -c ...\n'
W.write(line)

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
FAILED=0
ONLY_SHELL="$1"
@ -16,20 +16,44 @@ check_screen_log() {
run_test() {
SH="$1"
SESNAME="powerline-shell-test-${SH}-$$"
ARGS=( "$@" )
test "x$ONLY_SHELL" = "x" || test "x$ONLY_SHELL" = "x$SH" || return 0
which "${SH}" || return 0
if ! which "${SH}" ; then
if test "x${SH}" = "xbb" ; then
if ! which busybox ; then
return 0
fi
shift
ARGS=( busybox ash "$@" )
else
return 0
fi
fi
export SH
screen -L -c tests/test_shells/screenrc -d -m -S "$SESNAME" \
env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "$@"
env LANG=en_US.UTF-8 BINDFILE="$BINDFILE" "${ARGS[@]}"
screen -S "$SESNAME" -X readreg a tests/test_shells/input.$SH
# Wait for screen to initialize
sleep 1s
sleep 1
screen -S "$SESNAME" -p 0 -X width 300 1
screen -S "$SESNAME" -p 0 -X paste a
if test "x${SH}" = "xdash" ; then
# If I do not use this hack for dash then output will look like
#
# command1
# command2
# …
# prompt1> prompt2> …
while read -r line ; do
screen -S "$SESNAME" -p 0 -X stuff "$line"$'\n'
sleep 1
done < tests/test_shells/input.$SH
else
screen -S "$SESNAME" -p 0 -X paste a
fi
# Wait for screen to exit (sending command to non-existing screen session
# fails; when launched instance exits corresponding session is deleted)
while screen -S "$SESNAME" -X blankerprg "" > /dev/null ; do
@ -51,7 +75,23 @@ run_test() {
echo '============================================================'
cat -v tests/shell/${SH}.full.log
echo '____________________________________________________________'
${SH} --version
case ${SH} in
*ksh)
${SH} -c 'echo ${KSH_VERSION}'
;;
dash)
# ?
;;
bb)
bb --help
;;
*)
${SH} --version
;;
esac
if which dpkg >/dev/null ; then
dpkg -s ${SH}
fi
return 1
fi
return 0
@ -90,5 +130,19 @@ if ! run_test tcsh -f -i ; then
FAILED=1
fi
if ! run_test bb -i ; then
FAILED=1
fi
unset ENV
if ! run_test mksh -i ; then
FAILED=1
fi
if ! run_test dash -i ; then
FAILED=1
fi
test "x$ONLY_SHELL" = "x" && rm -r tests/shell
exit $FAILED