Skip to content
This repository was archived by the owner on Jul 9, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

13 changes: 12 additions & 1 deletion bin/jsctags.js
Original file line number Diff line number Diff line change
@@ -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
*
Expand Down Expand Up @@ -50,6 +56,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");
Expand All @@ -65,7 +72,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);
Expand Down Expand Up @@ -260,12 +267,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);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/jsctags/ctags/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
211 changes: 119 additions & 92 deletions lib/jsctags/ctags/writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,101 +41,128 @@ 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); });
},

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);
});
},
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("");
});
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); });
}
};
},

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);
});
},
});