##// END OF EJS Templates
Use plugin API for storemagic, so autorestore is configurable.
Use plugin API for storemagic, so autorestore is configurable.

File last commit:

r5498:24455c41
r5541:e1c26325
Show More
prompts.py
378 lines | 14.1 KiB | text/x-python | PythonLexer
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # -*- coding: utf-8 -*-
Brian Granger
Refactor of prompts and the displayhook....
r2781 """Classes for handling input/output prompts.
Authors:
* Fernando Perez
* Brian Granger
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 * Thomas Kluyver
Fernando Perez
Remove svn-style $Id marks from docstrings and Release imports....
r1853 """
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Brian Granger
Refactor of prompts and the displayhook....
r2781 #-----------------------------------------------------------------------------
Matthias BUSSONNIER
update copyright to 2011/20xx-2011...
r5390 # Copyright (C) 2008-2011 The IPython Development Team
Fernando Perez
Update copyright/author statements....
r1875 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 #
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
Brian Granger
Refactor of prompts and the displayhook....
r2781 #-----------------------------------------------------------------------------
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Brian Granger
Refactor of prompts and the displayhook....
r2781 #-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
fperez
Cosmetic cleanups: put all imports in a single line, and sort them...
r52 import os
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 import re
fperez
Cosmetic cleanups: put all imports in a single line, and sort them...
r52 import socket
import sys
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 import time
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 from IPython.config.configurable import Configurable
Brian Granger
Release.py => core/release.py and imports updated.
r2043 from IPython.core import release
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 from IPython.utils import coloransi
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Brian Granger
Refactor of prompts and the displayhook....
r2781 #-----------------------------------------------------------------------------
# Color schemes for prompts
#-----------------------------------------------------------------------------
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Brian Granger
ColorANSI.py -> utils/coloransi.py and all imports updated.
r2010 InputColors = coloransi.InputTermColors # just a shorthand
Colors = coloransi.TermColors # just a shorthand
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
PColNoColors = coloransi.ColorScheme(
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 'NoColor',
in_prompt = InputColors.NoColor, # Input prompt
in_number = InputColors.NoColor, # Input prompt number
in_prompt2 = InputColors.NoColor, # Continuation prompt
in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
Bernardo B. Marques
remove all trailling spaces
r4872
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 out_prompt = Colors.NoColor, # Output prompt
out_number = Colors.NoColor, # Output prompt number
normal = Colors.NoColor # color off (usu. Colors.Normal)
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 )
fperez
- Fairly significant changes to include Vivian's patches for improved pdb...
r46
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # make some schemes as instances so we can copy them for modification easily:
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 PColLinux = coloransi.ColorScheme(
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 'Linux',
in_prompt = InputColors.Green,
in_number = InputColors.LightGreen,
in_prompt2 = InputColors.Green,
in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
out_prompt = Colors.Red,
out_number = Colors.LightRed,
normal = Colors.Normal
)
fperez
- Fairly significant changes to include Vivian's patches for improved pdb...
r46
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Slightly modified Linux for light backgrounds
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 PColLightBG = PColLinux.copy('LightBG')
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 PColLightBG.colors.update(
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 in_prompt = InputColors.Blue,
in_number = InputColors.LightBlue,
in_prompt2 = InputColors.Blue
)
#-----------------------------------------------------------------------------
Brian Granger
Refactor of prompts and the displayhook....
r2781 # Utilities
#-----------------------------------------------------------------------------
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 class LazyEvaluate(object):
"""This is used for formatting strings with values that need to be updated
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 at that time, such as the current time or working directory."""
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 def __init__(self, func, *args, **kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
def __call__(self, **kwargs):
self.kwargs.update(kwargs)
return self.func(*self.args, **self.kwargs)
def __str__(self):
return str(self())
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 def multiple_replace(dict, text):
""" Replace in 'text' all occurences of any key in the given
dictionary by its corresponding value. Returns the new string."""
# Function by Xavier Defrang, originally found at:
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
# Create a regular expression from the dictionary keys
regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
# For each match, look-up corresponding value in dictionary
return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
#-----------------------------------------------------------------------------
# Special characters that can be used in prompt templates, mainly bash-like
Brian Granger
Refactor of prompts and the displayhook....
r2781 #-----------------------------------------------------------------------------
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
# If $HOME isn't defined (Windows), make it an absurd string so that it can
# never be expanded out into '~'. Basically anything which can never be a
# reasonable directory name will do, we just want the $HOME -> '~' operation
# to become a no-op. We pre-compute $HOME here so it's not done on every
# prompt call.
# FIXME:
# - This should be turned into a class which does proper namespace management,
# since the prompt specials need to be evaluated in a certain namespace.
# Currently it's just globals, which need to be managed manually by code
# below.
# - I also need to split up the color schemes from the prompt specials
# somehow. I don't have a clean design for that quite yet.
HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
# We precompute a few more strings here for the prompt_specials, which are
# fixed once ipython starts. This reduces the runtime overhead of computing
# prompt strings.
USER = os.environ.get("USER")
HOSTNAME = socket.gethostname()
HOSTNAME_SHORT = HOSTNAME.split(".")[0]
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$"
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 prompt_abbreviations = {
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Prompt/history count
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 '%n' : '{color.number}' '{count}' '{color.prompt}',
r'\#': '{color.number}' '{count}' '{color.prompt}',
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
# can get numbers displayed in whatever color they want.
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 r'\N': '{count}',
Fernando Perez
Add tests to ensure that %run does not modify __builtins__...
r1953
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Prompt/history count, with the actual digits replaced by dots. Used
# mainly in continuation prompts (prompt_in2)
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 r'\D': '{dots}',
Fernando Perez
Ensure that __builtin__ is always available and compute prompts from it....
r2485
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Current time
Thomas Kluyver
Use \T for timestamp in templates to distinguish it from \t = <tab>
r5497 r'\T' : '{time}',
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 # Current working directory
r'\w': '{cwd}',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Basename of current working directory.
# (use os.sep to make this portable across OSes)
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 r'\W' : '{cwd_last}',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # These X<N> are an extension to the normal bash prompts. They return
# N terms of the path, after replacing $HOME with '~'
Thomas Kluyver
Fix bugs in calling cwd_filt and cwd_filt2 for prompts.
r5498 r'\X0': '{cwd_x[0]}',
r'\X1': '{cwd_x[1]}',
r'\X2': '{cwd_x[2]}',
r'\X3': '{cwd_x[3]}',
r'\X4': '{cwd_x[4]}',
r'\X5': '{cwd_x[5]}',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Y<N> are similar to X<N>, but they show '~' if it's the directory
# N+1 in the list. Somewhat like %cN in tcsh.
Thomas Kluyver
Fix bugs in calling cwd_filt and cwd_filt2 for prompts.
r5498 r'\Y0': '{cwd_y[0]}',
r'\Y1': '{cwd_y[1]}',
r'\Y2': '{cwd_y[2]}',
r'\Y3': '{cwd_y[3]}',
r'\Y4': '{cwd_y[4]}',
r'\Y5': '{cwd_y[5]}',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Hostname up to first .
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\h': HOSTNAME_SHORT,
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Full hostname
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\H': HOSTNAME,
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Username of current user
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\u': USER,
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Escaped '\'
'\\\\': '\\',
# Newline
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\n': '\n',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Carriage return
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\r': '\r',
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Release version
Brian Granger
Release.py => core/release.py and imports updated.
r2043 r'\v': release.version,
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 # Root symbol ($ or #)
fperez
- Add \N escape for the actual prompt number, without any coloring.
r579 r'\$': ROOT_SYMBOL,
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 }
#-----------------------------------------------------------------------------
Brian Granger
Refactor of prompts and the displayhook....
r2781 # More utilities
#-----------------------------------------------------------------------------
Thomas Kluyver
Fix bugs in calling cwd_filt and cwd_filt2 for prompts.
r5498 def cwd_filt(depth):
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 """Return the last depth elements of the current working directory.
fperez
- new doctest_mode magic to toggle doctest pasting/prompts....
r763
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 $HOME is always replaced with '~'.
If depth==0, the full path is returned."""
fperez
- new doctest_mode magic to toggle doctest pasting/prompts....
r763
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 cwd = os.getcwd().replace(HOME,"~")
out = os.sep.join(cwd.split(os.sep)[-depth:])
return out or os.sep
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Fix bugs in calling cwd_filt and cwd_filt2 for prompts.
r5498 def cwd_filt2(depth):
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 """Return the last depth elements of the current working directory.
Bernardo B. Marques
remove all trailling spaces
r4872
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 $HOME is always replaced with '~'.
If depth==0, the full path is returned."""
fperez
- new doctest_mode magic to toggle doctest pasting/prompts....
r763
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 full_cwd = os.getcwd()
cwd = full_cwd.replace(HOME,"~").split(os.sep)
if '~' in cwd and len(cwd) == depth+1:
depth += 1
drivepart = ''
if sys.platform == 'win32' and len(cwd) > depth:
drivepart = os.path.splitdrive(full_cwd)[0]
out = drivepart + '/'.join(cwd[-depth:])
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 return out or os.sep
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 #-----------------------------------------------------------------------------
# Prompt classes
#-----------------------------------------------------------------------------
vivainio
prompt and set_term_title now include drive letter and / characters on win32
r794
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
'cwd': LazyEvaluate(os.getcwd),
'cwd_last': LazyEvaluate(lambda: os.getcwd().split(os.sep)[-1]),
'cwd_x': [LazyEvaluate(lambda: os.getcwd().replace("%s","~"))] +\
[LazyEvaluate(cwd_filt, x) for x in range(1,6)],
'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
}
class PromptManager(Configurable):
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 """This is the primary interface for producing IPython's prompts."""
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
color_scheme_table = Instance(coloransi.ColorSchemeTable)
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 color_scheme = Unicode('Linux', config=True)
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 def _color_scheme_changed(self, name, new_value):
self.color_scheme_table.set_active_scheme(new_value)
for pname in ['in', 'in2', 'out', 'rewrite']:
# We need to recalculate the number of invisible characters
self.update_prompt(pname)
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 lazy_evaluate_fields = Dict(help="""
This maps field names used in the prompt templates to functions which
will be called when the prompt is rendered. This allows us to include
things like the current time in the prompts. Functions are only called
if they are used in the prompt.
""")
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
in_template = Unicode('In [\\#]: ', config=True)
in2_template = Unicode(' .\\D.: ', config=True)
out_template = Unicode('Out[\\#]: ', config=True)
rewrite_template = Unicode("------> ", config=True)
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 justify = Bool(True, config=True, help="""
If True (default), each prompt will be right-aligned with the
preceding one.
""")
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495
# We actually store the expanded templates here:
templates = Dict()
# The number of characters in the last prompt rendered, not including
# colour characters.
width = Int()
# The number of characters in each prompt which don't contribute to width
invisible_chars = Dict()
def _invisible_chars_default(self):
return {'in': 0, 'in2': 0, 'out': 0, 'rewrite': 0}
def __init__(self, shell, config=None):
super(PromptManager, self).__init__(shell=shell, config=config)
# Prepare colour scheme table
self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
PColLinux, PColLightBG], self.color_scheme)
# Prepare templates
self.update_prompt('in', self.in_template)
self.update_prompt('in2', self.in2_template)
self.update_prompt('out', self.out_template)
self.update_prompt('rewrite', self.rewrite_template)
self.on_trait_change(self._update_prompt_trait, ['in_template',
'in2_template', 'out_template', 'rewrite_template'])
def update_prompt(self, name, new_template=None):
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 """This is called when a prompt template is updated. It processes
abbreviations used in the prompt template (like \#) and calculates how
many invisible characters (ANSI colour escapes) the resulting prompt
contains.
It is also called for each prompt on changing the colour scheme. In both
cases, traitlets should take care of calling this automatically.
"""
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 if new_template is not None:
self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
invis_chars = len(self.render(name, color=True, just=False)) - \
len(self.render(name, color=False, just=False))
self.invisible_chars[name] = invis_chars
def _update_prompt_trait(self, traitname, new_template):
name = traitname[:-9] # Cut off '_template'
self.update_prompt(name, new_template)
def render(self, name, color=True, just=None, **kwargs):
"""
Render the selected prompt.
Parameters
----------
name : str
Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
color : bool
If True (default), include ANSI escape sequences for a coloured prompt.
just : bool
If True, justify the prompt to the width of the last prompt. The
default is stored in self.justify.
**kwargs :
Additional arguments will be passed to the string formatting operation,
so they can override the values that would otherwise fill in the
template.
Returns
-------
A string containing the rendered prompt.
"""
if color:
scheme = self.color_scheme_table.active_colors
if name=='out':
colors = color_lists['normal']
colors.number, colors.prompt, colors.normal = \
scheme.out_number, scheme.out_prompt, scheme.normal
Thomas Kluyver
Further cleanup of prompts code - docstrings, etc.
r5496 elif name=='rewrite':
colors = color_lists['normal']
# We need a non-input version of these escapes
colors.number = scheme.in_number.replace("\001","").replace("\002","")
colors.prompt = scheme.in_prompt.replace("\001","").replace("\002","")
colors.normal = scheme.normal
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 else:
colors = color_lists['inp']
colors.number, colors.prompt, colors.normal = \
scheme.in_number, scheme.in_prompt, scheme.in_normal
if name=='in2':
colors.prompt = scheme.in_prompt2
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0 else:
Thomas Kluyver
Refactor prompt handling into new prompt manager.
r5495 # No color
colors = color_lists['nocolor']
colors.number, colors.prompt, colors.normal = '', '', ''
count = self.shell.execution_count # Shorthand
# Build the dictionary to be passed to string formatting
fmtargs = dict(color=colors, count=count,
dots="."*len(str(count)) )
fmtargs.update(self.lazy_evaluate_fields)
fmtargs.update(kwargs)
# Prepare the prompt
prompt = colors.prompt + self.templates[name] + colors.normal
# Fill in required fields
res = prompt.format(**fmtargs)
# Handle justification of prompt
invis_chars = self.invisible_chars[name] if color else 0
just = self.justify if (just is None) else just
if just:
res = res.rjust(self.width + invis_chars)
self.width = len(res) - invis_chars
return res
fperez
Reorganized the directory for ipython/ to have its own dir, which is a bit...
r0