mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-06 09:20:57 +01:00
Merge branch 'wrywerytwreywery-dirstack'
This commit is contained in:
commit
ce327ccd7b
5 changed files with 311 additions and 2 deletions
10
docs/api/dirstack.rst
Normal file
10
docs/api/dirstack.rst
Normal file
|
@ -0,0 +1,10 @@
|
|||
.. _xonsh_dirstack:
|
||||
|
||||
******************************************************
|
||||
Directory Stack (``xonsh.dirstack``)
|
||||
******************************************************
|
||||
|
||||
.. automodule:: xonsh.dirstack
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
|
@ -24,6 +24,7 @@ For those of you who want the gritty details.
|
|||
built_ins
|
||||
environ
|
||||
aliases
|
||||
dirstack
|
||||
inspectors
|
||||
completer
|
||||
shell
|
||||
|
|
|
@ -7,6 +7,8 @@ import subprocess
|
|||
import shlex
|
||||
from warnings import warn
|
||||
|
||||
from xonsh.dirstack import dirs, pushd, popd
|
||||
|
||||
def cd(args, stdin=None):
|
||||
"""Changes the directory.
|
||||
|
||||
|
@ -14,7 +16,7 @@ def cd(args, stdin=None):
|
|||
changes to the current user's home directory.
|
||||
"""
|
||||
env = builtins.__xonsh_env__
|
||||
cur_oldpwd = env.get('OLDPWD') or os.getcwd()
|
||||
cur_oldpwd = env.get('OLDPWD', os.getcwd())
|
||||
if len(args) == 0:
|
||||
d = os.path.expanduser('~')
|
||||
elif len(args) == 1:
|
||||
|
@ -27,6 +29,7 @@ def cd(args, stdin=None):
|
|||
return '', 'cd: no such file or directory: {0}\n'.format(d)
|
||||
if not os.path.isdir(d):
|
||||
return '', 'cd: {0} is not a directory\n'.format(d)
|
||||
|
||||
env['OLDPWD'] = os.getcwd()
|
||||
os.chdir(d)
|
||||
env['PWD'] = os.getcwd()
|
||||
|
@ -87,6 +90,9 @@ def bash_aliases():
|
|||
|
||||
DEFAULT_ALIASES = {
|
||||
'cd': cd,
|
||||
'pushd':pushd,
|
||||
'popd':popd,
|
||||
'dirs':dirs,
|
||||
'EOF': exit,
|
||||
'exit': exit,
|
||||
'quit': exit,
|
||||
|
|
|
@ -414,7 +414,7 @@ def load_builtins(execer=None):
|
|||
builtins.evalx = None if execer is None else execer.eval
|
||||
builtins.execx = None if execer is None else execer.exec
|
||||
builtins.compilex = None if execer is None else execer.compile
|
||||
builtins.aliases = Aliases(DEFAULT_ALIASES)
|
||||
builtins.default_aliases = builtins.aliases = Aliases(DEFAULT_ALIASES)
|
||||
builtins.aliases.update(bash_aliases())
|
||||
BUILTINS_LOADED = True
|
||||
|
||||
|
@ -437,6 +437,7 @@ def unload_builtins():
|
|||
'__xonsh_pyexit__', '__xonsh_pyquit__',
|
||||
'__xonsh_subproc_captured__', '__xonsh_subproc_uncaptured__',
|
||||
'__xonsh_execer__', 'evalx', 'execx', 'compilex',
|
||||
'default_aliases'
|
||||
]
|
||||
for name in names:
|
||||
if hasattr(builtins, name):
|
||||
|
|
291
xonsh/dirstack.py
Normal file
291
xonsh/dirstack.py
Normal file
|
@ -0,0 +1,291 @@
|
|||
"""Directory stack and associated utilities for the xonsh shell.
|
||||
"""
|
||||
import os
|
||||
import builtins
|
||||
from argparse import ArgumentParser
|
||||
|
||||
DIRSTACK = []
|
||||
"""
|
||||
A list containing the currently remembered directories.
|
||||
"""
|
||||
|
||||
|
||||
def pushd(args, stdin=None):
|
||||
"""
|
||||
xonsh command: pushd
|
||||
|
||||
Adds a directory to the top of the directory stack, or rotates the stack,
|
||||
making the new top of the stack the current working directory.
|
||||
"""
|
||||
global DIRSTACK
|
||||
|
||||
try:
|
||||
args = pushd_parser.parse_args(args)
|
||||
except SystemExit:
|
||||
return None, None
|
||||
|
||||
env = builtins.__xonsh_env__
|
||||
|
||||
pwd = env['PWD']
|
||||
|
||||
if env.get('PUSHD_MINUS', False):
|
||||
BACKWARD = '-'
|
||||
FORWARD = '+'
|
||||
else:
|
||||
BACKWARD = '+'
|
||||
FORWARD = '-'
|
||||
|
||||
if args.dir is None:
|
||||
try:
|
||||
new_pwd = DIRSTACK.pop(0)
|
||||
except IndexError:
|
||||
e = 'pushd: Directory stack is empty\n'
|
||||
return None, e
|
||||
elif os.path.isdir(args.dir):
|
||||
new_pwd = args.dir
|
||||
else:
|
||||
try:
|
||||
num = int(args.dir[1:])
|
||||
except ValueError:
|
||||
e = 'Invalid argument to pushd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
|
||||
if num < 0:
|
||||
e = 'Invalid argument to pushd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
|
||||
if num > len(DIRSTACK):
|
||||
e = 'Too few elements in dirstack ({0} elements)\n'
|
||||
return None, e.format(len(DIRSTACK))
|
||||
elif args.dir.startswith(FORWARD):
|
||||
if num == len(DIRSTACK):
|
||||
new_pwd = None
|
||||
else:
|
||||
new_pwd = DIRSTACK.pop(len(DIRSTACK)-1-num)
|
||||
elif args.dir.startswith(BACKWARD):
|
||||
if num == 0:
|
||||
new_pwd = None
|
||||
else:
|
||||
new_pwd = DIRSTACK.pop(num-1)
|
||||
else:
|
||||
e = 'Invalid argument to pushd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
if new_pwd is not None:
|
||||
o = None
|
||||
e = None
|
||||
if args.cd:
|
||||
DIRSTACK.insert(0, os.path.expanduser(pwd))
|
||||
o, e = builtins.default_aliases['cd']([new_pwd], None)
|
||||
else:
|
||||
DIRSTACK.insert(0, os.path.expanduser(os.path.abspath(new_pwd)))
|
||||
|
||||
if e is not None:
|
||||
return None, e
|
||||
|
||||
maxsize = env.get('DIRSTACK_SIZE', 20)
|
||||
if len(DIRSTACK) > maxsize:
|
||||
DIRSTACK = DIRSTACK[:maxsize]
|
||||
|
||||
if not args.quiet and not env.get('PUSHD_SILENT', False):
|
||||
return dirs([], None)
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def popd(args, stdin=None):
|
||||
"""
|
||||
xonsh command: popd
|
||||
|
||||
Removes entries from the directory stack.
|
||||
"""
|
||||
global DIRSTACK
|
||||
|
||||
try:
|
||||
args = pushd_parser.parse_args(args)
|
||||
except SystemExit:
|
||||
return None, None
|
||||
|
||||
env = builtins.__xonsh_env__
|
||||
|
||||
if env.get('PUSHD_MINUS', False):
|
||||
BACKWARD = '-'
|
||||
FORWARD = '+'
|
||||
else:
|
||||
BACKWARD = '-'
|
||||
FORWARD = '+'
|
||||
|
||||
if args.dir is None:
|
||||
try:
|
||||
new_pwd = DIRSTACK.pop(0)
|
||||
except IndexError:
|
||||
e = 'popd: Directory stack is empty\n'
|
||||
return None, e
|
||||
else:
|
||||
try:
|
||||
num = int(args.dir[1:])
|
||||
except ValueError:
|
||||
e = 'Invalid argument to popd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
|
||||
if num < 0:
|
||||
e = 'Invalid argument to popd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
|
||||
if num > len(DIRSTACK):
|
||||
e = 'Too few elements in dirstack ({0} elements)\n'
|
||||
return None, e.format(len(DIRSTACK))
|
||||
elif args.dir.startswith(FORWARD):
|
||||
if num == len(DIRSTACK):
|
||||
new_pwd = DIRSTACK.pop(0)
|
||||
else:
|
||||
new_pwd = None
|
||||
DIRSTACK.pop(len(DIRSTACK)-1-num)
|
||||
elif args.dir.startswith(BACKWARD):
|
||||
if num == 0:
|
||||
new_pwd = DIRSTACK.pop(0)
|
||||
else:
|
||||
new_pwd = None
|
||||
DIRSTACK.pop(num-1)
|
||||
else:
|
||||
e = 'Invalid argument to popd: {0}\n'
|
||||
return None, e.format(args.dir)
|
||||
|
||||
if new_pwd is not None:
|
||||
o = None
|
||||
e = None
|
||||
if args.cd:
|
||||
o, e = builtins.default_aliases['cd']([new_pwd], None)
|
||||
|
||||
if e is not None:
|
||||
return None, e
|
||||
|
||||
if not args.quiet and not env.get('PUSHD_SILENT', False):
|
||||
return dirs([], None)
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def dirs(args, stdin=None):
|
||||
"""
|
||||
xonsh command: dirs
|
||||
|
||||
Displays the list of currently remembered directories. Can also be used
|
||||
to clear the directory stack.
|
||||
"""
|
||||
global DIRSTACK
|
||||
dirstack = [os.path.expanduser(builtins.__xonsh_env__['PWD'])] + DIRSTACK
|
||||
|
||||
try:
|
||||
args = dirs_parser.parse_args(args)
|
||||
except SystemExit:
|
||||
return None, None
|
||||
|
||||
env = builtins.__xonsh_env__
|
||||
|
||||
if env.get('PUSHD_MINUS', False):
|
||||
BACKWARD = '-'
|
||||
FORWARD = '+'
|
||||
else:
|
||||
BACKWARD = '-'
|
||||
FORWARD = '+'
|
||||
|
||||
if args.clear:
|
||||
dirstack = []
|
||||
return None, None
|
||||
|
||||
if args.long:
|
||||
o = dirstack
|
||||
else:
|
||||
d = os.path.expanduser('~')
|
||||
o = [i.replace(d, '~') for i in dirstack]
|
||||
|
||||
if args.verbose:
|
||||
out = ''
|
||||
pad = len(str(len(o)-1))
|
||||
for (ix, e) in enumerate(o):
|
||||
blanks = ' ' * (pad - len(str(ix)))
|
||||
out += '\n{0}{1} {2}'.format(blanks, ix, e)
|
||||
out = out[1:]
|
||||
elif args.print_long:
|
||||
out = '\n'.join(o)
|
||||
else:
|
||||
out = ' '.join(o)
|
||||
|
||||
N = args.N
|
||||
if N is not None:
|
||||
try:
|
||||
num = int(N[1:])
|
||||
except ValueError:
|
||||
e = 'Invalid argument to dirs: {0}\n'
|
||||
return None, e.format(N)
|
||||
|
||||
if num < 0:
|
||||
e = 'Invalid argument to dirs: {0}\n'
|
||||
return None, e.format(len(o))
|
||||
|
||||
if num >= len(o):
|
||||
e = 'Too few elements in dirstack ({0} elements)\n'
|
||||
return None, e.format(len(o))
|
||||
|
||||
if N.startswith(BACKWARD):
|
||||
idx = num
|
||||
elif N.startswith(FORWARD):
|
||||
idx = len(o)-1-num
|
||||
else:
|
||||
e = 'Invalid argument to dirs: {0}\n'
|
||||
return None, e.format(N)
|
||||
|
||||
out = o[idx]
|
||||
|
||||
return out+'\n', None
|
||||
|
||||
|
||||
pushd_parser = ArgumentParser(prog="pushd")
|
||||
pushd_parser.add_argument('dir', nargs='?')
|
||||
pushd_parser.add_argument('-n',
|
||||
dest='cd',
|
||||
help='Suppresses the normal change of directory when'
|
||||
' adding directories to the stack, so that only the'
|
||||
' stack is manipulated.',
|
||||
action='store_false')
|
||||
pushd_parser.add_argument('-q',
|
||||
dest='quiet',
|
||||
help='Do not call dirs, regardless of $PUSHD_SILENT',
|
||||
action='store_true')
|
||||
|
||||
popd_parser = ArgumentParser(prog="popd")
|
||||
popd_parser.add_argument('dir', nargs='?')
|
||||
popd_parser.add_argument('-n',
|
||||
dest='cd',
|
||||
help='Suppresses the normal change of directory when'
|
||||
' adding directories to the stack, so that only the'
|
||||
' stack is manipulated.',
|
||||
action='store_false')
|
||||
popd_parser.add_argument('-q',
|
||||
dest='quiet',
|
||||
help='Do not call dirs, regardless of $PUSHD_SILENT',
|
||||
action='store_true')
|
||||
|
||||
dirs_parser = ArgumentParser(prog="dirs")
|
||||
dirs_parser.add_argument('N', nargs='?')
|
||||
dirs_parser.add_argument('-c',
|
||||
dest='clear',
|
||||
help='Clears the directory stack by deleting all of'
|
||||
' the entries.',
|
||||
action='store_true')
|
||||
dirs_parser.add_argument('-p',
|
||||
dest='print_long',
|
||||
help='Print the directory stack with one entry per'
|
||||
' line.',
|
||||
action='store_true')
|
||||
dirs_parser.add_argument('-v',
|
||||
dest='verbose',
|
||||
help='Print the directory stack with one entry per'
|
||||
' line, prefixing each entry with its index in the'
|
||||
' stack.',
|
||||
action='store_true')
|
||||
dirs_parser.add_argument('-l',
|
||||
dest='long',
|
||||
help='Produces a longer listing; the default listing'
|
||||
' format uses a tilde to denote the home directory.',
|
||||
action='store_true')
|
Loading…
Add table
Reference in a new issue