Tags
I've grown tired of the standard ipython prompt as it doesn't do much to give me any useful information. The default one gives out a line number that only seems to add anxiety as I am working on a simple problem and see that number grow to several hundred. I start to question my ability 🤦♂️.
Configuration
If you already have an ipython config you can move on otherwise check out this post on creating an ipython config.
The Dream Prompt
I want something similar to the starship prompt I am using in the shell. I want to be able to quickly see my python version, environment name, and git branch.
- python version
- active environment
- git branch
This is my zsh prompt I am using for inspiration
Basic Prompt
This is mostly boilerplate that I found from various google searches, but this gets me a basic green chevron as my prompt.
from IPython.terminal.prompts import Prompts, Token class MyPrompt(Prompts): def in_prompt_tokens(self, cli=None): return [ ( Token.Prompt, "❯ ",), ] def out_prompt_tokens(self, cli=None): return [] ip = get_ipython() ip.prompts = MyPrompt(ip)
The rest of this post will build off of this boilerplate and add to the
in_prompt_tokens
method of MyPrompt
Colors
I mostly set the colors of my prompt throughout this post by guessing and trying different attributes under the Token.
Red If Error
I found that the Prompts
subclass has many of the same methods as the ipython
object, so I would often use that for inspection. Looking through the ipython
class I found a boolean under shell.last_execution_succeeded
that would give
me if the last execution was successful or not. I did an inline if statemetn
to set the color to a Token.Generic.Error
if this was false.
def in_prompt_tokens(self, cli=None): return [ ( Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ]
Python Version
Next up to list out the python version that is running. I grabbed the version
from platform.python_version
, this seemed to get me the most concise version
that I was looking for to match the starship prompt.
update imports
from platform import python_version
update prompt
def in_prompt_tokens(self, cli=None): return [ ( (Token.Name.Class, "v" + python_version()), (Token, " "), Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ]
Python environment
Since I use conda for my environments I chose to pull the name of the
environment from the CONDA_DEFAULT_ENV
environment variable that is set by
conda when you change your environment.
update imports
from platform import python_version import os
update prompt
def in_prompt_tokens(self, cli=None): return [ ( (Token.Prompt, "©"), (Token.Prompt, os.environ["CONDA_DEFAULT_ENV"]), (Token, " "), (Token.Name.Class, "v" + python_version()), (Token, " "), Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ]
Git Branch
Git branch was a bit tricky. There might be a better way to get it,
but I was sticking with things I knew, the git cli and python. I
did need to do a bit of googling to figure out that git has a
--show-current
option.
getting the current git branch
def get_branch(): try: return ( subprocess.check_output( "git branch --show-current", shell=True, stderr=subprocess.DEVNULL ) .decode("utf-8") .replace("\n", "") ) except BaseException: return ""
NOTE If this is run form a non-git directory you will quickly find git errors after every command as this function tries to ask for the git branch. Sending stderr to devnull will avoid this inconvenience.
add git branch to prompt
def in_prompt_tokens(self, cli=None): return [ ( (Token.Generic.Subheading, "↪"), (Token.Generic.Subheading, get_branch()), (Token, " "), (Token.Prompt, "©"), (Token.Prompt, os.environ["CONDA_DEFAULT_ENV"]), (Token, " "), (Token.Name.Class, "v" + python_version()), (Token, " "), Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ]
Add current directory name
I am a big fan of pathlib so that is what I will use to get the path. If I
planned on using python <3.6
I would probably use something else, but this is
what I know and I can't think of the last time I used <3.6>
for anything.
update imports
from pathlib import Path
add git branch to prompt
def in_prompt_tokens(self, cli=None): return [ ( (Token, ""), (Token.OutPrompt, Path().absolute().stem), (Token, ""), (Token.Generic.Subheading, "↪"), (Token.Generic.Subheading, get_branch()), (Token, " "), (Token.Prompt, "©"), (Token.Prompt, os.environ["CONDA_DEFAULT_ENV"]), (Token, " "), (Token.Name.Class, "v" + python_version()), (Token, " "), Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ]
Final Script
That's it for my prompt at the moment. I have been using it for about a week. It seems to have everything I need so far, and skips on things I don't need.
Enjoy the full script.
my final prompt
from IPython.terminal.prompts import Prompts, Token from pathlib import Path import os from platform import python_version import subprocess def get_branch(): try: return ( subprocess.check_output( "git branch --show-current", shell=True, stderr=subprocess.DEVNULL ) .decode("utf-8") .replace("\n", "") ) except BaseException: return "" class MyPrompt(Prompts): def in_prompt_tokens(self, cli=None): return [ (Token, ""), (Token.OutPrompt, Path().absolute().stem), (Token, " "), (Token.Generic.Subheading, "↪"), (Token.Generic.Subheading, get_branch()), (Token, " "), (Token.Prompt, "©"), (Token.Prompt, os.environ["CONDA_DEFAULT_ENV"]), (Token, " "), (Token.Name.Class, "v" + python_version()), (Token, " "), (Token.Name.Entity, "ipython"), (Token, "\n"), ( Token.Prompt if self.shell.last_execution_succeeded else Token.Generic.Error, "❯ ", ), ] def out_prompt_tokens(self, cli=None): return [] ip = get_ipython() ip.prompts = MyPrompt(ip)
Want automatic imports??
This article covers how I setup automatic imports in ipython