aboutsummaryrefslogtreecommitdiffhomepage
path: root/make_completions.py
diff options
context:
space:
mode:
authorGravatar liljencrantz <liljencrantz@gmail.com>2007-10-29 04:51:43 +1000
committerGravatar liljencrantz <liljencrantz@gmail.com>2007-10-29 04:51:43 +1000
commitbdd1b6b4b23836ccfe441e1c40374f00aab442f3 (patch)
treec0e8fb748dbfb825a5d6dcae519718eae0f321a8 /make_completions.py
parent6dfdb3ba6edf7e7939657818ed6c27907aef60ba (diff)
Rewrite automatic completion creator from scratch. The new implementation uses a finite state machine instead of a set of regexes, which inpractice seems to make the parser more robust and the code subjectively more readable
darcs-hash:20071028185143-75c98-92c1a0cd579ff0c41f47e75c975405fe3e002ddb.gz
Diffstat (limited to 'make_completions.py')
-rwxr-xr-xmake_completions.py211
1 files changed, 130 insertions, 81 deletions
diff --git a/make_completions.py b/make_completions.py
index cee4698a..5830bfea 100755
--- a/make_completions.py
+++ b/make_completions.py
@@ -4,103 +4,152 @@ import sys
import commands
import re
+# Regexes for performing cleanup
+
+cl = {re.compile(r"[ \n\t\r]+", re.MULTILINE):" ",
+ re.compile(r"^[ \n\t\r]"):"",
+ re.compile(r"[ \n\t\r]$"):"",
+ re.compile(r"-[ \t]*\n[ \t\r]+" ):""}
+
+def header(cmd):
+ print '''#
+# Command specific completions for the %s command.
+# These completions where generated from the commands
+# man page by the make_completions.py script, but may
+# have been hand edited since.
+#
+''' % (cmd)
+
+def up_first(s):
+ return s[0].upper() + s[1:]
+
def escape_quotes(s):
return re.sub('\'', '\\\'', s)
def escape(s):
return re.sub('([\'"#%*?])', r"\\\1", s)
-def print_completion( cmd, switch_name, arg, desc ):
+def clean(s):
+ res=s
+ for r, str in cl.items():
+ res = r.sub(str, res)
+ return res
- offset=1
- switch_type = "o"
+def print_completion( cmd, switch_arr, arg, desc ):
- if len(switch_name) == 2:
- switch_type = "s"
+ if len(switch_arr)==0:
+ return
+
+ res = "complete -c %s" % (cmd)
+ for sw in switch_arr:
+
+ offset=1
+ switch_type = "o"
+
+ if len(sw) == 2:
+ switch_type = "s"
- if switch_name[1] == "-":
- switch_type = "l"
- offset=2
+ if sw[1] == "-":
+ switch_type = "l"
+ offset=2
- arg_str = ""
- if arg == None:
- pass
- elif arg == "standard":
- arg_str = "-a 'c89 c99 gnu89 gnu99 c++98 gnu++98'"
- else:
- pass
-
- print "complete -c %s -%s %s %s --description '%s'" % (cmd, switch_type, escape( switch_name[offset:] ), arg_str, escape_quotes(desc))
-
-def clean_whitespace( str ):
- clean_whitespace_prog0 = re.compile( r"-[ \t]*\n[ \t\r]+" )
- clean_whitespace_prog1 = re.compile( r"[ \n\t]+" )
- clean_whitespace_prog2 = re.compile( r"^[ \t\r]*", re.MULTILINE )
- str = clean_whitespace_prog0.sub( "", str )
- str = clean_whitespace_prog1.sub( " ", str )
- str = clean_whitespace_prog2.sub( "", str )
- return str
+ res += " -%s %s" % (switch_type, escape(sw[offset:]))
+ res += " --description '%s'" % (up_first(escape_quotes(clean(desc))))
+ print res
cmd = sys.argv[1]
-man = commands.getoutput( "man %s | col -b" % cmd )
-remainder = man
-
-re1 = r"\n( *-[^ ,]* *(|\n))+[^.]+"
-prog1 = re.compile(re1, re.MULTILINE)
-
-re2 = r"^(|=[^ ]*)( |\n)*(?P<switch>-[^ =./\n]+)( *[^-\n ]*\n|)"
-prog2 = re.compile(re2, re.MULTILINE)
-
-re3 = r"^=(?P<arg>[^ ]*)"
-prog3 = re.compile(re2, 0)
-
-while True:
-
- match = prog1.search( remainder )
-
- if match == None:
- break
-# print "yay match!!!\n"
- str = match.string[match.start():match.end()]
+header(cmd)
-# print str
-
- rem2 = str
-
- switch = []
-
- while True:
- match2 = prog2.search( rem2 )
-
- if match2 == None:
- break
-
- sw = match2.expand( r"\g<switch>" )
-# print "yay switch %s!!!\n" %sw
-
- switch.append( sw )
-
- rem2 = rem2[match2.end():]
-
- match_arg = prog3.search( rem2 )
- arg = None
-
- if match_arg != None:
- arg = match_arg.expand( r"\g<arg>" )
- rem2 = rem2[match_arg.end():]
-
- desc = clean_whitespace(rem2)
-
- if len( desc) > 8 and arg != None:
-
-# print "Yay desc '%s'!!\n" % desc
-
- for i in switch:
- print_completion( cmd, i, arg, desc )
+man = commands.getoutput( "man %s | col -b" % cmd )
+remainder = man
- remainder = remainder[match.end():]
+MODE_NONE = 0
+MODE_SWITCH = 1
+MODE_BETWEEN = 2
+MODE_BETWEEN_IGNORE = 3
+MODE_DESC = 4
+
+mode = MODE_NONE
+pos = 0
+sw=''
+sw_arr=[]
+switch_end="= \t\n[,"
+switch_between_ignore="[="
+switch_between_continue=" \t\n|"
+before_switch=" \t\r"
+between_ignore=" \t\n]"
+pc=False
+desc=''
+
+can_be_switch =True
+
+for c in man:
+
+ if mode == MODE_NONE:
+ if c == '-' and can_be_switch:
+ mode = MODE_SWITCH
+ sw = '-'
+
+ elif c == '\n':
+ can_be_switch = True
+ elif before_switch.find(c)<0:
+ can_be_switch = False
+
+
+ elif mode == MODE_SWITCH:
+ if not switch_end.find(c)>=0:
+ sw+=c
+ else:
+ if len(sw) > 1:
+ sw_arr.append(sw)
+
+ if switch_between_ignore.find(c) >= 0:
+ mode=MODE_BETWEEN_IGNORE
+ else:
+ mode=MODE_BETWEEN
+ # print "End of switch argumnt", sw, "switch to between mode"
+ sw=''
+
+ elif mode == MODE_BETWEEN:
+ if c == '-':
+ mode = MODE_SWITCH
+ sw = '-'
+ elif switch_between_ignore.find(c) >= 0:
+ mode = MODE_BETWEEN_IGNORE
+ # print "Found character", c, "switching to ignore mode"
+ elif not switch_between_continue.find(c) >= 0:
+ mode = MODE_DESC
+ desc = c
+
+ elif mode == MODE_BETWEEN_IGNORE:
+ if between_ignore.find(c)>=0:
+ mode = MODE_BETWEEN
+
+ elif mode == MODE_DESC:
+
+ stop = False
+
+ if c == '.':
+ stop = True
+
+ if c == '\n' and pc == '\n':
+ stop=True
+
+ if stop:
+ mode=MODE_NONE
+
+ print_completion( cmd, sw_arr, None, desc )
+
+ sw_arr = []
+
+ desc = ''
+
+ else:
+ desc += c
+
+ pc = c