Coverage for C:\leo.repo\leo-editor\leo\plugins\importers\perl.py : 74%

Hot-keys on this page
r m x p 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()
33 # This can be a node *outside* parent's tree!
34 if next and self.has_lines(next):
35 lines = self.get_lines(p)
36 if lines:
37 tail = []
38 while lines and lines[-1].strip().startswith('#'):
39 tail.append(lines.pop())
40 if tail:
41 self.set_lines(p, lines)
42 self.prepend_lines(next, reversed(tail))
44 #@+node:ekr.20161129024520.1: *3* perl_i.get_new_dict (test)
45 #@@nobeautify
47 def get_new_dict(self, context):
48 """
49 Return a *general* state dictionary for the given context.
50 Subclasses may override...
51 """
52 comment, block1, block2 = self.single_comment, self.block1, self.block2
54 def add_key(d, key, data):
55 aList = d.get(key,[])
56 aList.append(data)
57 d[key] = aList
59 d: Dict[str, List[Any]]
61 if context:
62 d = {
63 # key kind pattern ends?
64 '\\': [('len+1', '\\', None),],
65 '=': [('len', '=cut', context == '='),],
66 '/': [('len', '/', context == '/'),],
67 '"': [('len', '"', context == '"'),],
68 "'": [('len', "'", context == "'"),],
69 }
70 if block1 and block2:
71 add_key(d, block2[0], ('len', block1, True))
72 else:
73 # Not in any context.
74 d = {
75 # key kind pattern new-ctx deltas
76 '\\':[('len+1', '\\', context, None),],
77 '#': [('all', '#', context, None),],
78 '=': [('len', '=', context, None),],
79 't': [('len', 'tr///', '/', None),],
80 's': [('len', 's///', '/', None),],
81 'm': [('len', 'm//', '/', None),],
82 '/': [('len', '/', '/', None),],
83 '"': [('len', '"', '"', None),],
84 "'": [('len', "'", "'", None),],
85 '{': [('len', '{', context, (1,0,0)),],
86 '}': [('len', '}', context, (-1,0,0)),],
87 '(': [('len', '(', context, (0,1,0)),],
88 ')': [('len', ')', context, (0,-1,0)),],
89 '[': [('len', '[', context, (0,0,1)),],
90 ']': [('len', ']', context, (0,0,-1)),],
91 }
92 if comment:
93 add_key(d, comment[0], ('all', comment, '', None))
94 if block1 and block2:
95 add_key(d, block1[0], ('len', block1, block1, None))
96 return d
97 #@+node:ekr.20161027094537.12: *3* perl_i.skip_regex
98 def skip_regex(self, s, i, pattern):
99 """look ahead for a regex /"""
100 assert self.match(s, i, pattern)
101 i += len(pattern)
102 while i < len(s) and s[i] in ' \t':
103 i += 1
104 if i < len(s) and s[i] == '/':
105 i += 1
106 while i < len(s):
107 progress = i
108 ch = s[i]
109 if ch == '\\':
110 i += 2
111 elif ch == '/':
112 i += 1
113 break
114 else:
115 i += 1
116 assert progress < i
117 return i
118 #@-others
119#@+node:ekr.20161105095705.1: ** class Perl_ScanState
120class Perl_ScanState:
121 """A class representing the state of the perl line-oriented scan."""
123 def __init__(self, d=None):
124 """Perl_ScanState ctor."""
125 if d:
126 prev = d.get('prev')
127 self.context = prev.context
128 self.curlies = prev.curlies
129 self.parens = prev.parens
130 else:
131 self.context = ''
132 self.curlies = self.parens = 0
134 def __repr__(self):
135 """Perl_ScanState.__repr__"""
136 return 'Perl_ScanState context: %r curlies: %s parens: %s' % (
137 self.context, self.curlies, self.parens)
139 __str__ = __repr__
141 #@+others
142 #@+node:ekr.20161119115617.1: *3* perl_state.level
143 def level(self):
144 """Perl_ScanState.level."""
145 return (self.curlies, self.parens)
146 #@+node:ekr.20161119050522.1: *3* perl_state.update
147 def update(self, data):
148 """
149 Update the state using the 6-tuple returned by i.scan_line.
150 Return i = data[1]
151 """
152 context, i, delta_c, delta_p, delta_s, bs_nl = data
153 # self.bs_nl = bs_nl
154 self.context = context
155 self.curlies += delta_c
156 self.parens += delta_p
157 # self.squares += delta_s
158 return i
160 #@-others
162#@-others
163importer_dict = {
164 'func': Perl_Importer.do_import(),
165 'extensions': ['.pl',],
166}
167#@@language python
168#@@tabwidth -4
169#@-leo