| | """Implementation of magic functions for interaction with the OS. |
| | |
| | Note: this module is named 'osm' instead of 'os' to avoid a collision with the |
| | builtin. |
| | """ |
| | |
| | |
| |
|
| | import io |
| | import os |
| | import pathlib |
| | import re |
| | import sys |
| | from pprint import pformat |
| |
|
| | from IPython.core import magic_arguments |
| | from IPython.core import oinspect |
| | from IPython.core import page |
| | from IPython.core.alias import AliasError, Alias |
| | from IPython.core.error import UsageError |
| | from IPython.core.magic import ( |
| | Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic |
| | ) |
| | from IPython.testing.skipdoctest import skip_doctest |
| | from IPython.utils.openpy import source_to_unicode |
| | from IPython.utils.process import abbrev_cwd |
| | from IPython.utils.terminal import set_term_title |
| | from traitlets import Bool |
| | from warnings import warn |
| |
|
| |
|
| | @magics_class |
| | class OSMagics(Magics): |
| | """Magics to interact with the underlying OS (shell-type functionality). |
| | """ |
| |
|
| | cd_force_quiet = Bool(False, |
| | help="Force %cd magic to be quiet even if -q is not passed." |
| | ).tag(config=True) |
| |
|
| | def __init__(self, shell=None, **kwargs): |
| |
|
| | |
| | self.is_posix = False |
| | self.execre = None |
| | if os.name == 'posix': |
| | self.is_posix = True |
| | else: |
| | try: |
| | winext = os.environ['pathext'].replace(';','|').replace('.','') |
| | except KeyError: |
| | winext = 'exe|com|bat|py' |
| | try: |
| | self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) |
| | except re.error: |
| | warn("Seems like your pathext environmental " |
| | "variable is malformed. Please check it to " |
| | "enable a proper handle of file extensions " |
| | "managed for your system") |
| | winext = 'exe|com|bat|py' |
| | self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE) |
| |
|
| | |
| | super().__init__(shell=shell, **kwargs) |
| |
|
| |
|
| | def _isexec_POSIX(self, file): |
| | """ |
| | Test for executable on a POSIX system |
| | """ |
| | if os.access(file.path, os.X_OK): |
| | |
| | return file.is_file() |
| | return False |
| |
|
| |
|
| | |
| | def _isexec_WIN(self, file): |
| | """ |
| | Test for executable file on non POSIX system |
| | """ |
| | return file.is_file() and self.execre.match(file.name) is not None |
| |
|
| | def isexec(self, file): |
| | """ |
| | Test for executable file on non POSIX system |
| | """ |
| | if self.is_posix: |
| | return self._isexec_POSIX(file) |
| | else: |
| | return self._isexec_WIN(file) |
| |
|
| |
|
| | @skip_doctest |
| | @line_magic |
| | def alias(self, parameter_s=''): |
| | """Define an alias for a system command. |
| | |
| | '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd' |
| | |
| | Then, typing 'alias_name params' will execute the system command 'cmd |
| | params' (from your underlying operating system). |
| | |
| | Aliases have lower precedence than magic functions and Python normal |
| | variables, so if 'foo' is both a Python variable and an alias, the |
| | alias can not be executed until 'del foo' removes the Python variable. |
| | |
| | You can use the %l specifier in an alias definition to represent the |
| | whole line when the alias is called. For example:: |
| | |
| | In [2]: alias bracket echo "Input in brackets: <%l>" |
| | In [3]: bracket hello world |
| | Input in brackets: <hello world> |
| | |
| | You can also define aliases with parameters using %s specifiers (one |
| | per parameter):: |
| | |
| | In [1]: alias parts echo first %s second %s |
| | In [2]: %parts A B |
| | first A second B |
| | In [3]: %parts A |
| | Incorrect number of arguments: 2 expected. |
| | parts is an alias to: 'echo first %s second %s' |
| | |
| | Note that %l and %s are mutually exclusive. You can only use one or |
| | the other in your aliases. |
| | |
| | Aliases expand Python variables just like system calls using ! or !! |
| | do: all expressions prefixed with '$' get expanded. For details of |
| | the semantic rules, see PEP-215: |
| | https://peps.python.org/pep-0215/. This is the library used by |
| | IPython for variable expansion. If you want to access a true shell |
| | variable, an extra $ is necessary to prevent its expansion by |
| | IPython:: |
| | |
| | In [6]: alias show echo |
| | In [7]: PATH='A Python string' |
| | In [8]: show $PATH |
| | A Python string |
| | In [9]: show $$PATH |
| | /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:... |
| | |
| | You can use the alias facility to access all of $PATH. See the %rehashx |
| | function, which automatically creates aliases for the contents of your |
| | $PATH. |
| | |
| | If called with no parameters, %alias prints the current alias table |
| | for your system. For posix systems, the default aliases are 'cat', |
| | 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific |
| | aliases are added. For windows-based systems, the default aliases are |
| | 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'. |
| | |
| | You can see the definition of alias by adding a question mark in the |
| | end:: |
| | |
| | In [1]: cat? |
| | Repr: <alias cat for 'cat'>""" |
| |
|
| | par = parameter_s.strip() |
| | if not par: |
| | aliases = sorted(self.shell.alias_manager.aliases) |
| | |
| | |
| | |
| |
|
| | print("Total number of aliases:", len(aliases)) |
| | sys.stdout.flush() |
| | return aliases |
| |
|
| | |
| | try: |
| | alias,cmd = par.split(None, 1) |
| | except TypeError: |
| | print(oinspect.getdoc(self.alias)) |
| | return |
| | |
| | try: |
| | self.shell.alias_manager.define_alias(alias, cmd) |
| | except AliasError as e: |
| | print(e) |
| | |
| |
|
| | @line_magic |
| | def unalias(self, parameter_s=''): |
| | """Remove an alias""" |
| |
|
| | aname = parameter_s.strip() |
| | try: |
| | self.shell.alias_manager.undefine_alias(aname) |
| | except ValueError as e: |
| | print(e) |
| | return |
| | |
| | stored = self.shell.db.get('stored_aliases', {} ) |
| | if aname in stored: |
| | print("Removing %stored alias",aname) |
| | del stored[aname] |
| | self.shell.db['stored_aliases'] = stored |
| |
|
| | @line_magic |
| | def rehashx(self, parameter_s=''): |
| | """Update the alias table with all executable files in $PATH. |
| | |
| | rehashx explicitly checks that every entry in $PATH is a file |
| | with execute access (os.X_OK). |
| | |
| | Under Windows, it checks executability as a match against a |
| | '|'-separated string of extensions, stored in the IPython config |
| | variable win_exec_ext. This defaults to 'exe|com|bat'. |
| | |
| | This function also resets the root module cache of module completer, |
| | used on slow filesystems. |
| | """ |
| | from IPython.core.alias import InvalidAliasError |
| |
|
| | |
| | del self.shell.db['rootmodules_cache'] |
| |
|
| | path = [os.path.abspath(os.path.expanduser(p)) for p in |
| | os.environ.get('PATH','').split(os.pathsep)] |
| |
|
| | syscmdlist = [] |
| | savedir = os.getcwd() |
| |
|
| | |
| | try: |
| | |
| | |
| | if self.is_posix: |
| | for pdir in path: |
| | try: |
| | os.chdir(pdir) |
| | except OSError: |
| | continue |
| |
|
| | |
| | dirlist = os.scandir(path=pdir) |
| | for ff in dirlist: |
| | if self.isexec(ff): |
| | fname = ff.name |
| | try: |
| | |
| | |
| | if not self.shell.alias_manager.is_alias(fname): |
| | self.shell.alias_manager.define_alias( |
| | fname.replace('.',''), fname) |
| | except InvalidAliasError: |
| | pass |
| | else: |
| | syscmdlist.append(fname) |
| | else: |
| | no_alias = Alias.blacklist |
| | for pdir in path: |
| | try: |
| | os.chdir(pdir) |
| | except OSError: |
| | continue |
| |
|
| | |
| | dirlist = os.scandir(pdir) |
| | for ff in dirlist: |
| | fname = ff.name |
| | base, ext = os.path.splitext(fname) |
| | if self.isexec(ff) and base.lower() not in no_alias: |
| | if ext.lower() == '.exe': |
| | fname = base |
| | try: |
| | |
| | |
| | self.shell.alias_manager.define_alias( |
| | base.lower().replace('.',''), fname) |
| | except InvalidAliasError: |
| | pass |
| | syscmdlist.append(fname) |
| |
|
| | self.shell.db['syscmdlist'] = syscmdlist |
| | finally: |
| | os.chdir(savedir) |
| |
|
| | @skip_doctest |
| | @line_magic |
| | def pwd(self, parameter_s=''): |
| | """Return the current working directory path. |
| | |
| | Examples |
| | -------- |
| | :: |
| | |
| | In [9]: pwd |
| | Out[9]: '/home/tsuser/sprint/ipython' |
| | """ |
| | try: |
| | return os.getcwd() |
| | except FileNotFoundError as e: |
| | raise UsageError("CWD no longer exists - please use %cd to change directory.") from e |
| |
|
| | @skip_doctest |
| | @line_magic |
| | def cd(self, parameter_s=''): |
| | """Change the current working directory. |
| | |
| | This command automatically maintains an internal list of directories |
| | you visit during your IPython session, in the variable ``_dh``. The |
| | command :magic:`%dhist` shows this history nicely formatted. You can |
| | also do ``cd -<tab>`` to see directory history conveniently. |
| | Usage: |
| | |
| | - ``cd 'dir'``: changes to directory 'dir'. |
| | - ``cd -``: changes to the last visited directory. |
| | - ``cd -<n>``: changes to the n-th directory in the directory history. |
| | - ``cd --foo``: change to directory that matches 'foo' in history |
| | - ``cd -b <bookmark_name>``: jump to a bookmark set by %bookmark |
| | - Hitting a tab key after ``cd -b`` allows you to tab-complete |
| | bookmark names. |
| | |
| | .. note:: |
| | ``cd <bookmark_name>`` is enough if there is no directory |
| | ``<bookmark_name>``, but a bookmark with the name exists. |
| | |
| | Options: |
| | |
| | -q Be quiet. Do not print the working directory after the |
| | cd command is executed. By default IPython's cd |
| | command does print this directory, since the default |
| | prompts do not display path information. |
| | |
| | .. note:: |
| | Note that ``!cd`` doesn't work for this purpose because the shell |
| | where ``!command`` runs is immediately discarded after executing |
| | 'command'. |
| | |
| | Examples |
| | -------- |
| | :: |
| | |
| | In [10]: cd parent/child |
| | /home/tsuser/parent/child |
| | """ |
| |
|
| | try: |
| | oldcwd = os.getcwd() |
| | except FileNotFoundError: |
| | |
| | oldcwd = None |
| |
|
| | numcd = re.match(r'(-)(\d+)$',parameter_s) |
| | |
| | if numcd: |
| | nn = int(numcd.group(2)) |
| | try: |
| | ps = self.shell.user_ns['_dh'][nn] |
| | except IndexError: |
| | print('The requested directory does not exist in history.') |
| | return |
| | else: |
| | opts = {} |
| | elif parameter_s.startswith('--'): |
| | ps = None |
| | fallback = None |
| | pat = parameter_s[2:] |
| | dh = self.shell.user_ns['_dh'] |
| | |
| | for ent in reversed(dh): |
| | if pat in os.path.basename(ent) and os.path.isdir(ent): |
| | ps = ent |
| | break |
| |
|
| | if fallback is None and pat in ent and os.path.isdir(ent): |
| | fallback = ent |
| |
|
| | |
| | if ps is None: |
| | ps = fallback |
| |
|
| | if ps is None: |
| | print("No matching entry in directory history") |
| | return |
| | else: |
| | opts = {} |
| |
|
| |
|
| | else: |
| | opts, ps = self.parse_options(parameter_s, 'qb', mode='string') |
| | |
| | if ps == '-': |
| | try: |
| | ps = self.shell.user_ns['_dh'][-2] |
| | except IndexError as e: |
| | raise UsageError('%cd -: No previous directory to change to.') from e |
| | |
| | else: |
| | if not os.path.isdir(ps) or 'b' in opts: |
| | bkms = self.shell.db.get('bookmarks', {}) |
| |
|
| | if ps in bkms: |
| | target = bkms[ps] |
| | print('(bookmark:%s) -> %s' % (ps, target)) |
| | ps = target |
| | else: |
| | if 'b' in opts: |
| | raise UsageError("Bookmark '%s' not found. " |
| | "Use '%%bookmark -l' to see your bookmarks." % ps) |
| |
|
| | |
| | if ps: |
| | try: |
| | os.chdir(os.path.expanduser(ps)) |
| | if hasattr(self.shell, 'term_title') and self.shell.term_title: |
| | set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd())) |
| | except OSError: |
| | print(sys.exc_info()[1]) |
| | else: |
| | cwd = pathlib.Path.cwd() |
| | dhist = self.shell.user_ns['_dh'] |
| | if oldcwd != cwd: |
| | dhist.append(cwd) |
| | self.shell.db['dhist'] = compress_dhist(dhist)[-100:] |
| |
|
| | else: |
| | os.chdir(self.shell.home_dir) |
| | if hasattr(self.shell, 'term_title') and self.shell.term_title: |
| | set_term_title(self.shell.term_title_format.format(cwd="~")) |
| | cwd = pathlib.Path.cwd() |
| | dhist = self.shell.user_ns['_dh'] |
| |
|
| | if oldcwd != cwd: |
| | dhist.append(cwd) |
| | self.shell.db['dhist'] = compress_dhist(dhist)[-100:] |
| | if not 'q' in opts and not self.cd_force_quiet and self.shell.user_ns['_dh']: |
| | print(self.shell.user_ns['_dh'][-1]) |
| |
|
| | @line_magic |
| | def env(self, parameter_s=''): |
| | """Get, set, or list environment variables. |
| | |
| | Usage:\\ |
| | |
| | :``%env``: lists all environment variables/values |
| | :``%env var``: get value for var |
| | :``%env var val``: set value for var |
| | :``%env var=val``: set value for var |
| | :``%env var=$val``: set value for var, using python expansion if possible |
| | """ |
| | if parameter_s.strip(): |
| | split = '=' if '=' in parameter_s else ' ' |
| | bits = parameter_s.split(split) |
| | if len(bits) == 1: |
| | key = parameter_s.strip() |
| | if key in os.environ: |
| | return os.environ[key] |
| | else: |
| | err = "Environment does not have key: {0}".format(key) |
| | raise UsageError(err) |
| | if len(bits) > 1: |
| | return self.set_env(parameter_s) |
| | env = dict(os.environ) |
| | |
| | for key in list(env): |
| | if any(s in key.lower() for s in ('key', 'token', 'secret')): |
| | env[key] = '<hidden>' |
| |
|
| | return env |
| |
|
| | @line_magic |
| | def set_env(self, parameter_s): |
| | """Set environment variables. Assumptions are that either "val" is a |
| | name in the user namespace, or val is something that evaluates to a |
| | string. |
| | |
| | Usage:\\ |
| | :``%set_env var val``: set value for var |
| | :``%set_env var=val``: set value for var |
| | :``%set_env var=$val``: set value for var, using python expansion if possible |
| | """ |
| | split = '=' if '=' in parameter_s else ' ' |
| | bits = parameter_s.split(split, 1) |
| | if not parameter_s.strip() or len(bits)<2: |
| | raise UsageError("usage is 'set_env var=val'") |
| | var = bits[0].strip() |
| | val = bits[1].strip() |
| | if re.match(r'.*\s.*', var): |
| | |
| | |
| | |
| | |
| | |
| | |
| | err = "refusing to set env var with whitespace: '{0}'" |
| | err = err.format(val) |
| | raise UsageError(err) |
| | os.environ[var] = val |
| | print('env: {0}={1}'.format(var,val)) |
| |
|
| | @line_magic |
| | def pushd(self, parameter_s=''): |
| | """Place the current dir on stack and change directory. |
| | |
| | Usage:\\ |
| | %pushd ['dirname'] |
| | """ |
| |
|
| | dir_s = self.shell.dir_stack |
| | tgt = os.path.expanduser(parameter_s) |
| | cwd = os.getcwd().replace(self.shell.home_dir,'~') |
| | if tgt: |
| | self.cd(parameter_s) |
| | dir_s.insert(0,cwd) |
| | return self.shell.run_line_magic('dirs', '') |
| |
|
| | @line_magic |
| | def popd(self, parameter_s=''): |
| | """Change to directory popped off the top of the stack. |
| | """ |
| | if not self.shell.dir_stack: |
| | raise UsageError("%popd on empty stack") |
| | top = self.shell.dir_stack.pop(0) |
| | self.cd(top) |
| | print("popd ->",top) |
| |
|
| | @line_magic |
| | def dirs(self, parameter_s=''): |
| | """Return the current directory stack.""" |
| |
|
| | return self.shell.dir_stack |
| |
|
| | @line_magic |
| | def dhist(self, parameter_s=''): |
| | """Print your history of visited directories. |
| | |
| | %dhist -> print full history\\ |
| | %dhist n -> print last n entries only\\ |
| | %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\ |
| | |
| | This history is automatically maintained by the %cd command, and |
| | always available as the global list variable _dh. You can use %cd -<n> |
| | to go to directory number <n>. |
| | |
| | Note that most of time, you should view directory history by entering |
| | cd -<TAB>. |
| | |
| | """ |
| |
|
| | dh = self.shell.user_ns['_dh'] |
| | if parameter_s: |
| | try: |
| | args = map(int,parameter_s.split()) |
| | except: |
| | self.arg_err(self.dhist) |
| | return |
| | if len(args) == 1: |
| | ini,fin = max(len(dh)-(args[0]),0),len(dh) |
| | elif len(args) == 2: |
| | ini,fin = args |
| | fin = min(fin, len(dh)) |
| | else: |
| | self.arg_err(self.dhist) |
| | return |
| | else: |
| | ini,fin = 0,len(dh) |
| | print('Directory history (kept in _dh)') |
| | for i in range(ini, fin): |
| | print("%d: %s" % (i, dh[i])) |
| |
|
| | @skip_doctest |
| | @line_magic |
| | def sc(self, parameter_s=''): |
| | """Shell capture - run shell command and capture output (DEPRECATED use !). |
| | |
| | DEPRECATED. Suboptimal, retained for backwards compatibility. |
| | |
| | You should use the form 'var = !command' instead. Example: |
| | |
| | "%sc -l myfiles = ls ~" should now be written as |
| | |
| | "myfiles = !ls ~" |
| | |
| | myfiles.s, myfiles.l and myfiles.n still apply as documented |
| | below. |
| | |
| | -- |
| | %sc [options] varname=command |
| | |
| | IPython will run the given command using commands.getoutput(), and |
| | will then update the user's interactive namespace with a variable |
| | called varname, containing the value of the call. Your command can |
| | contain shell wildcards, pipes, etc. |
| | |
| | The '=' sign in the syntax is mandatory, and the variable name you |
| | supply must follow Python's standard conventions for valid names. |
| | |
| | (A special format without variable name exists for internal use) |
| | |
| | Options: |
| | |
| | -l: list output. Split the output on newlines into a list before |
| | assigning it to the given variable. By default the output is stored |
| | as a single string. |
| | |
| | -v: verbose. Print the contents of the variable. |
| | |
| | In most cases you should not need to split as a list, because the |
| | returned value is a special type of string which can automatically |
| | provide its contents either as a list (split on newlines) or as a |
| | space-separated string. These are convenient, respectively, either |
| | for sequential processing or to be passed to a shell command. |
| | |
| | For example:: |
| | |
| | # Capture into variable a |
| | In [1]: sc a=ls *py |
| | |
| | # a is a string with embedded newlines |
| | In [2]: a |
| | Out[2]: 'setup.py\\nwin32_manual_post_install.py' |
| | |
| | # which can be seen as a list: |
| | In [3]: a.l |
| | Out[3]: ['setup.py', 'win32_manual_post_install.py'] |
| | |
| | # or as a whitespace-separated string: |
| | In [4]: a.s |
| | Out[4]: 'setup.py win32_manual_post_install.py' |
| | |
| | # a.s is useful to pass as a single command line: |
| | In [5]: !wc -l $a.s |
| | 146 setup.py |
| | 130 win32_manual_post_install.py |
| | 276 total |
| | |
| | # while the list form is useful to loop over: |
| | In [6]: for f in a.l: |
| | ...: !wc -l $f |
| | ...: |
| | 146 setup.py |
| | 130 win32_manual_post_install.py |
| | |
| | Similarly, the lists returned by the -l option are also special, in |
| | the sense that you can equally invoke the .s attribute on them to |
| | automatically get a whitespace-separated string from their contents:: |
| | |
| | In [7]: sc -l b=ls *py |
| | |
| | In [8]: b |
| | Out[8]: ['setup.py', 'win32_manual_post_install.py'] |
| | |
| | In [9]: b.s |
| | Out[9]: 'setup.py win32_manual_post_install.py' |
| | |
| | In summary, both the lists and strings used for output capture have |
| | the following special attributes:: |
| | |
| | .l (or .list) : value as list. |
| | .n (or .nlstr): value as newline-separated string. |
| | .s (or .spstr): value as space-separated string. |
| | """ |
| |
|
| | opts,args = self.parse_options(parameter_s, 'lv') |
| | |
| | try: |
| | |
| | |
| | var,_ = args.split('=', 1) |
| | var = var.strip() |
| | |
| | |
| | |
| | _,cmd = parameter_s.split('=', 1) |
| | except ValueError: |
| | var,cmd = '','' |
| | |
| | split = 'l' in opts |
| | out = self.shell.getoutput(cmd, split=split) |
| | if 'v' in opts: |
| | print('%s ==\n%s' % (var, pformat(out))) |
| | if var: |
| | self.shell.user_ns.update({var:out}) |
| | else: |
| | return out |
| |
|
| | @line_cell_magic |
| | def sx(self, line='', cell=None): |
| | """Shell execute - run shell command and capture output (!! is short-hand). |
| | |
| | %sx command |
| | |
| | IPython will run the given command using commands.getoutput(), and |
| | return the result formatted as a list (split on '\\n'). Since the |
| | output is _returned_, it will be stored in ipython's regular output |
| | cache Out[N] and in the '_N' automatic variables. |
| | |
| | Notes: |
| | |
| | 1) If an input line begins with '!!', then %sx is automatically |
| | invoked. That is, while:: |
| | |
| | !ls |
| | |
| | causes ipython to simply issue system('ls'), typing:: |
| | |
| | !!ls |
| | |
| | is a shorthand equivalent to:: |
| | |
| | %sx ls |
| | |
| | 2) %sx differs from %sc in that %sx automatically splits into a list, |
| | like '%sc -l'. The reason for this is to make it as easy as possible |
| | to process line-oriented shell output via further python commands. |
| | %sc is meant to provide much finer control, but requires more |
| | typing. |
| | |
| | 3) Just like %sc -l, this is a list with special attributes: |
| | :: |
| | |
| | .l (or .list) : value as list. |
| | .n (or .nlstr): value as newline-separated string. |
| | .s (or .spstr): value as whitespace-separated string. |
| | |
| | This is very useful when trying to use such lists as arguments to |
| | system commands.""" |
| | |
| | if cell is None: |
| | |
| | return self.shell.getoutput(line) |
| | else: |
| | opts,args = self.parse_options(line, '', 'out=') |
| | output = self.shell.getoutput(cell) |
| | out_name = opts.get('out', opts.get('o')) |
| | if out_name: |
| | self.shell.user_ns[out_name] = output |
| | else: |
| | return output |
| |
|
| | system = line_cell_magic('system')(sx) |
| | bang = cell_magic('!')(sx) |
| |
|
| | @line_magic |
| | def bookmark(self, parameter_s=''): |
| | """Manage IPython's bookmark system. |
| | |
| | %bookmark <name> - set bookmark to current dir |
| | %bookmark <name> <dir> - set bookmark to <dir> |
| | %bookmark -l - list all bookmarks |
| | %bookmark -d <name> - remove bookmark |
| | %bookmark -r - remove all bookmarks |
| | |
| | You can later on access a bookmarked folder with:: |
| | |
| | %cd -b <name> |
| | |
| | or simply '%cd <name>' if there is no directory called <name> AND |
| | there is such a bookmark defined. |
| | |
| | Your bookmarks persist through IPython sessions, but they are |
| | associated with each profile.""" |
| |
|
| | opts,args = self.parse_options(parameter_s,'drl',mode='list') |
| | if len(args) > 2: |
| | raise UsageError("%bookmark: too many arguments") |
| |
|
| | bkms = self.shell.db.get('bookmarks',{}) |
| |
|
| | if 'd' in opts: |
| | try: |
| | todel = args[0] |
| | except IndexError as e: |
| | raise UsageError( |
| | "%bookmark -d: must provide a bookmark to delete") from e |
| | else: |
| | try: |
| | del bkms[todel] |
| | except KeyError as e: |
| | raise UsageError( |
| | "%%bookmark -d: Can't delete bookmark '%s'" % todel) from e |
| |
|
| | elif 'r' in opts: |
| | bkms = {} |
| | elif 'l' in opts: |
| | bks = sorted(bkms) |
| | if bks: |
| | size = max(map(len, bks)) |
| | else: |
| | size = 0 |
| | fmt = '%-'+str(size)+'s -> %s' |
| | print('Current bookmarks:') |
| | for bk in bks: |
| | print(fmt % (bk, bkms[bk])) |
| | else: |
| | if not args: |
| | raise UsageError("%bookmark: You must specify the bookmark name") |
| | elif len(args)==1: |
| | bkms[args[0]] = os.getcwd() |
| | elif len(args)==2: |
| | bkms[args[0]] = args[1] |
| | self.shell.db['bookmarks'] = bkms |
| |
|
| | @line_magic |
| | def pycat(self, parameter_s=''): |
| | """Show a syntax-highlighted file through a pager. |
| | |
| | This magic is similar to the cat utility, but it will assume the file |
| | to be Python source and will show it with syntax highlighting. |
| | |
| | This magic command can either take a local filename, an url, |
| | an history range (see %history) or a macro as argument. |
| | |
| | If no parameter is given, prints out history of current session up to |
| | this point. :: |
| | |
| | %pycat myscript.py |
| | %pycat 7-27 |
| | %pycat myMacro |
| | %pycat http://www.example.com/myscript.py |
| | """ |
| | try: |
| | cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False) |
| | except (ValueError, IOError): |
| | print("Error: no such file, variable, URL, history range or macro") |
| | return |
| |
|
| | page.page(self.shell.pycolorize(source_to_unicode(cont))) |
| |
|
| | @magic_arguments.magic_arguments() |
| | @magic_arguments.argument( |
| | '-a', '--append', action='store_true', default=False, |
| | help='Append contents of the cell to an existing file. ' |
| | 'The file will be created if it does not exist.' |
| | ) |
| | @magic_arguments.argument( |
| | 'filename', type=str, |
| | help='file to write' |
| | ) |
| | @cell_magic |
| | def writefile(self, line, cell): |
| | """Write the contents of the cell to a file. |
| | |
| | The file will be overwritten unless the -a (--append) flag is specified. |
| | """ |
| | args = magic_arguments.parse_argstring(self.writefile, line) |
| | if re.match(r'^(\'.*\')|(".*")$', args.filename): |
| | filename = os.path.expanduser(args.filename[1:-1]) |
| | else: |
| | filename = os.path.expanduser(args.filename) |
| | |
| | if os.path.exists(filename): |
| | if args.append: |
| | print("Appending to %s" % filename) |
| | else: |
| | print("Overwriting %s" % filename) |
| | else: |
| | print("Writing %s" % filename) |
| | |
| | mode = 'a' if args.append else 'w' |
| | with io.open(filename, mode, encoding='utf-8') as f: |
| | f.write(cell) |
| |
|