From 79f59bb6f47879e6354cdb57d1711257c3312d1c Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Sat, 21 Apr 2012 17:43:56 -0700 Subject: [PATCH] Added --ctags option to generate tags file --- README.md | 4 +++ autocomplete.d | 23 +++++++++++-- main.d | 11 ++++-- tokenizer.d | 2 +- types.d | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dc140d5..c996572 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,10 @@ is transformed into the following JSON markup: ] } +# Ctags output +Dscanner can create a tags file from the specified file. Output is formatted as +specified at http://ctags.sourceforge.net/FORMAT + # Line of Code count This option counts the logical lines of code in the given source files, not simply the physical lines. More specifically, it counts the number of diff --git a/autocomplete.d b/autocomplete.d index 4543736..18e08ec 100644 --- a/autocomplete.d +++ b/autocomplete.d @@ -28,6 +28,14 @@ immutable string[] versions = ["AIX", "all", "Alpha", "ARM", "BigEndian", "BSD", "Win64", "Windows", "X86", "X86_64" ]; +/+/** + * Returns: indicies into the token array + */ +Tuple!(size_t, size_t) findEndOfStatement(const Token[] tokens, size_t index, out size_t) +{ + +}+/ + string[] callChainBackwards(const Token[] tokens, size_t index) { if (index == 0) @@ -220,12 +228,21 @@ struct AutoComplete auto index = assumeSorted(tokens).lowerBound(cursor).length - 2; Token t = tokens[index]; if (t.startIndex + t.value.length + 1 != cursor) - return []; - if (tokens[index] == TokenType.tVersion) + return ""; + switch (tokens[index].type) { + case TokenType.tVersion: return to!string(array(join(map!`a ~ "?1"`(versions), " "))); + case TokenType.tIf: + case TokenType.tCast: + case TokenType.tWhile: + case TokenType.tFor: + case TokenType.tForeach: + case TokenType.tSwitch: + return ""; + default: + return ""; } - return ""; } string dotComplete(size_t cursor) diff --git a/main.d b/main.d index 059588a..ec14821 100644 --- a/main.d +++ b/main.d @@ -136,8 +136,10 @@ void main(string[] args) bool json; bool parenComplete; bool highlight; + bool ctags; getopt(args, "I", &importDirs, "dotComplete", &dotComplete, "sloc", &sloc, - "json", &json, "parenComplete", &parenComplete, "highlight", &highlight); + "json", &json, "parenComplete", &parenComplete, "highlight", &highlight, + "ctags", &ctags); importDirs ~= loadConfig(); @@ -174,11 +176,14 @@ void main(string[] args) return; } - if (json) + if (json || ctags) { auto tokens = tokenize(readText(args[1])); auto mod = parseModule(tokens); - mod.writeJSONTo(stdout); + if (json) + mod.writeJSONTo(stdout); + else + mod.writeCtagsTo(stdout, args[1]); } } diff --git a/tokenizer.d b/tokenizer.d index efe0b01..99aa3a8 100644 --- a/tokenizer.d +++ b/tokenizer.d @@ -160,7 +160,7 @@ string lexDelimitedString(S)(ref S inputString, ref size_t endIndex, { auto startIndex = endIndex; ++endIndex; - string open = to!string(inputString[endIndex]); + string open = inputString[endIndex .. endIndex + 1]; string close; bool nesting = false; switch (open) diff --git a/types.d b/types.d index 1cc386b..9f4f23f 100644 --- a/types.d +++ b/types.d @@ -11,6 +11,7 @@ import std.array; import std.range; import std.algorithm; import std.typecons; +import std.string; /** * Returns: s with any quote characters backslash-escaped @@ -172,6 +173,23 @@ public: return null; } + string[] getCtags(string fileName) + { + auto app = appender!(string[])(); + app.put(format("%s\t%s\t%d;\"\ts", name, fileName, line)); + foreach (Function f; functions) + { + app.put(format("%s\t%s\t%d;\"\tf\tarity:%d\tstruct:", f.name, fileName, + f.line, f.parameters.length, name)); + } + foreach (Variable v; variables) + { + app.put(format("%s\t%s\t%d;\"\tm\tstruct:%s", v.name, fileName, + v.line, name)); + } + return app.data(); + } + protected: override void printMembers(File f, uint indent = 0) const @@ -245,6 +263,24 @@ public: */ string[] baseClasses; + override string[] getCtags(string fileName) + { + auto app = appender!(string[])(); + app.put(format("%s\t%s\t%d;\"\tc\tinherits:%s", name, fileName, line, + array(baseClasses.joiner(",")))); + foreach (Function f; functions) + { + app.put(format("%s\t%s\t%d;\"\tf\tarity:%d\tstruct:", f.name, fileName, + f.line, f.parameters.length, name)); + } + foreach (Variable v; variables) + { + app.put(format("%s\t%s\t%d;\"\tm\tstruct:%s", v.name, fileName, + v.line, name)); + } + return app.data(); + } + protected: override void printMembers(File f, uint indent = 0) const @@ -277,6 +313,17 @@ public: /// Enum members; may be empty EnumMember[] members; + string[] getCtags(string fileName) const + { + auto app = appender!(string[])(); + app.put(format("%s\t%s\t%d;\"\tg", name, fileName, line)); + foreach (EnumMember member; members) + { + app.put(format("%s\t%s\t%d;\"\te\tenum:%s", member.name, fileName, member.line, name)); + } + return app.data; + } + protected: override void printMembers(File f, uint indent = 0) const @@ -299,6 +346,7 @@ protected: } f.write(std.array.replicate(" ", indent), "]"); } + } /** @@ -423,6 +471,49 @@ public: } f.writeln(" ]\n}"); } + + /** + * Standards: http://ctags.sourceforge.net/FORMAT + */ + void writeCtagsTo(File file, string fileName) + { + string[] tags; + foreach (Enum e; enums) + { + tags ~= e.getCtags(fileName); + } + + foreach (Variable v; variables) + { + tags ~= format("%s\t%s\t%d;\"\tv", v.name, fileName, v.line); + } + + foreach (Function f; functions) + { + tags ~= format("%s\t%s\t%d;\"\tf\tarity:%d", f.name, fileName, + f.line, f.parameters.length); + } + foreach (Inherits c; classes) + { + tags ~= c.getCtags(fileName); + } + foreach (Inherits i; interfaces) + { + tags ~= i.getCtags(fileName); + } + foreach (Struct s; structs) + { + tags ~= s.getCtags(fileName); + } + + sort(tags); + file.writeln("{!_TAG_FILE_FORMAT 2}"); + file.writeln("{!_TAG_FILE_SORTED 1}"); + foreach (tag; tags) + { + file.writeln(tag); + } + } } immutable(string[][string]) typeProperties;