mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
add moon-tags script for generating tag file for moonscript classes
This commit is contained in:
parent
fa104985a6
commit
00397fd64b
123
bin/moon-tags
Executable file
123
bin/moon-tags
Executable file
@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env moon
|
||||
|
||||
HEADER = [[
|
||||
!_TAG_FILE_FORMAT 2 /extended format/
|
||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||
!_TAG_PROGRAM_AUTHOR leaf corcoran /leafot@gmail.com/
|
||||
!_TAG_PROGRAM_NAME MoonTags //
|
||||
!_TAG_PROGRAM_URL https://github.com/leafo/moonscript /GitHub repository/
|
||||
!_TAG_PROGRAM_VERSION 0.0.1 //
|
||||
]]
|
||||
|
||||
-- see `ctags --list-kinds` for examples of kinds
|
||||
-- see `ctags --list-fields`
|
||||
|
||||
argparse = require "argparse"
|
||||
|
||||
parser = argparse "moon-tags", "Generate ctags style tags file for MoonScript files"
|
||||
parser\argument("files", "MoonScript files to generate tags for")\args "+"
|
||||
parser\flag "--include-line", "Include line number field for each tag"
|
||||
|
||||
args = parser\parse [v for _, v in ipairs _G.arg]
|
||||
|
||||
TAGS = {} -- the final output of tags
|
||||
|
||||
literals = require "moonscript.parse.literals"
|
||||
import Indent from require "moonscript.parse.util"
|
||||
|
||||
import P, S, C, Cc, Cg, Cb, Ct, Cs, V from require "lpeg"
|
||||
|
||||
-- consome the rest of the file
|
||||
until_end = (1 - literals.Stop)^0
|
||||
whitespace = S"\t " -- not including newline
|
||||
ignore_line = Ct until_end -- tag it for empty line
|
||||
|
||||
-- we have to do this double Ct to capture both the full line and the grouped captures
|
||||
Line = (p) -> Ct C Ct Cg(Indent, "indent") * p
|
||||
Type = (name) -> Cg Cc(name), "type"
|
||||
|
||||
class_line = Line P"class" * whitespace^1 * Cg(literals.Name, "tag") * until_end * Type "class"
|
||||
-- TODO: support lapis style routes
|
||||
-- class_property = Line P("@")^-1 * Cg(literals.Name, "tag") * P":" * until_end * Type "property"
|
||||
|
||||
method = P { P"=>" + P(1 - literals.Stop) * V(1) }
|
||||
class_method = Line P("@")^-1 * Cg(literals.Name, "tag") * P":" * method * until_end * Type "method"
|
||||
|
||||
parse_lines = Ct P {
|
||||
(class_line + class_method + ignore_line) * (P(-1) + literals.Break * V(1))
|
||||
}
|
||||
|
||||
escape_tagaddress = (line_text) ->
|
||||
replacements = P([[\]]) / [[\\]] + P([[/]]) / [[\/]] + P("\t") / [[\t]] + P("\r") / [[\r]] + P("\n") / [[\n]]
|
||||
Cs((replacements + 1)^0)\match line_text
|
||||
|
||||
for fname in *args.files
|
||||
file = assert io.open fname
|
||||
contents = assert file\read "*a"
|
||||
lines = assert parse_lines\match contents
|
||||
|
||||
class_stack = {}
|
||||
|
||||
push_class = (cls) ->
|
||||
assert cls.type == "class", "not a class match"
|
||||
-- remove classes that are longer in scope due to indentation
|
||||
for i=#class_stack,1,-1
|
||||
top = class_stack[i]
|
||||
|
||||
if cls.indent <= top.indent
|
||||
table.remove class_stack, i
|
||||
else
|
||||
break
|
||||
|
||||
table.insert class_stack, cls
|
||||
|
||||
-- find the class this property is associated with based on change in indent
|
||||
-- the expeted indent is written to `step` on the first proprety
|
||||
find_class = (property) ->
|
||||
for i=#class_stack,1,-1
|
||||
top = class_stack[i]
|
||||
step = property.indent - top.indent
|
||||
|
||||
if step > 0
|
||||
if top.step == nil
|
||||
top.step = step
|
||||
|
||||
if step == top.step
|
||||
return top
|
||||
|
||||
for line_no, line in ipairs lines
|
||||
continue unless next line
|
||||
|
||||
{line_text, properties} = line
|
||||
|
||||
fields = {"language:moon"}
|
||||
if args.include_line
|
||||
table.insert fields, 1, "line:#{line_no}"
|
||||
|
||||
switch properties.type
|
||||
when "method"
|
||||
if cls = find_class properties
|
||||
table.insert fields, "class:#{cls.tag}"
|
||||
|
||||
table.insert TAGS, {
|
||||
properties.tag
|
||||
fname
|
||||
"/^#{escape_tagaddress line_text}$/;\""
|
||||
"f"
|
||||
table.concat fields, " "
|
||||
}
|
||||
when "class"
|
||||
push_class properties
|
||||
|
||||
table.insert TAGS, {
|
||||
properties.tag
|
||||
fname
|
||||
"/^#{escape_tagaddress line_text}$/;\""
|
||||
"c"
|
||||
table.concat fields, " "
|
||||
}
|
||||
|
||||
print HEADER
|
||||
tag_lines = [table.concat(t, "\t") for t in *TAGS]
|
||||
table.sort tag_lines
|
||||
print table.concat tag_lines, "\n"
|
Loading…
Reference in New Issue
Block a user