mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-05 17:00:58 +01:00
OK, more fixes
This commit is contained in:
parent
35d95b593d
commit
1887864528
3 changed files with 50 additions and 20 deletions
|
@ -301,13 +301,13 @@ def _dh_create_parser(p=None):
|
|||
return p
|
||||
|
||||
|
||||
def _dh_main_action(ns, hist=None):
|
||||
def _dh_main_action(ns, hist=None, stdout=None, stderr=None):
|
||||
hd = HistoryDiffer(ns.a, ns.b, reopen=ns.reopen, verbose=ns.verbose)
|
||||
print_color(hd.format())
|
||||
print_color(hd.format(), file=stdout)
|
||||
|
||||
|
||||
def diff_history_main(args=None, stdin=None):
|
||||
def diff_history_main(args=None, stdin=None, stdout=None, stderr=None):
|
||||
"""Main entry point for history diff'ing"""
|
||||
parser = _dh_create_parser()
|
||||
ns = parser.parse_args(args)
|
||||
_dh_main_action(ns)
|
||||
_dh_main_action(ns, stdout=stdout)
|
||||
|
|
|
@ -443,7 +443,7 @@ def _hist_get(session='session', *, slices=None, datetime_format=None,
|
|||
return cmds
|
||||
|
||||
|
||||
def _hist_show(ns, *args, **kwargs):
|
||||
def _hist_show(ns, hist=None, stdout=None, stderr=None):
|
||||
"""Show the requested portion of shell history.
|
||||
Accepts same parameters with `_hist_get`.
|
||||
"""
|
||||
|
@ -454,24 +454,24 @@ def _hist_show(ns, *args, **kwargs):
|
|||
end_time=ns.end_time,
|
||||
datetime_format=ns.datetime_format)
|
||||
except ValueError as err:
|
||||
print("history: error: {}".format(err), file=sys.stderr)
|
||||
print("history: error: {}".format(err), file=stderr)
|
||||
return
|
||||
if ns.reverse:
|
||||
commands = reversed(list(commands))
|
||||
if not ns.numerate and not ns.timestamp:
|
||||
for c, _, _ in commands:
|
||||
print(c)
|
||||
print(c, file=stdout)
|
||||
elif not ns.timestamp:
|
||||
for c, _, i in commands:
|
||||
print('{}: {}'.format(i, c))
|
||||
print('{}: {}'.format(i, c), file=stdout)
|
||||
elif not ns.numerate:
|
||||
for c, ts, _ in commands:
|
||||
dt = datetime.datetime.fromtimestamp(ts).ctime()
|
||||
print('({}) {}'.format(dt, c))
|
||||
print('({}) {}'.format(dt, c), file=stdout)
|
||||
else:
|
||||
for c, ts, i in commands:
|
||||
dt = datetime.datetime.fromtimestamp(ts).ctime()
|
||||
print('{}:({}) {}'.format(i, dt, c))
|
||||
print('{}:({}) {}'.format(i, dt, c), file=stdout)
|
||||
|
||||
|
||||
# Interface to History
|
||||
|
@ -689,7 +689,7 @@ class History(object):
|
|||
'you can create new though.')
|
||||
|
||||
|
||||
def _hist_info(ns, hist):
|
||||
def _hist_info(ns, hist, stdout, stderr):
|
||||
"""Display information about the shell history."""
|
||||
data = collections.OrderedDict()
|
||||
data['sessionid'] = str(hist.sessionid)
|
||||
|
@ -699,10 +699,10 @@ def _hist_info(ns, hist):
|
|||
data['bufferlength'] = len(hist.buffer)
|
||||
if ns.json:
|
||||
s = json.dumps(data)
|
||||
print(s)
|
||||
print(s, file=stdout)
|
||||
else:
|
||||
lines = ['{0}: {1}'.format(k, v) for k, v in data.items()]
|
||||
print('\n'.join(lines))
|
||||
print('\n'.join(lines), file=stdout)
|
||||
|
||||
|
||||
def _hist_gc(ns, hist):
|
||||
|
@ -726,12 +726,12 @@ def _HIST_SESSIONS():
|
|||
def _HIST_MAIN_ACTIONS():
|
||||
return {
|
||||
'show': _hist_show,
|
||||
'id': lambda ns, hist: print(hist.sessionid),
|
||||
'file': lambda ns, hist: print(hist.filename),
|
||||
'id': lambda ns, hist, stdout, stderr: print(hist.sessionid, file=stdout),
|
||||
'file': lambda ns, hist, stdout, stderr: print(hist.filename, file=stdout),
|
||||
'info': _hist_info,
|
||||
'diff': _dh_main_action,
|
||||
'gc': _hist_gc,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def _hist_parse_args(args):
|
||||
|
@ -759,9 +759,9 @@ def _hist_parse_args(args):
|
|||
return ns
|
||||
|
||||
|
||||
def history_main(args=None, stdin=None):
|
||||
def history_main(args=None, stdin=None, stdout=None, stderr=None):
|
||||
"""This is the history command entry point."""
|
||||
hist = builtins.__xonsh_history__
|
||||
ns = _hist_parse_args(args)
|
||||
if ns:
|
||||
_HIST_MAIN_ACTIONS[ns.action](ns, hist)
|
||||
_HIST_MAIN_ACTIONS[ns.action](ns, hist, stdout, stderr)
|
||||
|
|
|
@ -491,6 +491,18 @@ def safe_flush(handle):
|
|||
return status
|
||||
|
||||
|
||||
def still_writable(fd):
|
||||
"""Determines whether a file descriptior is still writable by trying to
|
||||
write an empty string and seeing if it fails.
|
||||
"""
|
||||
try:
|
||||
os.write(fd, b'')
|
||||
status = True
|
||||
except OSError:
|
||||
status = False
|
||||
return status
|
||||
|
||||
|
||||
class PopenThread(threading.Thread):
|
||||
"""A thread for running and managing subprocess. This allows reading
|
||||
from the stdin, stdout, and stderr streams in a non-blocking fashion.
|
||||
|
@ -1010,8 +1022,11 @@ class FileThreadDispatcher:
|
|||
extra sure the string was written.
|
||||
"""
|
||||
h = self.handle
|
||||
r = h.write(s)
|
||||
safe_flush(h)
|
||||
try:
|
||||
r = h.write(s)
|
||||
h.flush()
|
||||
except OSError:
|
||||
r = None
|
||||
return r
|
||||
|
||||
@property
|
||||
|
@ -1286,6 +1301,21 @@ class ProcProxyThread(threading.Thread):
|
|||
r = self.f(self.args, sp_stdin, sp_stdout, sp_stderr, spec)
|
||||
except SystemExit as e:
|
||||
r = e.code if isinstance(e.code, int) else int(bool(e.code))
|
||||
except OSError as e:
|
||||
status = still_writable(self.c2pwrite) and \
|
||||
still_writable(self.errwrite)
|
||||
if status:
|
||||
# stdout and stderr are still writable, so error must
|
||||
# come from function itself.
|
||||
print_exception()
|
||||
r = 1
|
||||
else:
|
||||
# stdout and stderr are no longer writable, so error must
|
||||
# come from the fact that the next process in the pipeline
|
||||
# has closed the other side of the pipe. The function then
|
||||
# attempted to write to this side of the pipe anyway. This
|
||||
# is not truly an error and we should exit gracefully.
|
||||
r = 0
|
||||
except Exception:
|
||||
print_exception()
|
||||
r = 1
|
||||
|
|
Loading…
Add table
Reference in a new issue