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

78 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-24 10:21 -0500

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.""" 

12 

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 ) 

20 

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)) 

42 

43 #@+node:ekr.20161129024520.1: *3* perl_i.get_new_dict (test) 

44 #@@nobeautify 

45 

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 

52 

53 def add_key(d, key, data): 

54 aList = d.get(key,[]) 

55 aList.append(data) 

56 d[key] = aList 

57 

58 d: Dict[str, List[Any]] 

59 

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.""" 

121 

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 

132 

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) 

137 

138 __str__ = __repr__ 

139 

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 

158 

159 #@-others 

160 

161#@-others 

162importer_dict = { 

163 'func': Perl_Importer.do_import(), 

164 'extensions': ['.pl',], 

165} 

166#@@language python 

167#@@tabwidth -4 

168#@-leo