StaSh - Shell Like an Expert in Pythonista
-
[EDIT]: 2016-05-26
Inspired by shellista and its variants, StaSh is a serious attempt to implement a Bash-like shell for Pythonista.
Since its initial release, valuable contributions and advices have been received constantly from the Pythonista community. The two most popular utilities are
pip
(authored by @briarfox) andgit
(authored by @jsbain). Remarkable contributions are also made by
@dgelessus, @pudquick, @oefe, @cclauss, @georg.viehoever, @BBOOXX and @bennr01.StaSh stands for Pythonista Shell. While Sta may not be the best abbreviation for Pythonista, it forms a concise and meaningful word with the following Sh part. So the name StaSh was chose to indicate it is a confined environment and great treasures may be found within.
Installation
StaSh can be easily installed via one line of python command (courtesy of @whitone).
import requests as r; exec(r.get('http://bit.ly/get-stash').text)
Simply copy the above line, paste into Pythonista interactive prompt and execute. It installs StaSh as a Python module under the
site-packages
folder (~/Documents/site-packages/stash
) and copies a launching script,~/Documents/launch_stash.py
for easy access.If you have previous versions of StaSh installed (e.g. v0.4.x), You may need to restart Pythonista BEFORE the installation.
If you have a GitHub tool available in Pythonista, such as gitview or gitrepo, you can choose to directly clone or download the repository.
StaSh requires Pythonista v2.0 as the new ObjC feature is heavily used. For older Pythonista 1.5 compatible version, please refer to the v0.4 branch.
Upgrade
Once StaSh is installed, it can be easily updated by running the
selfupdate
command from within the shell.selfupdate
defaults to themaster
branch. To update from a different branch, e.g.dev
, useselfupdate dev
.- By default,
selfupdate
compares local and remote versions and only performs update if newer version is found. You can however force the update without version checking viaselfupdate -f
. - To check for newer version without actually install it, use
selfupdate -n
. selfupdate
manages StaSh installation folder and may delete files in the process. It is therefore recommended to not place your own scripts under$STASH_ROOT/bin
. Instead, save your own scripts in~/Documents/bin
or customise the locations with theBIN_PATH
environment variable.- You may need to restart Pythonista after the update for changes to take full effects.
selfupdate cannot be used for version 0.4.x and under. A fresh installation is needed.
Notable Features
StaSh has a pile of features that are expected from a real shell. These
features are what really set the difference from shellista.-
Panel UI program that is completely event driven
- No blocking thread, builtin interactive prompt is accessible at all time
- Consistent look and feel as a proper PC terminal
- Almost all scripts can be called from within StaSh, including programs using UI and Scene packages.
- Attributed text (color and style) support
- Multiple sessions are possible by opening additional Panel tabs
- Being a pure UI program, it is possible to launch and forget. The program
stays active indefinitely. Non-UI scripts can only run for 10 minutes in background. But StaSh can stay up forever (till memory runs out due to other Apps). You can just launch StaSh to run a few commands and leave it.
It will still be there for you when you return later.
-
Comprehensive command line parsing and handling using pyparsing
- Environmental variables, e.g
echo $HOME
,NAME=value
- Aliases, e.g.
alias l1='ls -1'
- Single and double quotes behave like Bash, e.g.
"*"
means literal*
,"$HOME"
expands while'$HOME'
does not. - Backslash escaping, e.g.
ls My\ Script.py
- Glob, e.g.
ls ~/*.py
- Backtick quotes for subprocess, e.g.
touch `ls *.py`
- Pipes to chain commands, e.g.
find . -name "*.txt" | grep interesting
- IO redirect (actually just Output redirect), e.g.
ls *.py > py_files.txt
. Input redirect can be achieved by using pipes.- It is possible to redirect to the Pythonista builtin console,
e.g.ls > &3
- It is possible to redirect to the Pythonista builtin console,
- Bang(!) to search command history, e.g.
ls -1
,!l
. Bang commands like!!
and!-1
also works.
- Environmental variables, e.g
-
Smart auto-completion just as expected
- One UI button,
Tab
, is provided to enable command line auto-completion. - It is smart to complete either commands or files based on the cursor position
- It also completes environment variables and aliases.
- It also features a sub-command auto-completion system. For an example, type
git sta
and pressTab
. It will auto-completes togit status
. You can easily add your own sub-commands completion via JSON files.
- One UI button,
-
Thread management allows multiple commands running in parallel
- One foreground jobs and unlimited number of background jobs can run simultaneously.
- A foreground job can be stopped by pressing the CC button or Ctrl-C on an external keyboard.
- A background job is issued by appending an ampersand character (
&
) at the end of a normal command, e.g.httpserver &
. It can be terminated by thekill
command using its job ID. - A few utilities are provided for thread management.
jobs
to list current running background jobs.kill
to kill a running job.fg
to bring background jobs to foregroundCZ
button (Ctrl-Z) to send a foreground job to background
-
Command line history management. Three UI buttons are provided to navigate through the history.
-
On-screen virtual keys - an extra row of keys on top of the on-screen keyboard to provide control functions and easier access to symbols
- Virtual keys for control functions including:
- Tab - command line auto-completion
- CC (Ctrl-C) - terminate the running job
- CD (Ctrl-D) - end of Input
- CU (Ctrl-U) - kill line
- CZ (Ctrl-Z) - Send current running foreground job to background
- KB - show/hide keyboard
- H - display a popup window to show command history
- Up - recall the previous command in history
- Dn - recall the next command in history
- Customisable virtual keys for commonly used symbols, e.g.
~/.-*|>
.- The Symbols can be customized via the
VK_SYMBOLS
option in stash config file (default is.stash_config
).
- The Symbols can be customized via the
- Virtual keys for control functions including:
-
Swipe on the virtual key row to position cursor (similar to what Pythonista builtin editor offers)
-
External keyboard support
- Tab key for auto-completion
- Up (↑) / Down (↓) for navigating through command history
- Ctrl-A and Ctrl-E to jump to the beginning and end of the input line, respectively
- Ctrl-U to erase the input line
- Ctrl-W to erase one word before cursor
- Ctrl-L to clear the screen
-
You can run (almost) any regular python scripts from within StaSh
- There is no need to customize them for the shell. If it can be executed by a python interpreter via
python your_script.py
, you can just call it from within StaSh by just typingyour_script
- The shell object is made available to scripts being called. This enables a range of complex interactions between the shell and called scripts. For an example, the running script can use the shell object to execute more commands, e.g.
_stash('pwd')
.
- There is no need to customize them for the shell. If it can be executed by a python interpreter via
-
You can give it a resource file, similar to
.bashrc
, to customize its behaviour. Like the Bash resource file, aliases, environment variables can be set here. The default resource file is.stashrc
under StaSh installation root (i.e.~/Documents/site-packages/stash
).- The prompt is customizable with the
PROMPT
environment variable.\w
- current working directory with HOME folder abbreviated as~
\W
- last path component of current working directory- All other strings are displayed literally
- The default setting is
PROMPT='[\W]$ '
- The prompt is customizable with the
-
Easy self update to keep update with the development by running a single
selfupdate
command from within the shell. -
The UI can be configured via configuration file to customize its font size and color. The default config file is
.stash_config
orstash.cfg
under StaSh installation root.
Usage
The usage of StaSh is in principle similar to Bash. A few things to note are:
-
The search paths for executable scripts is set via an environment variable called
BIN_PATH
asPATH
is used by the system. The defaultBIN_PATH
is~/Documents/bin:$STASH_ROOT/bin
. -
The executable files are either Python scripts or StaSh scripts. The type of script is determined by looking at the file extensions ".py" and ".sh". A file without extension is considered as a shell script.
- When invoking a script, you can omit the extension, StaSh will try find the file with one of the extensions. For an example, StaSh interprets the command
selfupdate
and find the fileselfupdate.py
to execute. - Files without extension won't show up as an auto-completion possibility.
- When invoking a script, you can omit the extension, StaSh will try find the file with one of the extensions. For an example, StaSh interprets the command
-
Commands can only be written in a single line. No line continuation is possible. However, multiple commands can be written in a single line by separating them with semicolons, e.g.
ls -1 > file_list; cat file_list
. -
There are many Python scripts provided along with StaSh. These scripts range from performing regular shell tasks to advanced utilities like
ssh
andgit
. Note the scripts are by no means complete when compared to a real Linux shell. The collection will be gradually expanded should the need arise. It is also expected and appreciated that the community would come up with more scripts.alias.py
- Define or print aliasescat.py
- Print contents of filecd.py
- Change current directoryclear.py
- Clear consolecp.py
- Copy filecrypt.py
- File encryption using AES in CBC modecurl.py
- Transfer from an URLcut.py
- Cut out selection portions of each line of a filedu.py
- Summarize disk usage of the set of FILEs, recursively for directoriesecho.py
- Output text to consoleedit.py
- Open any text type files in Pythonista editorfind.py
- Powerful file searching toolfg.py
- Bring a background job to foreground- `gci.py - Interface to Python's built-in garbage collector
git.py
- Git client ported from shellistagrep.py
- search contents of file(s)httpserver.py
- A simple HTTP server with upload function (ripped from https://gist.github.com/UniIsland/3346170)jobs.py
- List all jobs that are currently runningkill.py
- Terminate a running jobls.py
- List filesmail.py
- Send emails with optional file attachmentman.py
- Show help message (docstring) of a given commandmc.py
- Easily work with multiple filesystems (e.g. local and FTP) synchronously.md5sum.py
- Print or check MD5 checksumsmkdir.py
- Create directorymv.py
- Move fileopenin.py
- Show the open in dialog to open a file in external apps.pbcopy.py
- Copy to iOS clipboardpbpaste.py
- Paste from iOS clipboardpip.py
- Search, download, install, update and uninstall pure Python packages from PyPI.printenv.py
- List environment variablesprinthex.py
- Print hexadecimal dump of the given filepwd.py
- Print current directorypython.py
- Run python scripts or modulesquicklook.py
- iOS quick look for files of known typesrm.py
- delete (remove) filescp.py
- Copy files from/to remote servers.selfupdate.py
- Update StaSh from its GitHub reposha1sum.py
- Print of check SHA1 checksumssha256sum.py
- Print of check SHA256 checksumssort.py
- Sort a list, also see uniquesource.py
- Evaluate a script in the current environmentssh.py
- SSH client to either execute a command or spawn an interactive session on remote servers. pyte is used for terminal emulation and gives the command the feel of a full-fledged SSH client.ssh-keygen.py
- Generate RSA/DSA SSH Keys.stashconf.py
- Change StaSh configuration on the flytar.py
- Manipulate archive filestouch.py
- Update timestamp of the given file or create it if not existuniq.py
- Remove duplicates from list, also see sortunzip.py
- Unzip file, also see zipversion.py
- Show StaSh installation and version informationwc.py
- Line, word, character countingwget.py
- get data from the netwhich.py
- Find the exact path to a command scriptwol.py
- Wake on LAN using MAC address for launching a sleeping systemxargs.py
- Command constructing and executing utilityzip.py
- Zip file, also see unzip
Acknowledgements
- Pythonista is a wonderful piece of software.
- StaSh is inspired by
shellista and its variants, including ShellistaExt and ShellistaUI. - The UI part of StaSh has its root from ShellistaUI.
- Many of the command scripts, e.g.
ls.py
,cp.py
,mv.py
, are taken from ShellistaExt with some modifications.
Known Issues
- Pickled objects are not restored correctly and generate
AttributeError
as if the class definition cannot be found.
Contributing
- Check any open issues or open a new issue to start discussions about your ideas of features and/or bugs
- Fork the repository, make changes, and send pull requests
- Please send pull requests to the dev branch instead of master
-
It would be nice to have the zip comand on Stash, I only see unzip or tar, but Pythonista don't recognize tar.gz
-
@mncfre
zip
is now added. You can get it viaselfupdate
from within StaSh. Or if you want to get the latest development version, trySELFUPDATE_BRANCH=dev selfupdate
. You'll need restart StaSh afterwards. Thanks!
-
@ywangd thanks a lot, this is by far the best shell in Pythonista
-
I noticed that the pip command allows you to list all modules installed using this command and specially allows you to update individual modules! This is very useful! So I cleaned up my environment in Pythonista and now I'm handling everything with StaSh.
I was able to run many libraries in Pythonista without having to change them much, I tried only to override the functions. So now I'm creating StaSh scripts for running CLI program written in Python: in practice the first time they are run if the modules they needs are not installed they install these modules (as the command git) and apply monkey patches.
For those who have just installed Pythonista and want to install StaSh I created a simplified installation creating a shortened url for getstash.py.
To install StaSh just copy the following line in the Pythonista console:
import requests; exec requests.get('http://bit.ly/StaSh').text
Congratulations to all for this fantastic tool!
-
@whitone - Thanks for posting this. I have never used pip and my setup under Pythonista is now littered with many modules that I manually "installed". It is not hard, but I figured that there must be a better way. I also have no idea what monkey patches are about so I need to do some reading.
If you have any cycles it would be very instructional to have one quick tutorial on a useful program you installed and converted and the patches you had to apply to get it working and how you now have this captured and automated using stash - pip, etc.
One last question - are you referring to CLI programs in general or using the PyCLI module: https://pythonhosted.org/pyCLI/ ? This seems like a great way to go for writing scripts and gets people going using logging and a good command line interface.
-
last edited by
-
@whitone Glad you find the pip module useful. It's still limited on which packages it can install but it manages most of the common ones. We have tried to stub out setuptool as best we can but there are so many use cases. Currently pip will simply look for a folder with the same name as the package and put it into site-packages. Then it will look for src/package_name and as a last resort will attempt to run the setup.
I think @omz should add StaSh to the pythonista installation. It;s incredably useful and community developed. Props to @ywangd for creating such an awesome package.
-
@whitone The one line installation is a great idea. If it is OK with you, I'll add it to the README file as part of the installation instruction. The great work of
pip
is done by @briarfox. StaSh is made better by the excellent contributions from the community.After seeing the discussions, I am thinking to have something like "Tip/Treasure of the day" when StaSh starts up. Seems to be a good way for users to discover some useful tools and features in a non-intrusive manner.
-
@ywangd Tip of the day is a great idea, If I hadn't recently dove into linux command-line I'd be lost in staSh.
-
Great tool, thank you.<br /><br />
I want to ask if there is a trick using the find command?<br />
I always get:<br />
stash: IndentationError('unindent does not match any outer indentation level', ('findy.py', 148, 17, ...)<br /><br />
[~/Documents]$ find . -name "*.py"
-
@brumm works for me. Probably you edited
bin/find.py
by accident. The original is 147 lines long, but the error message refers to line 148..,
-
@oefe thank you 😀. My mistake...
-
An amazingly useful piece of software - thank you very much.
I had been trying to get MQTT running on the iPad - didn't have any joy loading paho-mqtt but pip install mosquitto does seem to be OK so far.
-
It'd be cool to use this to keep user themes in stash and get all pythonista's features
-
@Webmaster4o said:
It'd be cool to use this to keep user themes in stash and get all pythonista's features
I do plan to upgrade StaSh using the new and cool
ctypes
stuff. However, it may not use the Editor Internals as it is private and @omz does not recommend to use it seriously. So unless a more complete documentation about the Editor is available, I'll probably avoid using it.
-
Ok. Sounds good, I look forward to it.
-
Simply the most wonderful thing to add to my iPhone
second to Pythonista of course :-)
-
Hey does anyone no how to add an image in the background of stash. Like instead of changing background color you can add a background image ??????
-
@daveman It's not possible without editing the source code (Having an image as a terminal background is stupid anyway, if you ask me :P)
-
Thank you for writing this and sharing it. StaSh is great.