Merge branch 'dirstack' of https://github.com/wrywerytwreywery/xonsh into dirstack

This commit is contained in:
adam j hartz 2015-03-21 19:36:50 -04:00
commit 7214087420
3 changed files with 225 additions and 2 deletions

View file

@ -4,9 +4,12 @@ import os
import platform
import builtins
import subprocess
from argparse import ArgumentParser
import shlex
from warnings import warn
from xonsh.dirstack import dirs, pushd, popd
def cd(args, stdin=None):
"""Changes the directory.
@ -14,7 +17,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 +30,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 +91,9 @@ def bash_aliases():
DEFAULT_ALIASES = {
'cd': cd,
'pushd':pushd,
'popd':popd,
'dirs':dirs,
'EOF': exit,
'exit': exit,
'quit': exit,

View file

@ -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

216
xonsh/dirstack.py Normal file
View file

@ -0,0 +1,216 @@
import os
import builtins
from argparse import ArgumentParser
DIRSTACK = []
def pushd(args, stdin=None):
global DIRSTACK
try:
args = pushd_parser.parse_args(args)
except SystemExit:
return None, None
pwd = builtins.__xonsh_env__['PWD']
if args.dir is None:
try:
new_pwd = DIRSTACK.pop(0)
except:
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:])
assert num >= 0
except:
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('+'):
if num == len(DIRSTACK):
new_pwd = None
else:
new_pwd = DIRSTACK.pop(len(DIRSTACK)-1-num)
elif args.dir.startswith('-'):
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:
DIRSTACK.insert(0, os.path.expanduser(pwd))
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 builtins.__xonsh_env__.get('QUIET_PUSHD', False):
return dirs([], None)
return None, None
def popd(args, stdin=None):
global DIRSTACK
try:
args = pushd_parser.parse_args(args)
except SystemExit:
return None, None
if args.dir is None:
try:
new_pwd = DIRSTACK.pop(0)
except:
e = 'popd: Directory stack is empty\n'
return None, e
else:
try:
num = int(args.dir[1:])
assert num >= 0
except:
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('+'):
if num == len(DIRSTACK):
new_pwd = DIRSTACK.pop(0)
else:
new_pwd = None
DIRSTACK.pop(len(DIRSTACK)-1-num)
elif args.dir.startswith('-'):
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 builtins.__xonsh_env__.get('QUIET_PUSHD', False):
return dirs([], None)
return None, None
def dirs(args, stdin=None):
global DIRSTACK
dirstack = [os.path.expanduser(builtins.__xonsh_env__['PWD'])] + DIRSTACK
try:
args = dirs_parser.parse_args(args)
except SystemExit:
return None, None
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:])
assert num >= 0
except:
e = 'Invalid argument to dirs: {0}\n'
return None, e.format(N)
if num >= len(o):
e = 'Too few elements in dirstack ({0} elements)\n'
return None, e.format(len(o))
if N.startswith('-'):
idx = num
elif N.startswith('+'):
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')
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')
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')