comparison mercurial/dispatch.py @ 24221:4e240d6ab898

dispatch: offer near-edit-distance suggestions for {file,rev}set functions Before this patch, when I have a brain fart and type `hg log -r 'add(foo)'`, hg exits and just says add isn't a function, leading me to the help page for revset to figure out how to spell the function. With this patch, it suggests 'adds' as a function I might have meant.
author Augie Fackler <augie@google.com>
date Mon, 26 Jan 2015 15:43:13 -0500
parents bb11081562d7
children 02d7b5cd373b
comparison
equal deleted inserted replaced
24220:fe195d41f7d2 24221:4e240d6ab898
5 # This software may be used and distributed according to the terms of the 5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version. 6 # GNU General Public License version 2 or any later version.
7 7
8 from i18n import _ 8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re 9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
10 import difflib
10 import util, commands, hg, fancyopts, extensions, hook, error 11 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding 12 import cmdutil, encoding
12 import ui as uimod 13 import ui as uimod
13 14
14 class request(object): 15 class request(object):
25 26
26 def run(): 27 def run():
27 "run the command in sys.argv" 28 "run the command in sys.argv"
28 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255) 29 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
29 30
31 def _getsimilar(symbols, value):
32 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
33 # The cutoff for similarity here is pretty arbitrary. It should
34 # probably be investigated and tweaked.
35 return [s for s in symbols if sim(s) > 0.6]
36
30 def _formatparse(write, inst): 37 def _formatparse(write, inst):
38 similar = []
39 if isinstance(inst, error.UnknownIdentifier):
40 # make sure to check fileset first, as revset can invoke fileset
41 similar = _getsimilar(inst.symbols, inst.function)
31 if len(inst.args) > 1: 42 if len(inst.args) > 1:
32 write(_("hg: parse error at %s: %s\n") % 43 write(_("hg: parse error at %s: %s\n") %
33 (inst.args[1], inst.args[0])) 44 (inst.args[1], inst.args[0]))
34 if (inst.args[0][0] == ' '): 45 if (inst.args[0][0] == ' '):
35 write(_("unexpected leading whitespace\n")) 46 write(_("unexpected leading whitespace\n"))
36 else: 47 else:
37 write(_("hg: parse error: %s\n") % inst.args[0]) 48 write(_("hg: parse error: %s\n") % inst.args[0])
49 if similar:
50 if len(similar) == 1:
51 write(_("(did you mean %r?)\n") % similar[0])
52 else:
53 ss = ", ".join(sorted(similar))
54 write(_("(did you mean one of %s?)\n") % ss)
38 55
39 def dispatch(req): 56 def dispatch(req):
40 "run the command specified in req.args" 57 "run the command specified in req.args"
41 if req.ferr: 58 if req.ferr:
42 ferr = req.ferr 59 ferr = req.ferr