@@ -17,13 +17,14 @@ argparse = require "argparse"
17
17
parser = argparse " moon-tags" , " Generate ctags style tags file for MoonScript files"
18
18
parser\ argument( " files" , " MoonScript files to generate tags for" ) \ args " +"
19
19
parser\ flag " --include-line" , " Include line number field for each tag"
20
+ parser\ flag " --lapis" , " Support extracting lapis routes"
20
21
21
22
args = parser\ parse [ v for _, v in ipairs _G . arg]
22
23
23
24
TAGS = {} -- the final output of tags
24
25
25
26
literals = require " moonscript.parse.literals"
26
- import Indent from require " moonscript.parse.util"
27
+ import Indent , simple_string from require " moonscript.parse.util"
27
28
28
29
import P , S , C , Cc , Cg , Cb , Ct , Cs , V from require " lpeg"
29
30
@@ -32,18 +33,20 @@ until_end = (1 - literals.Stop)^0
32
33
whitespace = S " \t " -- not including newline
33
34
ignore_line = Ct until_end -- tag it for empty line
34
35
36
+ -- NOTE: we disable interpolation parsing since we don't have full grammar
37
+ SingleString = simple_string " '" , false
38
+ DoubleString = simple_string ' "' , false
39
+ String = SingleString + DoubleString
40
+
35
41
-- we have to do this double Ct to capture both the full line and the grouped captures
36
42
Type = ( name) -> Cg Cc ( name) , " type"
37
43
Line = ( type_name, p) -> Ct C Ct Cg ( Indent , " indent" ) * p * Type type_name
38
44
39
- class_line = Line " class" , P " class" * whitespace^ 1 * Cg ( literals. Name , " tag" ) * until_end
40
-
41
- -- TODO: support lapis style routes
42
- -- class_property = Line P("@")^-1 * Cg(literals.Name, "tag") * P":" * until_end * Type "property"
43
-
44
45
method = P { P " =>" + P ( 1 - literals. Stop ) * V ( 1 ) }
45
46
func = P { P " ->" + P " =>" + P ( 1 - literals. Stop ) * V ( 1 ) }
46
47
48
+ self_prefix = Cg ( P ( " @" ) * Cc ( true ) , " self" )
49
+
47
50
-- this matches end-of-file return table convention for module files to figure
48
51
-- out what names are exported
49
52
export_list = Ct P " {" * P {
@@ -52,17 +55,37 @@ export_list = Ct P"{" * P {
52
55
53
56
eof_exports = P { export_list * S ( " \t\r\n " ) ^ 0 * P ( - 1 ) + P ( 1 ) * V ( 1 ) }
54
57
58
+ class_line = Line " class" , P " class" * whitespace^ 1 * Cg ( literals. Name , " tag" ) * until_end
59
+ class_property = Line " property" , self_prefix^- 1 * Cg ( literals. Name , " tag" ) * P " :" * whitespace^ 0 * Cg ( String , " value" ) ^ 0 * until_end
55
60
class_method = Line ( " method" , P ( " @" ) ^- 1 * Cg ( literals. Name , " tag" ) * P " :" * method) * until_end
56
61
function_def = Line ( " function" , Cg ( literals. Name , " tag" ) * whitespace^ 0 * P " =" * func) * until_end
62
+ lapis_route = Line " lapis-route" , P " [" * Cg ( literals. Name , " tag" ) * P " :" * whitespace^ 0 * Cg ( String , " route" ) * whitespace^ 0 * P ( " ]:" ) * until_end
63
+
64
+ line_types = class_line + class_method + class_property + function_def
65
+
66
+ if args. lapis
67
+ line_types += lapis_route
57
68
58
69
parse_lines = Ct P {
59
- ( class_line + class_method + function_def + ignore_line) * ( P ( - 1 ) + literals. Break * V ( 1 ))
70
+ ( line_types + ignore_line) * ( P ( - 1 ) + literals. Break * V ( 1 ))
60
71
}
61
72
62
73
escape_tagaddress = ( line_text) ->
63
74
replacements = S ( [[ \/.$^]] ) / [[ \%0]] + P ( " \t " ) / [[ \t]] + P ( " \r " ) / [[ \r]] + P ( " \n " ) / [[ \n]]
64
75
Cs (( replacements + 1 ) ^ 0 ) \ match line_text
65
76
77
+ import types from require " tableshape"
78
+
79
+ class_field = types. partial {
80
+ " self" : true
81
+ tag : types. string\ tag " name"
82
+ value : types. partial {
83
+ " string"
84
+ types. string
85
+ types. string\ tag " value" -- TODO: will need to un-escape this
86
+ }
87
+ }
88
+
66
89
for fname in * args. files
67
90
file = assert io.open fname
68
91
contents = assert file\ read " *a"
@@ -109,6 +132,30 @@ for fname in *args.files
109
132
table.insert fields, 1 , " line:#{line_no}"
110
133
111
134
switch properties. type
135
+ when " lapis-route"
136
+ if cls = find_class properties
137
+ prefix = if cls. fields
138
+ cls. fields. name
139
+
140
+ table.insert TAGS , {
141
+ " #{prefix or " " }#{properties.tag}"
142
+ fname
143
+ " /^#{escape_tagaddress line_text}/;\" "
144
+ " f"
145
+ table.concat fields, " "
146
+ }
147
+
148
+ when " property"
149
+ -- this is necessary to register the correct indent level for the class
150
+ cls = find_class properties
151
+
152
+ -- record the fields into the class object so they can be referenced by
153
+ -- other tags. Note this is code-order dependent
154
+ if cls and args. lapis
155
+ if field = class_field properties
156
+ cls. fields or= {}
157
+ cls. fields[ field. name] = field. value
158
+
112
159
when " function"
113
160
if exports[ properties. tag] and properties. indent == 0
114
161
table.insert TAGS , {
0 commit comments