mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-05 17:00:58 +01:00
suggestions for unknown commands in subprocess mode
This commit is contained in:
parent
4177c6bc06
commit
90adbaf070
2 changed files with 61 additions and 3 deletions
|
@ -11,9 +11,9 @@ from io import TextIOWrapper, StringIO
|
|||
from glob import glob, iglob
|
||||
from subprocess import Popen, PIPE
|
||||
from contextlib import contextmanager
|
||||
from collections import Sequence, MutableMapping, Iterable, namedtuple
|
||||
from collections import Sequence, MutableMapping, Iterable, namedtuple, OrderedDict
|
||||
|
||||
from xonsh.tools import string_types, redirect_stdout, redirect_stderr
|
||||
from xonsh.tools import string_types, redirect_stdout, redirect_stderr, levenshtein, levenshtein_sort_helper
|
||||
from xonsh.inspectors import Inspector
|
||||
from xonsh.environ import default_env
|
||||
from xonsh.aliases import DEFAULT_ALIASES
|
||||
|
@ -355,7 +355,34 @@ def run_subproc(cmds, captured=True):
|
|||
proc = Popen(aliased_cmd, universal_newlines=uninew, env=ENV.detype(),
|
||||
stdin=stdin, stdout=stdout)
|
||||
except FileNotFoundError:
|
||||
print('xonsh: subprocess mode: command not found: {0}'.format(aliased_cmd[0]))
|
||||
cmd = aliased_cmd[0]
|
||||
print('xonsh: subprocess mode: command not found: {0}'.format(cmd))
|
||||
if(ENV.get('SUGGEST_COMMANDS', True)):
|
||||
threshold = ENV.get('SUGGEST_ERROR_THRESHOLD', 3)
|
||||
max_sugg = ENV.get('SUGGEST_MAX_NUM', 5)
|
||||
if max_sugg < 0:
|
||||
max_sugg = float('inf')
|
||||
suggested = {}
|
||||
path = ENV.get('PATH',[])
|
||||
for a in builtins.aliases:
|
||||
if a not in suggested and levenshtein(a, cmd) < threshold:
|
||||
suggested[a] = 'Alias'
|
||||
for d in path:
|
||||
if os.path.isdir(d):
|
||||
for f in os.listdir(d):
|
||||
if f not in suggested and levenshtein(f, cmd) < threshold:
|
||||
fname = os.path.join(d,f)
|
||||
suggested[f] = 'Command ({0})'.format(fname)
|
||||
suggested = OrderedDict(sorted(suggested.items(),
|
||||
key=lambda x: levenshtein_sort_helper(x[0], cmd)))
|
||||
num = min(len(suggested), max_sugg)
|
||||
if num>1:
|
||||
print('Did you mean one of the following?')
|
||||
elif num>0:
|
||||
print('Did you mean the following?')
|
||||
for i in range(num):
|
||||
k,v = suggested.popitem(False)
|
||||
print(' {0}: {1}'.format(k,v))
|
||||
return
|
||||
if prev_is_proxy:
|
||||
proc.communicate(input=prev_proc.stdout)
|
||||
|
|
|
@ -210,3 +210,34 @@ class redirect_stdout(_RedirectStream):
|
|||
class redirect_stderr(_RedirectStream):
|
||||
"""Context manager for temporarily redirecting stderr to another file."""
|
||||
_stream = "stderr"
|
||||
|
||||
|
||||
# Public Domain code, by Magnus Lie Hetland
|
||||
# from http://hetland.org/coding/python/levenshtein.py
|
||||
def levenshtein(a,b):
|
||||
"Calculates the Levenshtein distance between a and b."
|
||||
n, m = len(a), len(b)
|
||||
if n > m:
|
||||
# Make sure n <= m, to use O(min(n,m)) space
|
||||
a,b = b,a
|
||||
n,m = m,n
|
||||
|
||||
current = range(n+1)
|
||||
for i in range(1,m+1):
|
||||
previous, current = current, [i]+[0]*n
|
||||
for j in range(1,n+1):
|
||||
add, delete = previous[j]+1, current[j-1]+1
|
||||
change = previous[j-1]
|
||||
if a[j-1] != b[i-1]:
|
||||
change = change + 1
|
||||
current[j] = min(add, delete, change)
|
||||
|
||||
return current[n]
|
||||
|
||||
def levenshtein_sort_helper(x, y):
|
||||
x = x.lower()
|
||||
y = y.lower()
|
||||
lendiff = len(x)+len(y)
|
||||
inx = len([i for i in x if i not in y])
|
||||
iny = len([i for i in y if i not in x])
|
||||
return lendiff + inx + iny
|
||||
|
|
Loading…
Add table
Reference in a new issue