From 0889913cfdd2d7904e858ae869610e25032e1e21 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Mon, 16 Mar 2015 05:52:13 -0400 Subject: [PATCH 01/16] dirstack skeleton --- xonsh/aliases.py | 16 ++++++++++++++++ xonsh/environ.py | 3 +++ 2 files changed, 19 insertions(+) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index efa69e0ad..0e5d29cb4 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -4,6 +4,7 @@ import os import platform import builtins import subprocess +from argparse import ArgumentParser def cd(args, stdin=None): """Changes the directory. @@ -25,6 +26,18 @@ def cd(args, stdin=None): builtins.__xonsh_env__['PWD'] = os.getcwd() return None, None +pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") +def pushd(args, stdin=None): + return None, None + +popd_parser = ArgumentParser(description="popd: pop from the directory stack") +def popd(args, stdin=None): + return None, None + +dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack") +def dirs(args, stdin=None): + return None, None + def exit(args, stdin=None): """Sends signal to exit shell.""" builtins.__xonsh_exit__ = True @@ -57,6 +70,9 @@ def source_bash(args, stdin=None): DEFAULT_ALIASES = { 'cd': cd, + 'pushd':pushd, + 'popd':popd, + 'dirs':dirs, 'EOF': exit, 'exit': exit, 'source-bash': source_bash, diff --git a/xonsh/environ.py b/xonsh/environ.py index 86cfb475c..167b4aa23 100644 --- a/xonsh/environ.py +++ b/xonsh/environ.py @@ -93,6 +93,7 @@ def multiline_prompt(): BASE_ENV = { 'INDENT': ' ', + 'XONSH_DIRSTACK': None, 'PROMPT': default_prompt, 'MULTILINE_PROMPT': '.', 'XONSHRC': os.path.expanduser('~/.xonshrc'), @@ -149,6 +150,8 @@ def default_env(env=None): """Constructs a default xonsh environment.""" # in order of increasing precedence ctx = dict(BASE_ENV) + if ctx.get('XONSH_DIRSTACK',None) is None: + ctx['XONSH_DIRSTACK'] = [] ctx.update(os.environ) ctx.update(bash_env()) if env is not None: From 68f5e4dba660e65163d884b9fb6abffdb5c2f9ce Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 18:35:59 -0400 Subject: [PATCH 02/16] implemented dirs --- xonsh/dirstack.py | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 xonsh/dirstack.py diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py new file mode 100644 index 000000000..a9d8651d6 --- /dev/null +++ b/xonsh/dirstack.py @@ -0,0 +1,96 @@ +import os +import builtins + +from argparse import ArgumentParser + +DIRSTACK = [] + +def get_dirstack(): + global DIRSTACK + return [builtins.__xonsh_env__['PWD']] + DIRSTACK + +def set_dirstack(x): + global DIRSTACK + DIRSTACK = DIRSTACK[1:] + +pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") +def pushd(args, stdin=None): + dirstack = get_dirstack() + return None, None + +popd_parser = ArgumentParser(description="popd: pop from the directory stack") +def popd(args, stdin=None): + dirstack = get_dirstack() + return None, None + + +def dirs(args, stdin=None): + dirstack = get_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:]) + except: + return None, 'Invalid argument to dirs: {0}\n'.format(N) + if num >= len(o): + e = 'Too few elements in dirstack ({1} elements)\n'.format(len(o)) + return None, e + if N.startswith('-'): + idx = num + elif N.startswith('+'): + idx = len(o)-1-num + else: + return None, 'Invalid argument to dirs: {0}\n'.format(N) + + out = o[idx] + + return out+'\n', None + + +dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack", ) +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') +dirs_parser.add_argument('N', nargs='?') + From 5b12120bbc7a9a3abf73fb7796f675fdcbb9a7d4 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 22:12:25 -0400 Subject: [PATCH 03/16] implement pushd --- xonsh/dirstack.py | 75 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index a9d8651d6..d371bceb2 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -1,21 +1,57 @@ import os import builtins - from argparse import ArgumentParser DIRSTACK = [] -def get_dirstack(): - global DIRSTACK - return [builtins.__xonsh_env__['PWD']] + DIRSTACK - -def set_dirstack(x): - global DIRSTACK - DIRSTACK = DIRSTACK[1:] - -pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") def pushd(args, stdin=None): - dirstack = get_dirstack() + global DIRSTACK + + try: + args = pushd_parser.parse_args(args) + except SystemExit: + return None, None + + pwd = builtins.__xonsh_env__['PWD'] + + if args.dir is None: + new_pwd = DIRSTACK.pop(0) + elif os.path.isdir(args.dir): + new_pwd = args.dir + else: + try: + num = int(args.dir[1:]) + assert num >=0 + except: + return None, 'Invalid argument to pushd: {0}\n'.format(args.dir) + if num > len(DIRSTACK): + return None, 'Too few elements in dirstack ({0} elements)\n'.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: + return None, 'Invalid argument to pushd: {0}\n'.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 popd_parser = ArgumentParser(description="popd: pop from the directory stack") @@ -23,9 +59,9 @@ def popd(args, stdin=None): dirstack = get_dirstack() return None, None - def dirs(args, stdin=None): - dirstack = get_dirstack() + global DIRSTACK + dirstack = [os.path.expanduser(builtins.__xonsh_env__['PWD'])] + DIRSTACK try: args = dirs_parser.parse_args(args) @@ -58,11 +94,11 @@ def dirs(args, stdin=None): if N is not None: try: num = int(N[1:]) + assert num >=0 except: return None, 'Invalid argument to dirs: {0}\n'.format(N) if num >= len(o): - e = 'Too few elements in dirstack ({1} elements)\n'.format(len(o)) - return None, e + return None, 'Too few elements in dirstack ({0} elements)\n'.format(len(o)) if N.startswith('-'): idx = num elif N.startswith('+'): @@ -74,8 +110,14 @@ def dirs(args, stdin=None): return out+'\n', None +pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") +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('dir', nargs='?') -dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack", ) +dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack", add_help=False) dirs_parser.add_argument('-c', dest='clear', help='Clears the directory stack by deleting all of the entries', @@ -93,4 +135,3 @@ dirs_parser.add_argument('-l', help='Produces a longer listing; the default listing format uses a tilde to denote the home directory.', action='store_true') dirs_parser.add_argument('N', nargs='?') - From 217d47dd0ea83a77f848b1d51ecf4a8b3b34f498 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 22:12:45 -0400 Subject: [PATCH 04/16] make the default aliases available to dirstack.py --- xonsh/aliases.py | 14 ++------------ xonsh/built_ins.py | 2 +- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index 1bd787daa..f36646b56 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -8,6 +8,8 @@ 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. @@ -34,18 +36,6 @@ def cd(args, stdin=None): env['PWD'] = os.getcwd() return None, None -pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") -def pushd(args, stdin=None): - return None, None - -popd_parser = ArgumentParser(description="popd: pop from the directory stack") -def popd(args, stdin=None): - return None, None - -dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack") -def dirs(args, stdin=None): - return None, None - def exit(args, stdin=None): """Sends signal to exit shell.""" builtins.__xonsh_exit__ = True diff --git a/xonsh/built_ins.py b/xonsh/built_ins.py index 20aed081b..c6be51633 100644 --- a/xonsh/built_ins.py +++ b/xonsh/built_ins.py @@ -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 From d4a1cdb3e14da158c3013beb2263a5b0ec4d4407 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 22:26:43 -0400 Subject: [PATCH 05/16] implemented popd --- xonsh/dirstack.py | 63 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index d371bceb2..5f967d7e0 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -15,7 +15,10 @@ def pushd(args, stdin=None): pwd = builtins.__xonsh_env__['PWD'] if args.dir is None: - new_pwd = DIRSTACK.pop(0) + try: + new_pwd = DIRSTACK.pop(0) + except: + return None, 'pushd: Directory stack is empty\n' elif os.path.isdir(args.dir): new_pwd = args.dir else: @@ -54,9 +57,54 @@ def pushd(args, stdin=None): return None, None -popd_parser = ArgumentParser(description="popd: pop from the directory stack") def popd(args, stdin=None): - dirstack = get_dirstack() + 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: + return None, 'popd: Directory stack is empty\n' + else: + try: + num = int(args.dir[1:]) + assert num >=0 + except: + return None, 'Invalid argument to popd: {0}\n'.format(args.dir) + if num > len(DIRSTACK): + return None, 'Too few elements in dirstack ({0} elements)\n'.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: + return None, 'Invalid argument to popd: {0}\n'.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): @@ -110,6 +158,7 @@ def dirs(args, stdin=None): return out+'\n', None + pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") pushd_parser.add_argument('-n', dest='cd', @@ -117,6 +166,14 @@ pushd_parser.add_argument('-n', action='store_false') pushd_parser.add_argument('dir', nargs='?') +popd_parser = ArgumentParser(description="popd: pop from the directory stack") +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('dir', nargs='?') + + dirs_parser = ArgumentParser(description="dirs: view and manipulate the directory stack", add_help=False) dirs_parser.add_argument('-c', dest='clear', From b35b91b7cf8994947260924ad19459538b5f053d Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 22:41:45 -0400 Subject: [PATCH 06/16] PEP8 fixes --- xonsh/dirstack.py | 110 +++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 5f967d7e0..50959c2fb 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -4,6 +4,7 @@ from argparse import ArgumentParser DIRSTACK = [] + def pushd(args, stdin=None): global DIRSTACK @@ -18,17 +19,20 @@ def pushd(args, stdin=None): try: new_pwd = DIRSTACK.pop(0) except: - return None, 'pushd: Directory stack is empty\n' + 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 + assert num >= 0 except: - return None, 'Invalid argument to pushd: {0}\n'.format(args.dir) + e = 'Invalid argument to pushd: {0}\n' + return None, e.format(args.dir) if num > len(DIRSTACK): - return None, 'Too few elements in dirstack ({0} elements)\n'.format(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 @@ -40,7 +44,8 @@ def pushd(args, stdin=None): else: new_pwd = DIRSTACK.pop(num-1) else: - return None, 'Invalid argument to pushd: {0}\n'.format(args.dir) + 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)) @@ -57,6 +62,7 @@ def pushd(args, stdin=None): return None, None + def popd(args, stdin=None): global DIRSTACK @@ -69,15 +75,18 @@ def popd(args, stdin=None): try: new_pwd = DIRSTACK.pop(0) except: - return None, 'popd: Directory stack is empty\n' + e = 'popd: Directory stack is empty\n' + return None, e else: try: num = int(args.dir[1:]) - assert num >=0 + assert num >= 0 except: - return None, 'Invalid argument to popd: {0}\n'.format(args.dir) + e = 'Invalid argument to popd: {0}\n' + return None, e.format(args.dir) if num > len(DIRSTACK): - return None, 'Too few elements in dirstack ({0} elements)\n'.format(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) @@ -91,8 +100,9 @@ def popd(args, stdin=None): new_pwd = None DIRSTACK.pop(num-1) else: - return None, 'Invalid argument to popd: {0}\n'.format(args.dir) - + e = 'Invalid argument to popd: {0}\n' + return None, e.format(args.dir) + if new_pwd is not None: o = None e = None @@ -107,6 +117,7 @@ def popd(args, stdin=None): return None, None + def dirs(args, stdin=None): global DIRSTACK dirstack = [os.path.expanduser(builtins.__xonsh_env__['PWD'])] + DIRSTACK @@ -142,53 +153,64 @@ def dirs(args, stdin=None): if N is not None: try: num = int(N[1:]) - assert num >=0 + assert num >= 0 except: - return None, 'Invalid argument to dirs: {0}\n'.format(N) + e = 'Invalid argument to dirs: {0}\n' + return None, e.format(N) if num >= len(o): - return None, 'Too few elements in dirstack ({0} elements)\n'.format(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 + idx = len(o)-1-num else: - return None, 'Invalid argument to dirs: {0}\n'.format(N) + e = 'Invalid argument to dirs: {0}\n' + return None, e.format(N) out = o[idx] return out+'\n', None -pushd_parser = ArgumentParser(description="pushd: push onto the directory stack") -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 = 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(description="popd: pop from the directory stack") -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 = 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(description="dirs: view and manipulate the directory stack", add_help=False) -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') +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') From 5d465e343b5b74b6de73e855538ffa25aff36235 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Fri, 20 Mar 2015 22:43:40 -0400 Subject: [PATCH 07/16] remove superfluous environment variable --- xonsh/environ.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/xonsh/environ.py b/xonsh/environ.py index d45969cf4..7a2275cee 100644 --- a/xonsh/environ.py +++ b/xonsh/environ.py @@ -105,7 +105,6 @@ def multiline_prompt(): BASE_ENV = { 'INDENT': ' ', - 'XONSH_DIRSTACK': None, 'PROMPT': default_prompt, 'MULTILINE_PROMPT': '.', 'XONSHRC': os.path.expanduser('~/.xonshrc'), @@ -162,8 +161,6 @@ def default_env(env=None): """Constructs a default xonsh environment.""" # in order of increasing precedence ctx = dict(BASE_ENV) - if ctx.get('XONSH_DIRSTACK',None) is None: - ctx['XONSH_DIRSTACK'] = [] ctx.update(os.environ) ctx.update(bash_env()) if env is not None: From 84323fd3dffe19820cdf0e375cca448f72308ce6 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 19:54:13 -0400 Subject: [PATCH 08/16] cleanup --- xonsh/aliases.py | 1 - xonsh/built_ins.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/xonsh/aliases.py b/xonsh/aliases.py index f36646b56..2b99f452e 100644 --- a/xonsh/aliases.py +++ b/xonsh/aliases.py @@ -4,7 +4,6 @@ import os import platform import builtins import subprocess -from argparse import ArgumentParser import shlex from warnings import warn diff --git a/xonsh/built_ins.py b/xonsh/built_ins.py index 373eeafc3..99d1d2175 100644 --- a/xonsh/built_ins.py +++ b/xonsh/built_ins.py @@ -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): From c2496fc59623f97d2f97f6d24c146366303f78c6 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 19:54:46 -0400 Subject: [PATCH 09/16] use bash dirstack convention by default, and support PUSHD_MINUS --- xonsh/dirstack.py | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 50959c2fb..0ed0fd0bf 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -13,7 +13,16 @@ def pushd(args, stdin=None): except SystemExit: return None, None - pwd = builtins.__xonsh_env__['PWD'] + env = builtins.__xonsh_env__ + + pwd = env['PWD'] + + if env.get('PUSHD_MINUS', False): + BACKWARD = '-' + FORWARD = '+' + else: + BACKWARD = '+' + FORWARD = '-' if args.dir is None: try: @@ -33,12 +42,12 @@ def pushd(args, stdin=None): if num > len(DIRSTACK): e = 'Too few elements in dirstack ({0} elements)\n' return None, e.format(len(DIRSTACK)) - elif args.dir.startswith('+'): + 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('-'): + elif args.dir.startswith(BACKWARD): if num == 0: new_pwd = None else: @@ -57,7 +66,7 @@ def pushd(args, stdin=None): if e is not None: return None, e - if not builtins.__xonsh_env__.get('QUIET_PUSHD', False): + if not builtins.__xonsh_env__.get('PUSHD_SILENT', False): return dirs([], None) return None, None @@ -71,6 +80,16 @@ def popd(args, stdin=None): 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) @@ -87,13 +106,13 @@ def popd(args, stdin=None): if num > len(DIRSTACK): e = 'Too few elements in dirstack ({0} elements)\n' return None, e.format(len(DIRSTACK)) - elif args.dir.startswith('+'): + 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('-'): + elif args.dir.startswith(BACKWARD): if num == 0: new_pwd = DIRSTACK.pop(0) else: @@ -112,7 +131,7 @@ def popd(args, stdin=None): if e is not None: return None, e - if not builtins.__xonsh_env__.get('QUIET_PUSHD', False): + if not builtins.__xonsh_env__.get('PUSHD_SILENT', False): return dirs([], None) return None, None @@ -127,6 +146,15 @@ def dirs(args, stdin=None): 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 @@ -160,9 +188,9 @@ def dirs(args, stdin=None): if num >= len(o): e = 'Too few elements in dirstack ({0} elements)\n' return None, e.format(len(o)) - if N.startswith('-'): + if N.startswith(BACKWARD): idx = num - elif N.startswith('+'): + elif N.startswith(FORWARD): idx = len(o)-1-num else: e = 'Invalid argument to dirs: {0}\n' From 6bd814c8b9dec2a8f59629301a280d542b9b1136 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:01:10 -0400 Subject: [PATCH 10/16] documentation for dirstack module --- docs/api/dirstack.rst | 10 ++++++++++ docs/api/index.rst | 1 + 2 files changed, 11 insertions(+) create mode 100644 docs/api/dirstack.rst diff --git a/docs/api/dirstack.rst b/docs/api/dirstack.rst new file mode 100644 index 000000000..881bc908d --- /dev/null +++ b/docs/api/dirstack.rst @@ -0,0 +1,10 @@ +.. _xonsh_dirstack: + +****************************************************** +Directory Stack (``xonsh.dirstack``) +****************************************************** + +.. automodule:: xonsh.dirstack + :members: + :undoc-members: + :inherited-members: diff --git a/docs/api/index.rst b/docs/api/index.rst index 407ad45ba..f0f3f9b14 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -24,6 +24,7 @@ For those of you who want the gritty details. built_ins environ aliases + dirstack inspectors completer shell From 4c91c84559b9e2b26f6f9d226122c8d325151f34 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:15:26 -0400 Subject: [PATCH 11/16] documentation for dirstack module --- xonsh/dirstack.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 0ed0fd0bf..d4e212e00 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -1,11 +1,21 @@ +"""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: @@ -73,6 +83,11 @@ def pushd(args, stdin=None): def popd(args, stdin=None): + """ + xonsh command: popd + + Removes entries from the directory stack. + """ global DIRSTACK try: @@ -138,6 +153,12 @@ def popd(args, stdin=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 From 81d3616c46a54bd4b5e8a11a76944a03aff35b57 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:27:54 -0400 Subject: [PATCH 12/16] add quiet mode to pushd and popd --- xonsh/dirstack.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index d4e212e00..0eb28850b 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -76,7 +76,7 @@ def pushd(args, stdin=None): if e is not None: return None, e - if not builtins.__xonsh_env__.get('PUSHD_SILENT', False): + if not args.quiet and not env.get('PUSHD_SILENT', False): return dirs([], None) return None, None @@ -146,7 +146,7 @@ def popd(args, stdin=None): if e is not None: return None, e - if not builtins.__xonsh_env__.get('PUSHD_SILENT', False): + if not args.quiet and not env.get('PUSHD_SILENT', False): return dirs([], None) return None, None @@ -230,6 +230,10 @@ pushd_parser.add_argument('-n', ' 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='?') @@ -239,6 +243,10 @@ popd_parser.add_argument('-n', ' 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='?') From fca90ec0ddcd25a31613b946f4021e07058f57d3 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:29:28 -0400 Subject: [PATCH 13/16] maximum dirstack size --- xonsh/dirstack.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 0eb28850b..82066b4b3 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -76,6 +76,10 @@ def pushd(args, stdin=None): 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) From 4e9fe713944575c20b4242d5fcd32a4b65f41a63 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:48:50 -0400 Subject: [PATCH 14/16] pushd bugfix --- xonsh/dirstack.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 82066b4b3..828e67053 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -66,12 +66,13 @@ def pushd(args, stdin=None): 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: + 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 From 8e3af41a538ec2ec793e63feef5849ad335f8417 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 20:50:06 -0400 Subject: [PATCH 15/16] dirstack: PEP8 fixes --- xonsh/dirstack.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index 828e67053..e62ec06ca 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -9,11 +9,12 @@ 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, + + 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 @@ -90,7 +91,7 @@ def pushd(args, stdin=None): def popd(args, stdin=None): """ xonsh command: popd - + Removes entries from the directory stack. """ global DIRSTACK @@ -109,7 +110,6 @@ def popd(args, stdin=None): BACKWARD = '-' FORWARD = '+' - if args.dir is None: try: new_pwd = DIRSTACK.pop(0) @@ -160,7 +160,7 @@ def popd(args, stdin=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. """ From 1f7024e2840c354cceb82ea8a50f33a262177578 Mon Sep 17 00:00:00 2001 From: adam j hartz Date: Sat, 21 Mar 2015 21:13:11 -0400 Subject: [PATCH 16/16] dirstack: small refactoring --- xonsh/dirstack.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/xonsh/dirstack.py b/xonsh/dirstack.py index e62ec06ca..dc86622ff 100644 --- a/xonsh/dirstack.py +++ b/xonsh/dirstack.py @@ -38,7 +38,7 @@ def pushd(args, stdin=None): if args.dir is None: try: new_pwd = DIRSTACK.pop(0) - except: + except IndexError: e = 'pushd: Directory stack is empty\n' return None, e elif os.path.isdir(args.dir): @@ -46,10 +46,14 @@ def pushd(args, stdin=None): else: try: num = int(args.dir[1:]) - assert num >= 0 - except: + 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)) @@ -113,16 +117,20 @@ def popd(args, stdin=None): if args.dir is None: try: new_pwd = DIRSTACK.pop(0) - except: + except IndexError: e = 'popd: Directory stack is empty\n' return None, e else: try: num = int(args.dir[1:]) - assert num >= 0 - except: + 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)) @@ -207,13 +215,18 @@ def dirs(args, stdin=None): if N is not None: try: num = int(N[1:]) - assert num >= 0 - except: + 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):