From 4ae5fc2bd496a935f8e599f7b9d98d9c9114ba0e Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Fri, 23 May 2014 21:07:08 +1200 Subject: [PATCH 1/7] Add Emacs TAGS (etags) output. --- bin/jsctags.js | 7 +++- lib/jsctags/ctags/writer.js | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/bin/jsctags.js b/bin/jsctags.js index 242cd6d..230c701 100755 --- a/bin/jsctags.js +++ b/bin/jsctags.js @@ -50,6 +50,7 @@ var Tags = ctags.Tags; function usage() { util.puts("usage: jsctags [options] path0 [.. pathN]"); util.puts("options:"); + util.puts(" -e, --emacs emit Emacs TAGS"); util.puts(" -f, --output file place output in the given file (-f " + "- for stdout)"); util.puts(" -h, --help display this usage info"); @@ -65,7 +66,7 @@ function usage() { var opts; try { - opts = getopt("help|h", "jsonp|j=s", "libroot|L=s@", "oneprog", "output|o|f=s", + opts = getopt("help|h", "emacs|e", "jsonp|j=s", "libroot|L=s@", "oneprog", "output|o|f=s", "sort|=s", "warning|W=s"); } catch (e) { util.puts(e); @@ -260,12 +261,16 @@ if (opts.hasOwnProperty('output')) { } } else if (opts.hasOwnProperty('jsonp')) { out = fs.createWriteStream("tags.jsonp"); +} else if (opts.hasOwnProperty('emacs')) { + out = fs.createWriteStream("TAGS"); } else { out = fs.createWriteStream("tags"); } if (opts.hasOwnProperty('jsonp')) { tags.writeJSONP(out, opts.jsonp); +} else if (opts.hasOwnProperty('emacs')) { + tags.writeEmacs(out, opts); } else { tags.write(out, opts); } diff --git a/lib/jsctags/ctags/writer.js b/lib/jsctags/ctags/writer.js index bee3183..a66dc48 100644 --- a/lib/jsctags/ctags/writer.js +++ b/lib/jsctags/ctags/writer.js @@ -130,6 +130,72 @@ exports.TagWriter = Trait({ lines.forEach(function(line) { stream.write(line); }); }, + writeEmacs: function(stream, opts) { + var sections = {}; + this.tags.map(function(tag) { + if (!sections[tag.tagfile]) + sections[tag.tagfile] = new Array(); + sections[tag.tagfile].push(tag); + }); + for (var filename in sections) { + if (sections.hasOwnProperty(filename)) { + stream.write(" \n"); + var section = sections[filename]; + var lines = section.map(function(tag) { + var line_number = tag["lineno"]; + var addr = tag.addr.substr(2, tag.addr.length-4); + addr = addr.replace ("\\t", "\t"); + var buf = [ addr, "", tag.name, "", line_number, ",1"]; + buf.push("\n"); + return buf.join(""); + }); + var size = 0; + var buf = [ filename, ",", size, "\n" ] + stream.write(buf.join("")); + lines.forEach(function(line) { stream.write(line); }); + } + }; + var lines = this.tags.map(function(tag) { + delete tag.sortno; + var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; + + var addr = tag.addr; + buf.push(addr !== undefined ? addr : "//"); + + var tagfields = []; + for (var key in tag) { + if (!(key in SPECIAL_FIELDS)) { + tagfields.push(key); + } + } + tagfields.sort(); + + var kind = tag.kind; + if (kind === undefined && tagfields.length === 0) { + buf.push("\n"); + return buf.join(""); + } + + buf.push(";\""); + + if (kind !== undefined) { + buf.push("\t", kind); + } + + tagfields.forEach(function(tagfield) { + buf.push("\t", tagfield, ":"); + + var escape = function(str) { return ESCAPES[str]; }; + buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); + }); + + buf.push("\n"); + return buf.join(""); + }); + + //lines.forEach(function(line) { stream.write(line); }); + }, + writeJSONP: function(stream, func) { this.tags.map(function(tag) { delete tag.sortno; }); var json = JSON.stringify(this.tags); From 71d2cd0fb49fb7c0751e07522bac9babdafb4e8e Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Mon, 26 May 2014 11:22:45 +1200 Subject: [PATCH 2/7] Added comment on how to make this work with Ubuntu 14.04. --- bin/jsctags.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/jsctags.js b/bin/jsctags.js index 230c701..a2b2250 100755 --- a/bin/jsctags.js +++ b/bin/jsctags.js @@ -1,4 +1,10 @@ #!/usr/bin/env node +/** + * If you get: + * /usr/bin/env: node: No such file or directory + * Please install nodejs-legacy. + */ + /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * From 0a165b2636e9798681a375a1f4292f2aa6d2880f Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Mon, 26 May 2014 11:32:14 +1200 Subject: [PATCH 3/7] Add nodjs-legacy requirements to README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 36e53bf..415c98f 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ Requirements * node.js * `make` +On newer Debian and Ubuntu systems, please install nodejs-legacy in addition +to nodejs. + Building -------- To install: @@ -68,4 +71,3 @@ The directory structure mostly follows the CommonJS packaging scheme: [6]: http://mxr.mozilla.org/mozilla/source/js/narcissus/ [parser]: http://localhost:8080/html/parser.html - From dbd353d669fd20df0f98d43a26175900d9edbe39 Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Mon, 26 May 2014 11:32:37 +1200 Subject: [PATCH 4/7] Pull in nodejs 0.10.x compatibility fix from https://github.com/mozilla/doctorjs/pull/54/files --- lib/jsctags/ctags/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/jsctags/ctags/index.js b/lib/jsctags/ctags/index.js index fff958c..f076e27 100644 --- a/lib/jsctags/ctags/index.js +++ b/lib/jsctags/ctags/index.js @@ -43,11 +43,12 @@ var TagWriter = require('./writer').TagWriter; var Trait = require('../traits').Trait; exports.Tags = function (initialTags) { - this.tags = initialTags != null ? initialTags : []; this.init(); }; exports.Tags.prototype = Object.create(Object.prototype, Trait.compose(Trait({ + tags: [], + _search: function (id, pred) { var shadowTag = { name: id }; var tags = this.tags; From 29c72da814fd83713bdf7c026abf4b2bfddb45f5 Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Tue, 27 May 2014 10:30:01 +1200 Subject: [PATCH 5/7] Tabify file. --- lib/jsctags/ctags/writer.js | 311 ++++++++++++++++++------------------ 1 file changed, 155 insertions(+), 156 deletions(-) diff --git a/lib/jsctags/ctags/writer.js b/lib/jsctags/ctags/writer.js index a66dc48..c89ac1c 100644 --- a/lib/jsctags/ctags/writer.js +++ b/lib/jsctags/ctags/writer.js @@ -41,167 +41,166 @@ var _ = require('../underscore')._; const ESCAPES = { "\\": "\\\\", "\n": "\\n", "\r": "\\r", "\t": "\\t" }; var METATAGS = [ - { name: '!_TAG_FILE_FORMAT', tagfile: 2, addr: "/extended format/" }, - { - name: '!_TAG_FILE_SORTED', - tagfile: 0, - addr: "/0=unsorted, 1=sorted, 2=foldcase/" - }, - { - name: '!_TAG_PROGRAM_AUTHOR', - tagfile: "Patrick Walton", - addr: "/pwalton@mozilla.com/" - }, - { name: '!_TAG_PROGRAM_NAME', tagfile: "jsctags" }, - { - name: '!_TAG_PROGRAM_URL', - tagfile: "http://github.com/pcwalton/jsctags", - addr: "/GitHub repository/" - }, - { name: '!_TAG_PROGRAM_VERSION', tagfile: "0.1" } + { name: '!_TAG_FILE_FORMAT', tagfile: 2, addr: "/extended format/" }, + { + name: '!_TAG_FILE_SORTED', + tagfile: 0, + addr: "/0=unsorted, 1=sorted, 2=foldcase/" + }, + { + name: '!_TAG_PROGRAM_AUTHOR', + tagfile: "Patrick Walton", + addr: "/pwalton@mozilla.com/" + }, + { name: '!_TAG_PROGRAM_NAME', tagfile: "jsctags" }, + { + name: '!_TAG_PROGRAM_URL', + tagfile: "http://github.com/pcwalton/jsctags", + addr: "/GitHub repository/" + }, + { name: '!_TAG_PROGRAM_VERSION', tagfile: "0.1" } ]; const SPECIAL_FIELDS = { addr: true, kind: true, name: true, tagfile: true }; exports.TagWriter = Trait({ - tags: Trait.required, - - init: function() { }, - - write: function(stream, opts) { - if (!opts.hasOwnProperty('sort') || opts.sort === 'no') { - var sortfunc = function(a, b) { return parseInt(a.sortno, 10) - parseInt(b.sortno, 10); }; - } else if (opts.sort === 'yes') { - var sortfunc = function(a, b) { - if (a.name === b.name) return 0; - else if (a.name < b.name) return -1; - else return 1; - }; - for (var i in METATAGS) { - if (METATAGS[i].name == '!_TAG_FILE_SORTED') { - METATAGS[i].tagfile = 1; - break; - } - } - } else { - throw new Error("Invalid value for --sort flag."); - } - this.tags = this.tags.sort(sortfunc); - this.tags = METATAGS.concat(this.tags); - - var lines = this.tags.map(function(tag) { - delete tag.sortno; - var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; - - var addr = tag.addr; - buf.push(addr !== undefined ? addr : "//"); - - var tagfields = []; - for (var key in tag) { - if (!(key in SPECIAL_FIELDS)) { - tagfields.push(key); - } - } - tagfields.sort(); - - var kind = tag.kind; - if (kind === undefined && tagfields.length === 0) { - buf.push("\n"); - return buf.join(""); - } - - buf.push(";\""); - - if (kind !== undefined) { - buf.push("\t", kind); - } - - tagfields.forEach(function(tagfield) { - buf.push("\t", tagfield, ":"); - - var escape = function(str) { return ESCAPES[str]; }; - buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); - }); - - buf.push("\n"); - return buf.join(""); - }); - - lines.forEach(function(line) { stream.write(line); }); - }, - - writeEmacs: function(stream, opts) { - var sections = {}; - this.tags.map(function(tag) { - if (!sections[tag.tagfile]) - sections[tag.tagfile] = new Array(); - sections[tag.tagfile].push(tag); - }); - for (var filename in sections) { - if (sections.hasOwnProperty(filename)) { - stream.write(" \n"); - var section = sections[filename]; - var lines = section.map(function(tag) { - var line_number = tag["lineno"]; - var addr = tag.addr.substr(2, tag.addr.length-4); - addr = addr.replace ("\\t", "\t"); - var buf = [ addr, "", tag.name, "", line_number, ",1"]; - buf.push("\n"); - return buf.join(""); + tags: Trait.required, + + init: function() { }, + + write: function(stream, opts) { + if (!opts.hasOwnProperty('sort') || opts.sort === 'no') { + var sortfunc = function(a, b) { return parseInt(a.sortno, 10) - parseInt(b.sortno, 10); }; + } else if (opts.sort === 'yes') { + var sortfunc = function(a, b) { + if (a.name === b.name) return 0; + else if (a.name < b.name) return -1; + else return 1; + }; + for (var i in METATAGS) { + if (METATAGS[i].name == '!_TAG_FILE_SORTED') { + METATAGS[i].tagfile = 1; + break; + } + } + } else { + throw new Error("Invalid value for --sort flag."); + } + this.tags = this.tags.sort(sortfunc); + this.tags = METATAGS.concat(this.tags); + + var lines = this.tags.map(function(tag) { + delete tag.sortno; + var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; + + var addr = tag.addr; + buf.push(addr !== undefined ? addr : "//"); + + var tagfields = []; + for (var key in tag) { + if (!(key in SPECIAL_FIELDS)) { + tagfields.push(key); + } + } + tagfields.sort(); + + var kind = tag.kind; + if (kind === undefined && tagfields.length === 0) { + buf.push("\n"); + return buf.join(""); + } + + buf.push(";\""); + + if (kind !== undefined) { + buf.push("\t", kind); + } + + tagfields.forEach(function(tagfield) { + buf.push("\t", tagfield, ":"); + + var escape = function(str) { return ESCAPES[str]; }; + buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); + }); + + buf.push("\n"); + return buf.join(""); }); - var size = 0; - var buf = [ filename, ",", size, "\n" ] - stream.write(buf.join("")); + lines.forEach(function(line) { stream.write(line); }); - } - }; - var lines = this.tags.map(function(tag) { - delete tag.sortno; - var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; - - var addr = tag.addr; - buf.push(addr !== undefined ? addr : "//"); - - var tagfields = []; - for (var key in tag) { - if (!(key in SPECIAL_FIELDS)) { - tagfields.push(key); - } - } - tagfields.sort(); - - var kind = tag.kind; - if (kind === undefined && tagfields.length === 0) { - buf.push("\n"); - return buf.join(""); - } - - buf.push(";\""); - - if (kind !== undefined) { - buf.push("\t", kind); - } - - tagfields.forEach(function(tagfield) { - buf.push("\t", tagfield, ":"); - - var escape = function(str) { return ESCAPES[str]; }; - buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); - }); - - buf.push("\n"); - return buf.join(""); - }); - - //lines.forEach(function(line) { stream.write(line); }); - }, - - writeJSONP: function(stream, func) { - this.tags.map(function(tag) { delete tag.sortno; }); - var json = JSON.stringify(this.tags); - _([ func, "(", json, ");" ]).each(function(str) { - stream.write(str); - }); - }, -}); + }, + + writeEmacs: function(stream, opts) { + var sections = {}; + this.tags.map(function(tag) { + if (!sections[tag.tagfile]) + sections[tag.tagfile] = new Array(); + sections[tag.tagfile].push(tag); + }); + for (var filename in sections) { + if (sections.hasOwnProperty(filename)) { + stream.write(" \n"); + var section = sections[filename]; + var lines = section.map(function(tag) { + var line_number = tag["lineno"]; + var addr = tag.addr.substr(2, tag.addr.length-4); + addr = addr.replace ("\\t", "\t"); + var buf = [ addr, "", tag.name, "", line_number, ",1"]; + buf.push("\n"); + return buf.join(""); + }); + var size = 0; + var buf = [ filename, ",", size, "\n" ] + stream.write(buf.join("")); + lines.forEach(function(line) { stream.write(line); }); + } + }; + var lines = this.tags.map(function(tag) { + delete tag.sortno; + var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; + + var addr = tag.addr; + buf.push(addr !== undefined ? addr : "//"); + + var tagfields = []; + for (var key in tag) { + if (!(key in SPECIAL_FIELDS)) { + tagfields.push(key); + } + } + tagfields.sort(); + + var kind = tag.kind; + if (kind === undefined && tagfields.length === 0) { + buf.push("\n"); + return buf.join(""); + } + + buf.push(";\""); + + if (kind !== undefined) { + buf.push("\t", kind); + } + + tagfields.forEach(function(tagfield) { + buf.push("\t", tagfield, ":"); + + var escape = function(str) { return ESCAPES[str]; }; + buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); + }); + + buf.push("\n"); + return buf.join(""); + }); + //lines.forEach(function(line) { stream.write(line); }); + }, + + writeJSONP: function(stream, func) { + this.tags.map(function(tag) { delete tag.sortno; }); + var json = JSON.stringify(this.tags); + _([ func, "(", json, ");" ]).each(function(str) { + stream.write(str); + }); + }, +}); From 6f909d13ed7f65b01a96b3501118bdceabe87e07 Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Tue, 27 May 2014 10:32:04 +1200 Subject: [PATCH 6/7] Removed ununused code. --- lib/jsctags/ctags/writer.js | 39 ------------------------------------- 1 file changed, 39 deletions(-) diff --git a/lib/jsctags/ctags/writer.js b/lib/jsctags/ctags/writer.js index c89ac1c..2e0ed0d 100644 --- a/lib/jsctags/ctags/writer.js +++ b/lib/jsctags/ctags/writer.js @@ -155,45 +155,6 @@ exports.TagWriter = Trait({ lines.forEach(function(line) { stream.write(line); }); } }; - var lines = this.tags.map(function(tag) { - delete tag.sortno; - var buf = [ tag.name, "\t", tag.tagfile, "\t" ]; - - var addr = tag.addr; - buf.push(addr !== undefined ? addr : "//"); - - var tagfields = []; - for (var key in tag) { - if (!(key in SPECIAL_FIELDS)) { - tagfields.push(key); - } - } - tagfields.sort(); - - var kind = tag.kind; - if (kind === undefined && tagfields.length === 0) { - buf.push("\n"); - return buf.join(""); - } - - buf.push(";\""); - - if (kind !== undefined) { - buf.push("\t", kind); - } - - tagfields.forEach(function(tagfield) { - buf.push("\t", tagfield, ":"); - - var escape = function(str) { return ESCAPES[str]; }; - buf.push(tag[tagfield].replace("[\\\n\r\t]", escape)); - }); - - buf.push("\n"); - return buf.join(""); - }); - - //lines.forEach(function(line) { stream.write(line); }); }, writeJSONP: function(stream, func) { From c00bbdbf7f45a0339c026eb1f6c0a4c087ac93ec Mon Sep 17 00:00:00 2001 From: Berend de Boer Date: Tue, 27 May 2014 10:43:23 +1200 Subject: [PATCH 7/7] After having problems seeing commands, added tag definition data size --- lib/jsctags/ctags/writer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/jsctags/ctags/writer.js b/lib/jsctags/ctags/writer.js index 2e0ed0d..b19ccc6 100644 --- a/lib/jsctags/ctags/writer.js +++ b/lib/jsctags/ctags/writer.js @@ -149,7 +149,8 @@ exports.TagWriter = Trait({ buf.push("\n"); return buf.join(""); }); - var size = 0; + var s = lines.join("\n"); + var size = s.length; var buf = [ filename, ",", size, "\n" ] stream.write(buf.join("")); lines.forEach(function(line) { stream.write(line); });