-
Notifications
You must be signed in to change notification settings - Fork 428
/
Copy pathchpltags
executable file
·139 lines (118 loc) · 5.15 KB
/
chpltags
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
import optparse
import os
import subprocess
import sys
from shutil import which
# ctags regexes
c_module = r'/^[ \t]*module[ \t]+([_a-zA-Z0-9$]+)/\1/'
c_enum = r'/^[ \t]*enum[ \t]+([_a-zA-Z0-9$]+)/\1/'
c_class = r'/^[ \t]*(extern[ \t]+)?class[ \t]+([_a-zA-Z0-9$]+)/\2/'
c_record = r'/^[ \t]*(extern[ \t]+)?record[ \t]+([_a-zA-Z0-9$]+)/\2/'
c_func = r'/^[ \t]*((export [_a-zA-Z0-9$]+|inline|extern)[ \t]+)?(proc|iter)[ \t]+((param|ref)[ \t]+)?([_a-zA-Z0-9]+\.)?([_a-zA-Z0-9$]+)/\7/'
ctags_opts = [
'--langdef=Chapel',
'--langmap=Chapel:.chpl',
'--regex-chapel='+c_module+'m,modules,module names/',
'--regex-chapel='+c_enum+'g,enums,enumeration names/',
'--regex-chapel='+c_class+'c,classes,class definitions/',
'--regex-chapel='+c_record+'r,records,record definitions/',
'--regex-chapel='+c_func+'f,functions,function definitions/',
]
# etags regexes use escaped () and | for capturing groups :(
# same as above otherwise
e_module = r'/^[ \t]*module[ \t]+\([_a-zA-Z0-9$]+\)/\1/'
e_enum = r'/^[ \t]*enum[ \t]+\([_a-zA-Z0-9$]+\)/\1/'
e_class = r'/^[ \t]*\(extern[ \t]+\)?class[ \t]+\([_a-zA-Z0-9$]+\)/\2/'
e_record = r'/^[ \t]*\(extern[ \t]+\)?record[ \t]+\([_a-zA-Z0-9$]+\)/\2/'
e_func = r'/^[ \t]*\(\(export [_a-zA-Z0-9$]+\|inline\|extern\)[ \t]+\)?\(proc\|iter\)[ \t]+\(\(param\|ref\)[ \t]+\)?\([_a-zA-Z0-9]+\.\)?\([_a-zA-Z0-9$]+\)/\7/'
etags_opts = [
'-o', 'TAGS',
'--language=none',
'--regex='+e_module,
'--regex='+e_enum,
'--regex='+e_class,
'--regex='+e_record,
'--regex='+e_func,
]
def check_ex_ctags():
if not which('ctags'):
return False
process = subprocess.Popen(['ctags', '--version'],
stdout=subprocess.PIPE)
out, err = process.communicate()
if sys.version_info[0] >= 3 and not isinstance(out, str):
out = str(out, 'utf-8')
return bool(out and ('Exuberant Ctags' in out) and ('+regex' in out))
def collect_chpl_files(file_list, recurse):
result = []
for x in file_list:
if os.path.isfile(x) and os.path.splitext(x)[1] == '.chpl':
result.append(x)
elif recurse:
for root, dirs, files in os.walk(x):
for f in files:
if os.path.splitext(f)[1] == '.chpl':
result.append(os.path.join(root, f))
# skip hidden
dirs[:] = [d for d in dirs if d[0] != '.']
# strip off any leading "./"s from the path to work around a bug in ctags
# (which was fixed ~5 years ago) that results in mangled output
return [p[2:] if p.startswith("./") else p for p in result]
def _main():
parser = optparse.OptionParser(usage="usage: %prog {-e | -v} [-r] [DIR | FILE...]",
epilog="If neither -e or -v are set, a TAGS file will be generated by "
"default. If CHPL_EDITOR or EDITOR are set to vi(m) a tags file "
"will be created instead.")
parser.add_option('-e', '--emacs', dest='emacs', action='store_true',
default=False,
help="Generate a TAGS file.")
parser.add_option('-v', '--vi', dest='vi', action='store_true',
default=False,
help="Generate a tags file.")
parser.add_option('-r', '--recurse', dest='recurse', action='store_true',
default=False,
help="Recurse into directories provided to find .chpl files.")
(options, args) = parser.parse_args()
if options.vi and options.emacs:
sys.stderr.write("chpltags: Can't specify both -e and -v\n")
sys.exit(1)
if not (options.vi or options.emacs):
editor = os.environ.get('CHPL_EDITOR', '')
if not editor:
editor = os.environ.get('EDITOR', '')
if editor.startswith('vi'):
options.vi = True
else:
options.emacs = True
files = collect_chpl_files(args, options.recurse)
if not files:
sys.stderr.write("chpltags: No files specified.\n")
sys.exit(1)
have_ex_ctags = check_ex_ctags()
global ctags_opts, etags_opts
if have_ex_ctags:
if options.emacs:
ctags_opts = ['-e'] + ctags_opts
process = subprocess.Popen(['ctags'] + ctags_opts + files,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
process.communicate()
sys.exit(process.returncode)
elif options.emacs:
if not which('etags'):
sys.stderr.write("chpltags: Must have either Exuberant Ctags "
"with +regex or etags installed to create "
"Chapel tags.\n")
sys.exit(1)
process = subprocess.Popen(['etags'] + etags_opts + files,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
process.communicate()
sys.exit(process.returncode)
elif options.vi:
sys.stderr.write("chpltags: Must have Exuberant Ctags installed with "
"+regex to create Chapel tags.\n")
sys.exit(1)
if __name__ == '__main__':
_main()