Coverage for C:\Repos\leo-editor\leo\plugins\importers\elisp.py: 77%

65 statements  

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

1#@+leo-ver=5-thin 

2#@+node:ekr.20140723122936.18141: * @file ../plugins/importers/elisp.py 

3"""The @auto importer for the elisp language.""" 

4import re 

5from typing import Any, Dict, List 

6from leo.core import leoGlobals as g 

7from leo.plugins.importers import linescanner 

8Importer = linescanner.Importer 

9#@+others 

10#@+node:ekr.20161127184128.2: ** class Elisp_Importer 

11class Elisp_Importer(Importer): 

12 """The importer for the elisp lanuage.""" 

13 

14 def __init__(self, importCommands, **kwargs): 

15 """Elisp_Importer.__init__""" 

16 # Init the base class. 

17 super().__init__( 

18 importCommands, 

19 language='lisp', 

20 state_class=Elisp_ScanState, 

21 strict=False, 

22 ) 

23 

24 #@+others 

25 #@+node:ekr.20170205195239.1: *3* elisp_i.get_new_dict 

26 #@@nobeautify 

27 

28 def get_new_dict(self, context): 

29 """elisp state dictionary for the given context.""" 

30 comment, block1, block2 = self.single_comment, self.block1, self.block2 

31 

32 def add_key(d, pattern, data): 

33 key = pattern[0] 

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

35 aList.append(data) 

36 d[key] = aList 

37 

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

39 

40 if context: 

41 d = { 

42 # key kind pattern ends? 

43 '\\': [('len+1', '\\', None),], 

44 '"': [('len', '"', context == '"'),], 

45 # "'": [('len', "'", context == "'"),], 

46 } 

47 if block1 and block2: 

48 # Bug fix: 2016/12/04: the tuple contained block1, not block2. 

49 add_key(d, block2, ('len', block2, True)) 

50 else: 

51 # Not in any context. 

52 d = { 

53 # key kind pattern new-ctx deltas 

54 '\\':[('len+1', '\\', context, None),], 

55 '"': [('len', '"', '"', None),], 

56 # "'": [('len', "'", "'", None),], 

57 '{': [('len', '{', context, (1,0,0)),], 

58 '}': [('len', '}', context, (-1,0,0)),], 

59 '(': [('len', '(', context, (0,1,0)),], 

60 ')': [('len', ')', context, (0,-1,0)),], 

61 '[': [('len', '[', context, (0,0,1)),], 

62 ']': [('len', ']', context, (0,0,-1)),], 

63 } 

64 if comment: 

65 add_key(d, comment, ('all', comment, '', None)) 

66 if block1 and block2: 

67 add_key(d, block1, ('len', block1, block1, None)) 

68 return d 

69 #@+node:ekr.20161127184128.4: *3* elisp_i.clean_headline 

70 elisp_clean_pattern = re.compile(r'^\s*\(\s*defun\s+([\w_-]+)') 

71 

72 def clean_headline(self, s, p=None): 

73 """Return a cleaned up headline s.""" 

74 m = self.elisp_clean_pattern.match(s) 

75 if m and m.group(1): 

76 return 'defun %s' % m.group(1) 

77 return s.strip() 

78 #@+node:ekr.20161127185851.1: *3* elisp_i.starts_block 

79 def starts_block(self, i, lines, new_state, prev_state): 

80 """True if the new state starts a block.""" 

81 line = lines[i] 

82 return self.elisp_clean_pattern.match(line) 

83 #@+node:ekr.20170205194802.1: *3* elisp_i.trace_status 

84 def trace_status(self, line, new_state, prev_state, stack, top): 

85 """Print everything important in the i.gen_lines loop.""" 

86 if line.isspace() or line.strip().startswith(';'): 

87 return # for elisp 

88 print('') 

89 try: 

90 g.trace(repr(line)) 

91 except Exception: 

92 g.trace(f" top.p: {g.toUnicode(top.p.h)}") 

93 # print('len(stack): %s' % len(stack)) 

94 print(' new_state: %s' % new_state) 

95 print('prev_state: %s' % prev_state) 

96 # print(' top.state: %s' % top.state) 

97 g.printList(stack) 

98 #@-others 

99#@+node:ekr.20161127184128.6: ** class Elisp_ScanState 

100class Elisp_ScanState: 

101 """A class representing the state of the elisp line-oriented scan.""" 

102 

103 def __init__(self, d=None): 

104 """Elisp_ScanState.__init__""" 

105 if d: 

106 prev = d.get('prev') 

107 self.context = prev.context 

108 self.parens = prev.parens 

109 else: 

110 self.context = '' 

111 self.parens = 0 

112 

113 def __repr__(self): 

114 """Elisp_ScanState.__repr__""" 

115 return "Elisp_ScanState context: %r parens: %s" % ( 

116 self.context, self.parens) 

117 

118 __str__ = __repr__ 

119 

120 #@+others 

121 #@+node:ekr.20161127184128.7: *3* elisp_state.level 

122 def level(self): 

123 """Elisp_ScanState.level.""" 

124 return self.parens 

125 

126 #@+node:ekr.20161127184128.8: *3* elisp_state.update 

127 def update(self, data): 

128 """ 

129 Elisp_ScanState.update 

130 

131 Update the state using the 6-tuple returned by i.scan_line. 

132 Return i = data[1] 

133 """ 

134 context, i, delta_c, delta_p, delta_s, bs_nl = data 

135 # All ScanState classes must have a context ivar. 

136 self.context = context 

137 self.parens += delta_p 

138 return i 

139 #@-others 

140#@-others 

141importer_dict = { 

142 'func': Elisp_Importer.do_import(), # Also clojure, clojurescript 

143 'extensions': ['.el', '.clj', '.cljs', '.cljc',], 

144} 

145#@@language python 

146#@@tabwidth -4 

147#@-leo