diff --git a/Makefile.in b/Makefile.in index 179d2c18b..7f57ca36f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -168,7 +168,7 @@ GENERATED_INTERN_SCRIPT_FILES := builtin_scripts.h builtin_scripts.cpp # Use a pattern rule so that Make knows to only issue one invocation # per http://www.gnu.org/software/make/manual/make.html#Pattern-Intro builtin%scripts.h builtin%scripts.cpp: internalize_scripts.py - ./internalize_scripts.py share/functions/*.fish + ./internalize_scripts.py share/functions/*.fish share/completions/*.fish # @@ -889,6 +889,7 @@ distclean: clean clean: rm -f *.o doc.h doc.tmp doc_src/*.doxygen doc_src/*.cpp doc_src/*.o doc_src/commands.hdr + rm -f $(GENERATED_INTERN_SCRIPT_FILES) rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt rm -f $(PROGRAMS) fish_tests tokenizer_test key_reader rm -f share/config.fish etc/config.fish doc_src/index.hdr doc_src/commands.hdr diff --git a/internalize_scripts.py b/internalize_scripts.py index 9d9770f1c..68a2f6480 100755 --- a/internalize_scripts.py +++ b/internalize_scripts.py @@ -1,5 +1,6 @@ #!/usr/bin/python + import string, sys, os.path escapes = {} @@ -11,7 +12,7 @@ escapes['\r'] = r'\r' #escapes['\t'] = r'\t' # Let's replace tabs with four spaces # so the text looks nicely indented in the C source -escapes['\t'] = r' ' +escapes['\t'] = r' ' escapes['\v'] = r'\v' # escapes['\''] = r'\'' escapes['\"'] = r'\"' @@ -19,21 +20,28 @@ escapes['\\'] = r'\\' def escape(c): if c in escapes: - return escapes[c] + return (escapes[c], False) elif c not in string.printable: - return "\\x%x" % ord(c) + return ("\\x%x" % ord(c), True) else: - return c + return (c, False) def stringize(line): newline = '"' + was_escape = False for c in line: - newline += escape(c) + # Avoid an issue where characters after a hexadecimal escape are treated as part of that escape + # by adding two quotes + if was_escape and c in string.hexdigits: + newline += '""' + chars, was_escape = escape(c) + newline += chars newline += '"' return newline class cfunc: - def __init__(self, name, lines): + def __init__(self, type, name, lines): + self.type = type self.name = name self.lines = lines @@ -45,22 +53,36 @@ class cfunc: return result def cfunc_name(self): - munged_name = string.replace(self.name, '-', '_') - return "function_%s" % munged_name + # Translate - and . to underscore + translator = string.maketrans('-.', '__') + munged_name = string.translate(self.name, translator) + return "%s_%s" % (self.type, munged_name) -funcs = [] +TYPES = ['function', 'completion'] +type_to_funcs = dict((t, []) for t in TYPES) for file in sys.argv[1:]: fd = open(file, 'r') newlines = [] for line in fd: newlines.append(stringize(line)) fd.close() + dirname = os.path.dirname(file) + + # Try to figure out the file type (completion or function) + matches = [dir in dirname for dir in TYPES] + if matches.count(True) is not 1: + print "Cannot determine the type of the file at path %s" % file + sys.exit(-1) + type = TYPES[matches.index(True)] + name = os.path.basename(file) name, ext = os.path.splitext(name) - funcs.append(cfunc(name, newlines)) + newfunc = cfunc(type, name, newlines) + type_to_funcs[type].append(newfunc) # Sort our functions by name -funcs.sort(key=cfunc.cfunc_name) +for funcs in type_to_funcs.itervalues(): + funcs.sort(key=cfunc.cfunc_name) # Output our header fd = open('builtin_scripts.h', 'w') @@ -71,22 +93,29 @@ fd.write("""struct builtin_script_t { };""") fd.write('\n') -fd.write('\n') -fd.write('extern const struct builtin_script_t internal_function_scripts[%d];\n' % len(funcs)) -fd.write('\n') + +for type in TYPES: + funcs = type_to_funcs[type] + fd.write('\n') + fd.write('extern const struct builtin_script_t internal_%s_scripts[%d];' % (type, len(funcs))) + fd.write('\n') fd.close() # Output the function definitions fd = open('builtin_scripts.cpp', 'w') fd.write('/* This file is generated by internalize_scripts.py */\n\n') fd.write('#include "builtin_scripts.h"\n\n') -for func in funcs: - fd.write(func.cdef()) - fd.write('\n') +for type in TYPES: + for func in type_to_funcs[type]: + fd.write(func.cdef()) + fd.write('\n') # Output the refs -func_refs = ["{L%s, %s}" % (stringize(func.name), func.cfunc_name()) for func in funcs] -fd.write('const struct builtin_script_t internal_function_scripts[%d] =\n' % len(funcs)) -fd.write('{\n\t') -fd.write(',\n\t'.join(func_refs)) -fd.write('\n};\n') +for type in TYPES: + funcs = type_to_funcs[type] + func_refs = ["{L%s, %s}" % (stringize(func.name), func.cfunc_name()) for func in funcs] + fd.write('const struct builtin_script_t internal_%s_scripts[%d] =\n' % (type, len(funcs))) + fd.write('{\n\t') + fd.write(',\n\t'.join(func_refs)) + fd.write('\n};\n') +fd.close() diff --git a/parse_util.cpp b/parse_util.cpp index 00dd75d6b..8ddf1a904 100644 --- a/parse_util.cpp +++ b/parse_util.cpp @@ -870,10 +870,12 @@ int parse_util_load( const wcstring &cmd, /* Figure out which builtin-scripts array to search (if any) */ const builtin_script_t *builtins = NULL; size_t builtin_count = 0; - if (path_var_name == L"fish_function_path") - { + if (path_var_name == L"fish_function_path") { builtins = internal_function_scripts; builtin_count = sizeof internal_function_scripts / sizeof *internal_function_scripts; + } else if (path_var_name == L"fish_complete_path") { + builtins = internal_completion_scripts; + builtin_count = sizeof internal_completion_scripts / sizeof *internal_completion_scripts; } /*