5

Characters such as - , + etc are not parsed the same way as alphanumeric ASCII characters by Python's readline based cmd module. This seems to be linux specific issue only, as it seems to work as expected on Mac OS.

Sample code

import cmd

class Test(cmd.Cmd):
    def do_abc(self, line):
        print line 
    def complete_abc(self, text, line, begidx, endidx):
        return [i for i in ['-xxx', '-yyy', '-zzz'] if i.startswith(text)]

try:
    import readline
except ImportError:
    print "Module readline not available."
else:
    import rlcompleter
    if 'libedit' in readline.__doc__:
        readline.parse_and_bind("bind ^I rl_complete")
    else:
        readline.parse_and_bind("tab: complete")

Test().cmdloop()

Expected behavior on Mac OS

(Cmd) abc <TAB>
abc  
(Cmd) abc -<TAB>
-xxx  -yyy  -zzz  
(Cmd) abc -x<TAB>
(Cmd) abc -xxx

Incorrect behavior on Linux

(Cmd) abc <TAB>
abc  
(Cmd) abc -x<TAB>
 <Nothing>
(Cmd) abc -<TAB> 
(Cmd) abc --<TAB>
(Cmd) abc ---<TAB>
(Cmd) abc ----

I tried adding - to cmd.Cmd.identchars, but it didn't help.

cmd.Cmd.identchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'

Why is there a difference in readline parsing between Mac OS and Linux even though both use GNU readline:

Mac OS:

>>> readline.__doc__
'Importing this module enables command line editing using GNU readline.'

Linux:

>>> readline.__doc__
'Importing this module enables command line editing using GNU readline.'

Thanks!

rajivRaja
  • 527
  • 3
  • 6
  • 16
  • btw identchars is just used to find out the point where your command ends and args begin eg: `cmd arg1` == `cmd?arg1` so adding to identchars wont help, in fact it is dangerous as it will break the parsing like @Dunes said you have to adjust the delimiters. – user881300 Mar 25 '16 at 09:29

1 Answers1

6

On linux, the readline module considers - a delimiter for tab completion. That is, after a - is encountered a fresh completion will be tried.

The solution to your problem is the remove - from the set of characters used by readline as delimiters.

eg.

old_delims = readline.get_completer_delims()
readline.set_completer_delims(old_delims.replace('-', ''))
Dunes
  • 37,291
  • 7
  • 81
  • 97
  • Interesting! That did it. I did check readline.get_completer_delims() on both mac os and linux, they were the same. But it didn't occur to me that delimiter was the problem, nice catch and thanks a bunch! – rajivRaja Dec 04 '14 at 14:36