Coverage for C:\leo.repo\leo-editor\leo\plugins\importers\perl.py: 74%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#@+leo-ver=5-thin
2#@+node:ekr.20161027100313.1: * @file ../plugins/importers/perl.py
3"""The @auto importer for Perl."""
4import re
5from typing import Any, Dict, List
6from leo.plugins.importers import linescanner
7Importer = linescanner.Importer
8#@+others
9#@+node:ekr.20161027094537.13: ** class Perl_Importer
10class Perl_Importer(Importer):
11 """A scanner for the perl language."""
13 def __init__(self, importCommands, **kwargs):
14 """The ctor for the Perl_ImportController class."""
15 super().__init__(
16 importCommands,
17 language='perl',
18 state_class=Perl_ScanState,
19 )
21 #@+others
22 #@+node:ekr.20161027183713.1: *3* perl_i.clean_headline
23 def clean_headline(self, s, p=None):
24 """Return a cleaned up headline s."""
25 m = re.match(r'sub\s+(\w+)', s)
26 return 'sub ' + m.group(1) if m else s
27 #@+node:ekr.20161027194956.1: *3* perl_i.clean_nodes
28 def clean_nodes(self, parent):
29 """Clean nodes as part of the perl post pass."""
30 # Move trailing comments into following def nodes.
31 for p in parent.subtree():
32 next = p.threadNext() # This can be a node *outside* parent's tree!
33 if next and self.has_lines(next):
34 lines = self.get_lines(p)
35 if lines:
36 tail = []
37 while lines and lines[-1].strip().startswith('#'):
38 tail.append(lines.pop())
39 if tail:
40 self.set_lines(p, lines)
41 self.prepend_lines(next, reversed(tail))
43 #@+node:ekr.20161129024520.1: *3* perl_i.get_new_dict (test)
44 #@@nobeautify
46 def get_new_dict(self, context):
47 """
48 Return a *general* state dictionary for the given context.
49 Subclasses may override...
50 """
51 comment, block1, block2 = self.single_comment, self.block1, self.block2
53 def add_key(d, key, data):
54 aList = d.get(key,[])
55 aList.append(data)
56 d[key] = aList
58 d: Dict[str, List[Any]]
60 if context:
61 d = {
62 # key kind pattern ends?
63 '\\': [('len+1', '\\', None),],
64 '=': [('len', '=cut', context == '='),],
65 '/': [('len', '/', context == '/'),],
66 '"': [('len', '"', context == '"'),],
67 "'": [('len', "'", context == "'"),],
68 }
69 if block1 and block2:
70 add_key(d, block2[0], ('len', block1, True))
71 else:
72 # Not in any context.
73 d = {
74 # key kind pattern new-ctx deltas
75 '\\':[('len+1', '\\', context, None),],
76 '#': [('all', '#', context, None),],
77 '=': [('len', '=', context, None),],
78 't': [('len', 'tr///', '/', None),],
79 's': [('len', 's///', '/', None),],
80 'm': [('len', 'm//', '/', None),],
81 '/': [('len', '/', '/', None),],
82 '"': [('len', '"', '"', None),],
83 "'": [('len', "'", "'", None),],
84 '{': [('len', '{', context, (1,0,0)),],
85 '}': [('len', '}', context, (-1,0,0)),],
86 '(': [('len', '(', context, (0,1,0)),],
87 ')': [('len', ')', context, (0,-1,0)),],
88 '[': [('len', '[', context, (0,0,1)),],
89 ']': [('len', ']', context, (0,0,-1)),],
90 }
91 if comment:
92 add_key(d, comment[0], ('all', comment, '', None))
93 if block1 and block2:
94 add_key(d, block1[0], ('len', block1, block1, None))
95 return d
96 #@+node:ekr.20161027094537.12: *3* perl_i.skip_regex
97 def skip_regex(self, s, i, pattern):
98 """look ahead for a regex /"""
99 assert self.match(s, i, pattern)
100 i += len(pattern)
101 while i < len(s) and s[i] in ' \t':
102 i += 1
103 if i < len(s) and s[i] == '/':
104 i += 1
105 while i < len(s):
106 progress = i
107 ch = s[i]
108 if ch == '\\':
109 i += 2
110 elif ch == '/':
111 i += 1
112 break
113 else:
114 i += 1
115 assert progress < i
116 return i
117 #@-others
118#@+node:ekr.20161105095705.1: ** class Perl_ScanState
119class Perl_ScanState:
120 """A class representing the state of the perl line-oriented scan."""
122 def __init__(self, d=None):
123 """Perl_ScanState ctor."""
124 if d:
125 prev = d.get('prev')
126 self.context = prev.context
127 self.curlies = prev.curlies
128 self.parens = prev.parens
129 else:
130 self.context = ''
131 self.curlies = self.parens = 0
133 def __repr__(self):
134 """Perl_ScanState.__repr__"""
135 return 'Perl_ScanState context: %r curlies: %s parens: %s' % (
136 self.context, self.curlies, self.parens)
138 __str__ = __repr__
140 #@+others
141 #@+node:ekr.20161119115617.1: *3* perl_state.level
142 def level(self):
143 """Perl_ScanState.level."""
144 return (self.curlies, self.parens)
145 #@+node:ekr.20161119050522.1: *3* perl_state.update
146 def update(self, data):
147 """
148 Update the state using the 6-tuple returned by i.scan_line.
149 Return i = data[1]
150 """
151 context, i, delta_c, delta_p, delta_s, bs_nl = data
152 # self.bs_nl = bs_nl
153 self.context = context
154 self.curlies += delta_c
155 self.parens += delta_p
156 # self.squares += delta_s
157 return i
159 #@-others
161#@-others
162importer_dict = {
163 'func': Perl_Importer.do_import(),
164 'extensions': ['.pl',],
165}
166#@@language python
167#@@tabwidth -4
168#@-leo