Mercurial > public > mercurial-scm > hg-stable
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 |