Add support for Byron Rakitzis’ rc shell reimplementation

Fixes #1238
This commit is contained in:
ZyX 2015-01-08 01:46:16 +03:00
parent 0942b3d8c4
commit c6bf5fb512
12 changed files with 263 additions and 11 deletions

View File

@ -416,11 +416,15 @@ Shell
Currently it is expected to contain at least the following attributes:
``last_exit_code``
Exit code returned by last shell command.
Exit code returned by last shell command. Is either one integer,
``sig{name}`` or ``sig{name}+core`` (latter two are only seen in ``rc``
shell).
``last_pipe_status``
List of exit codes returned by last programs in the pipe or some false
object. Only available in ``zsh``.
object. Only available in ``zsh`` and ``rc``. Is a list of either
integers, ``sig{name}`` or ``sig{name}+core`` (latter two are only seen
in ``rc`` shell).
``jobnum``
Number of background jobs.

View File

@ -67,6 +67,27 @@ is the absolute path to your Powerline installation directory:
.. _tmux-statusline:
Rcsh prompt
===========
Powerline supports Plan9 rc reimplementation *by Byron Rakitzis* packaged by
many \*nix distributions. To use it add
.. code-black:: bash
. {repository_root}/powerline/bindings/rc/powerline.rc
to your :file:`rcrc` file (usually :file:`~/.rcrc`) and make sure you start your
shell as a login shell (with ``-l`` argument): otherwise this configuration file
is not read.
.. warning::
Original Plan9 shell and its \*nix port are not supported because they are
missing ``prompt`` special function (it is being called once before each
non-continuation prompt). Since powerline could not support shell without
this or equivalent feature some other not-so-critical features of that port
were used.
Busybox (ash), mksh and dash prompt
=====================================

View File

@ -0,0 +1,84 @@
fn _powerline_sigwinch {
_POWERLINE_COLUMNS = `{
stty size | cut -d' ' -f2
}
_powerline_tmux_setenv COLUMNS $_POWERLINE_COLUMNS
}
fn _powerline_update_pwd {
_POWERLINE_NEW_PWD = `{pwd}
if (test $^_POWERLINE_NEW_PWD '=' $^_POWERLINE_SAVED_PWD) {
_POWERLINE_SAVED_PWD = $_POWERLINE_NEW_PWD
_powerline_tmux_setenv PWD $_POWERLINE_SAVED_PWD
}
}
fn _powerline_continuation_prompt {
_powerline_prompt --renderer-arg 'local_theme=continuation' $*
}
fn _powerline_prompt {
$POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell aboveleft -r.rcsh --last-pipe-status $^_POWERLINE_STATUS --last-exit-code $_POWERLINE_STATUS($#_POWERLINE_STATUS) --jobnum $_POWERLINE_JOBNUM --renderer-arg 'client_id='$pid $*
}
fn _powerline_set_prompt {
_POWERLINE_STATUS = ( $status )
_POWERLINE_JOBNUM = $#apids
prompt = (``() {
_powerline_prompt
} ``() {
_powerline_continuation_prompt
})
_powerline_update_pwd
}
fn _powerline_common_setup {
fn sigwinch {
_powerline_sigwinch
}
_powerline_sigwinch
_POWERLINE_SAVED_PWD = ''
}
fn _powerline_tmux_setenv {
}
if (test -z $POWERLINE_CONFIG_COMMAND) {
if (which powerline-config >/dev/null) {
POWERLINE_CONFIG_COMMAND = powerline-config
} else {
echo powerline-config executable not found, unable to proceed >[2=1]
}
}
if (test x$POWERLINE_CONFIG_COMMAND '!=' x) {
if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses prompt) {
if (test x$POWERLINE_COMMAND_ARGS '!=' x) {
# Perform splitting
POWERLINE_COMMAND_ARGS=( `{echo $POWERLINE_COMMAND_ARGS} )
}
fn prompt {
_powerline_set_prompt
}
if (test -z $POWERLINE_SHELL_CONTINUATION$POWERLINE_RCSH_CONTINUATION) {
_POWERLINE_STATUS = 0
_POWERLINE_JOBNUM = 0
_POWERLINE_CONTINUATION = `{
_powerline_continuation_prompt
}
fn _powerline_continuation_prompt {
echo -n $_POWERLINE_CONTINUATION
}
}
_powerline_common_setup
}
if (test x$TMUX '!=' x) {
if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses tmux) {
_POWERLINE_TMUX=$TMUX
fn _powerline_tmux_setenv {
if (test x$2 '!=' x) {
TMUX=$_POWERLINE_TMUX tmux setenv -g TMUX_$1^_`{
TMUX=$_POWERLINE_TMUX tmux display -p '#D' | tr -d %
} $2
}
}
_powerline_common_setup
}
}
}
# vim: ft=rcshell

View File

@ -10,6 +10,7 @@ from itertools import chain
from powerline.lib.overrides import parsedotval, parse_override_var
from powerline.lib.dict import mergeargs
from powerline.lib.encoding import get_preferred_arguments_encoding
from powerline.lib.unicode import u
if sys.version_info < (3,):
@ -55,6 +56,13 @@ def finish_args(environ, args):
return args
def int_or_sig(s):
if s.startswith('sig'):
return u(s)
else:
return int(s)
def get_argparser(ArgumentParser=argparse.ArgumentParser):
parser = ArgumentParser(description='Powerline prompt and statusline script.')
parser.add_argument('ext', nargs=1, help='Extension: application for which powerline command is launched (usually `shell\' or `tmux\').')
@ -64,8 +72,8 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
help='Renderer module. Usually something like `.bash\' or `.zsh\', is supposed to be set only in shell-specific bindings file.'
)
parser.add_argument('-w', '--width', type=int, help='Maximum prompt with. Triggers truncation of some segments.')
parser.add_argument('--last-exit-code', metavar='INT', type=int, help='Last exit code.')
parser.add_argument('--last-pipe-status', metavar='LIST', default='', type=lambda s: [int(status) for status in s.split()], help='Like above, but is supposed to contain space-separated array of statuses, representing exit statuses of commands in one pipe.')
parser.add_argument('--last-exit-code', metavar='INT', type=int_or_sig, help='Last exit code.')
parser.add_argument('--last-pipe-status', metavar='LIST', default='', type=lambda s: [int_or_sig(status) for status in s.split()], help='Like above, but is supposed to contain space-separated array of statuses, representing exit statuses of commands in one pipe.')
parser.add_argument('--jobnum', metavar='INT', type=int, help='Number of jobs.')
parser.add_argument('-c', '--config-override', metavar='KEY.KEY=VALUE', type=arg_to_unicode, action='append', help='Configuration overrides for `config.json\'. Is translated to a dictionary and merged with the dictionary obtained from actual JSON configuration: KEY.KEY=VALUE is translated to `{"KEY": {"KEY": VALUE}}\' and then merged recursively. VALUE may be any JSON value, values that are not `null\', `true\', `false\', start with digit, `{\', `[\' are treated like strings. If VALUE is omitted then corresponding key is removed.')
parser.add_argument('-t', '--theme-override', metavar='THEME.KEY.KEY=VALUE', type=arg_to_unicode, action='append', help='Like above, but theme-specific. THEME should point to an existing and used theme to have any effect, but it is fine to use any theme here.')

View File

@ -0,0 +1,12 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderers.shell import ShellRenderer
class RcshRenderer(ShellRenderer):
'''Powerline rcsh prompt renderer'''
escape_hl_start = '\x01'
escape_hl_end = '\x02'
renderer = RcshRenderer

View File

@ -5,7 +5,7 @@ git clone --depth=1 git://github.com/powerline/deps tests/bot-ci/deps
. tests/bot-ci/scripts/common/main.sh
sudo apt-get install -qq libssl1.0.0
sudo apt-get install -qq screen zsh tcsh mksh busybox socat realpath bc
sudo apt-get install -qq screen zsh tcsh mksh busybox socat realpath bc rc
if test -n "$USE_UCS2_PYTHON" ; then
pip install virtualenvwrapper

View File

@ -47,7 +47,7 @@ class TestParser(TestCase):
(['shell', '--renderer-arg'], 'expected one argument'),
(['shell', '--jobnum'], 'expected one argument'),
(['-r', '.zsh'], 'too few arguments|the following arguments are required: ext'),
(['shell', '--last-exit-code', 'i'], 'invalid int value'),
(['shell', '--last-exit-code', 'i'], 'invalid int_or_sig value'),
(['shell', '--last-pipe-status', '1 i'], 'invalid <lambda> value'),
]:
self.assertRaises(SystemExit, parser.parse_args, raising_args)

View File

@ -7,7 +7,7 @@ import os
from functools import partial
from collections import namedtuple
from powerline.segments import shell, tmux, common
from powerline.segments import shell, tmux
from powerline.lib.vcs import get_fallback_create_watcher
from powerline.lib.unicode import out_u
@ -38,6 +38,14 @@ class TestShell(TestCase):
self.assertEqual(shell.last_status(pl=pl, segment_info=segment_info), None)
segment_info['args'].last_exit_code = None
self.assertEqual(shell.last_status(pl=pl, segment_info=segment_info), None)
segment_info['args'].last_exit_code = 'sigsegv'
self.assertEqual(shell.last_status(pl=pl, segment_info=segment_info), [
{'contents': 'sigsegv', 'highlight_groups': ['exit_fail']}
])
segment_info['args'].last_exit_code = 'sigsegv+core'
self.assertEqual(shell.last_status(pl=pl, segment_info=segment_info), [
{'contents': 'sigsegv+core', 'highlight_groups': ['exit_fail']}
])
def test_last_pipe_status(self):
pl = Pl()
@ -51,6 +59,24 @@ class TestShell(TestCase):
{'contents': '2', 'highlight_groups': ['exit_fail'], 'draw_inner_divider': True},
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True}
])
segment_info['args'].last_pipe_status = [0, 'sigsegv', 'sigsegv+core']
self.assertEqual(shell.last_pipe_status(pl=pl, segment_info=segment_info), [
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True},
{'contents': 'sigsegv', 'highlight_groups': ['exit_fail'], 'draw_inner_divider': True},
{'contents': 'sigsegv+core', 'highlight_groups': ['exit_fail'], 'draw_inner_divider': True}
])
segment_info['args'].last_pipe_status = [0, 'sigsegv', 0]
self.assertEqual(shell.last_pipe_status(pl=pl, segment_info=segment_info), [
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True},
{'contents': 'sigsegv', 'highlight_groups': ['exit_fail'], 'draw_inner_divider': True},
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True}
])
segment_info['args'].last_pipe_status = [0, 'sigsegv+core', 0]
self.assertEqual(shell.last_pipe_status(pl=pl, segment_info=segment_info), [
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True},
{'contents': 'sigsegv+core', 'highlight_groups': ['exit_fail'], 'draw_inner_divider': True},
{'contents': '0', 'highlight_groups': ['exit_success'], 'draw_inner_divider': True}
])
def test_jobnum(self):
pl = Pl()

View File

@ -0,0 +1,32 @@
fn set_theme_option {
POWERLINE_THEME_OVERRIDES = $POWERLINE_THEME_OVERRIDES';'$1'='$2
}
set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
POWERLINE_CONFIG_OVERRIDES = 'ext.shell.theme=default_leftonly'
. powerline/bindings/rc/powerline.rc
VIRTUAL_ENV = ()
cd tests/shell/3rd
cd .git
cd ..
VIRTUAL_ENV = '/home/foo/.virtenvs/some-virtual-environment'
VIRTUAL_ENV = ()
bgscript.sh & waitpid.sh
false
kill `{cat pid} ; sleep 1s
cd $DIR1
cd ../$DIR2
cd ../'\[\]'
cd ../'%%'
cd ../'#[bold]'
cd ../'(echo)'
cd ../'$(echo)'
cd ../'`echo`'
cd ../'«Unicode!»'
false
set_theme_option default_leftonly.segment_data.hostname.display false
set_theme_option default_leftonly.segment_data.user.display false
echo `{
echo Continuation!
}
true is the last line
exit

View File

@ -0,0 +1,24 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV = '/home/foo/.virtenvs/some-virtual-environment'
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV = ()
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `{cat pid} ; sleep 1s
  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`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  false
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  1  set_theme_option default_leftonly.segment_data.hostname.display false
 USER   BRANCH  ⋯  shell  3rd  «Unicode!»  set_theme_option default_leftonly.segment_data.user.display false
  BRANCH  ⋯  shell  3rd  «Unicode!»  echo `{
                                           echo Continuation!
                                          }
Continuation!

View File

@ -0,0 +1,24 @@
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  cd .git
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  .git  cd ..
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV = '/home/foo/.virtenvs/some-virtual-environment'
  HOSTNAME  USER  ⓔ  some-virtual-environment   BRANCH  ⋯  tests  shell  3rd  VIRTUAL_ENV = ()
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  bgscript.sh & waitpid.sh
PID
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  false
  HOSTNAME  USER   BRANCH  ⋯  tests  shell  3rd  1  1  kill `{cat pid} ; sleep 1s
  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`  cd ../'«Unicode!»'
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  false
  HOSTNAME  USER   BRANCH  ⋯  shell  3rd  «Unicode!»  1  set_theme_option default_leftonly.segment_data.hostname.display false
 USER   BRANCH  ⋯  shell  3rd  «Unicode!»  set_theme_option default_leftonly.segment_data.user.display false
  BRANCH  ⋯  shell  3rd  «Unicode!»  echo `{
    echo Continuation!
   }
Continuation!

View File

@ -233,6 +233,8 @@ ln -s "$(which grep)" tests/shell/path
ln -s "$(which sed)" tests/shell/path
ln -s "$(which rm)" tests/shell/path
ln -s "$(which uname)" tests/shell/path
ln -s "$(which test)" tests/shell/path
ln -s "$(which pwd)" tests/shell/path
ln -s ../../test_shells/bgscript.sh tests/shell/path
ln -s ../../test_shells/waitpid.sh tests/shell/path
if which socat ; then
@ -249,6 +251,20 @@ for pexe in powerline powerline-config ; do
fi
done
if test -z "$POWERLINE_RC_EXE" ; then
if which rc-status >/dev/null ; then
# On Gentoo `rc` executable is from OpenRC. Thus app-shells/rc instals
# `rcsh` executable.
POWERLINE_RC_EXE=rcsh
else
POWERLINE_RC_EXE=rc
fi
fi
if which "$POWERLINE_RC_EXE" >/dev/null ; then
ln -s "$(which $POWERLINE_RC_EXE)" tests/shell/path/rc
fi
for exe in bash zsh busybox fish tcsh mksh dash ipython ; do
if which $exe >/dev/null ; then
ln -s "$(which $exe)" tests/shell/path
@ -261,7 +277,7 @@ export ADDRESS="powerline-ipc-test-$$"
export PYTHON
echo "Powerline address: $ADDRESS"
if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox ; then
if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox || test "x${ONLY_SHELL}" = xrc ; then
scripts/powerline-config shell command
for TEST_TYPE in "daemon" "nodaemon" ; do
@ -327,7 +343,8 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
"tcsh -f -i" \
"busybox ash -i" \
"mksh -i" \
"dash -i"
"dash -i" \
"rc -i -p"
do
J="$(( J + 1 ))"
if test x$FAST = x1 ; then
@ -343,10 +360,10 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
if test "x$ONLY_SHELL" != "x" && test "x$ONLY_SHELL" != "x$SH" ; then
continue
fi
if ! which $SH >/dev/null ; then
if ! test -x tests/shell/path/$SH ; then
continue
fi
echo ">>> $(which $SH)"
echo ">>> $(readlink "tests/shell/path/$SH")"
if ! run_test $TEST_TYPE $TEST_CLIENT $TEST_COMMAND ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T ${TEST_TYPE} ${TEST_CLIENT} ${TEST_COMMAND}"