Wednesday, September 23, 2020

IPython replacing shell

IPython is a good UNIX shell replacement, for those who want an interactive shell with a better programming language.

You can use unadorned shell commands, file globbing, and pipes, as well as regular python.

Regular shell: ls *.py | grep -v foo

Regular python: for x in range(3): print(x)

There is special syntax for running shell commands to be easily used by python code...

Shell in python: my_python_var1 = !ls #only for assigning variables

Python in shell: ls $my_python_var2

For anybody pining for python2: print "foo" #works!

Also works for any outermost python function: dir enumerate(list())

But unfortunately doesn't currently work with other code: for x in range(3): print x

For some reason, the maintainers are no longer publishing a profile for this stuff, so you can use the following to get up and running:

pip install ipython

mkdir -p ~/.ipython/profile_default
cat >> ~/.ipython/profile_default/ipython_config.py <<EOF
from IPython.terminal.prompts import Prompts, Token
import os

class MyPrompt(Prompts):
    def cwd(self):
        cwd = os.getcwd()
        if cwd.startswith(os.environ['HOME']):
            cwd = cwd.replace(os.environ['HOME'], '~')
            cwd_list = cwd.split('/')
            for i,v in enumerate(cwd_list):
                if i not in (1,len(cwd_list)-1): #not last and first after ~
                    cwd_list[i] = cwd_list[i][0] #abbreviate
            cwd = '/'.join(cwd_list)
        return cwd

    def in_prompt_tokens(self, cli=None):
        return [
                (Token.Prompt, 'In ['),
                (Token.PromptNum, str(self.shell.execution_count)),
                (Token.Prompt, '] '),
                (Token, self.cwd()),
                (Token.Prompt, ': ')]

c.TerminalInteractiveShell.prompts_class = MyPrompt
c.TerminalInteractiveShell.editing_mode = 'vi'
c.InteractiveShell.autocall = 2 #insert parens around functions as much as possible
c.InteractiveShellApp.exec_lines = ['%rehashx']
EOF