Advanced¶
This section of the docs shows you how to do useful but advanced things with twosheds.
Change your login shell¶
Replacing your login shell the shell you just wrote is simple.
Let’s assume your shell is named $SHELLPATH
. First you need to add your
shell to the list of valid shells, and then you need to actually change it.
To add your shell to the list of valid shells, you need to add it to
/etc/shells
, a list of paths to valid login shells on the system. By
default, it looks something like this:
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
So to add your shell, simply:
$ sudo bash -c "echo $SHELLPATH >> /etc/shells"
Finally, change your login shell:
$ chsh -s $SHELLPATH
Add git branch to prompt¶
Add the current git branch to the prompt:
def git_branch():
"""Get the current git branch or None."""
try:
return check_output("git symbolic-ref --short HEAD 2> /dev/null",
shell=True).strip()
except CalledProcessError:
return None
@shell.before_request
def primary_prompt_string():
pwd = os.getcwd().replace(os.environ["HOME"], "~")
branch = git_branch()
ps1 = "%s " % pwd if branch is None else "%s(%s) " % (pwd, branch)
os.environ["PS1"] = ps1
Automate ls
¶
We so frequently type ls
that sometimes it seems like it would be nice to
automate it.
In other shells, there are either prebuilt hooks from which we can execute arbitrary code or we can devise impressive aliases to automatically ls whenever the state of the directory changes:
# automate ls in zsh
# If the contents of the current working directory have changed, `ls`.
function precmd() {
a=$(cat ~/.contents)
b=$(ls)
if [ $a = $b ]
then
else
emulate -L zsh
ls
fi
ls > ~/.contents
}
With twosheds it’s much simpler:
from subprocess import check_output
import twosheds
shell = twosheds.Shell()
last_ls = ""
@shell.before_request
def ls():
global last_ls
ls = check_output("ls", shell=True)
if ls != last_ls:
last_ls = ls
shell.eval("ls")
This code reads the contents of the current directory before every command
and checks if its different from whatever the contents were before the last
command. If they’re different, it runs ls
.
Automate git status
¶
Automating git status is similar to automating ls:
from subprocess import check_output, CalledProcessError
import twosheds
shell = twosheds.Shell()
last_gs = ""
@shell.before_request
def gs():
global last_gs
try:
gs = check_output("git status --porcelain 2> /dev/null", shell=True)
except CalledProcessError:
pass
else:
if gs != last_gs:
last_gs = gs
# show status concisely
shell.eval("git status -s")
Auto-complete Git branches¶
To extend the completer, you can use the Shell.completes
decorator. It takes
a generator which given a string representing the word the user is trying to
complete, generates possible matches. For example, the following shows how to
extend the completer to match Git branches:
@shell.completes
def git_branches(word):
branches = sh("git branch --list {}* 2> /dev/null".format(word)).split()
try:
branches.remove("*")
except ValueError:
pass
for branch in branches:
yield branch