This repository was archived by the owner on Sep 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinit.lua
More file actions
162 lines (146 loc) · 4.82 KB
/
init.lua
File metadata and controls
162 lines (146 loc) · 4.82 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
-- Copyright 2007-2023 Mitchell. See LICENSE.
local M = {}
--[[ This comment is for LuaDoc.
---
-- The python module for Textadept.
-- It provides utilities for editing Python code.
--
-- ### Key Bindings
--
-- + `Shift+Enter` (`⇧↩` | `S-Enter`)
-- Add ':' to the end of the current line and insert a newline.
module('_M.python')]]
-- Sets default buffer properties for Python files.
events.connect(events.LEXER_LOADED, function(name)
if name ~= 'python' then return end
buffer.use_tabs, buffer.tab_width = false, 4
end)
-- Autocompletion and documentation.
---
-- List of ctags files to use for autocompletion.
-- @class table
-- @name tags
M.tags = {_HOME .. '/modules/python/tags', _USERHOME .. '/modules/python/tags'}
-- LuaFormatter off
---
-- Map of expression patterns to their types.
-- Expressions are expected to match after the '=' sign of a statement.
-- @class table
-- @name expr_types
M.expr_types = {
['^[\'"]'] = 'str',
['^%('] = 'tuple',
['^%['] = 'list',
['^{'] = 'dict',
['^open%s*%b()%s*$'] = 'file',
['^%d+%f[^%d%.]'] = 'int',
['^%d+%.'] = 'float'
}
-- LuaFormatter on
local XPM = textadept.editing.XPM_IMAGES
local xpms = {c = XPM.CLASS, f = XPM.METHOD, m = XPM.VARIABLE, M = XPM.STRUCT, v = XPM.VARIABLE}
textadept.editing.autocompleters.python = function()
local list = {}
-- Retrieve the symbol behind the caret.
local line, pos = buffer:get_cur_line()
local symbol, op, part = line:sub(1, pos - 1):match('([%w_%.]-)(%.?)([%w_]*)$')
if symbol == '' and part == '' then return nil end -- nothing to complete
-- Attempt to identify the symbol type.
-- TODO: identify literals like "'foo'." and "[1, 2, 3].".
local assignment = '%f[%w_]' .. symbol:gsub('(%p)', '%%%1') .. '%s*=%s*(.*)$'
for i = buffer:line_from_position(buffer.current_pos) - 1, 1, -1 do
local expr = buffer:get_line(i):match(assignment)
if not expr then goto continue end
for patt, type in pairs(M.expr_types) do
if expr:find(patt) then
symbol = type
break
end
end
if expr:find('^[%u][%w_.]*%s*%b()%s*$') then
symbol = expr:match('^([%u][%w_.]+)%s*%b()%s*$') -- e.g. a = Foo()
break
end
::continue::
end
-- Search through ctags for completions for that symbol.
local name_patt = '^' .. part
local sep = string.char(buffer.auto_c_type_separator)
for _, filename in ipairs(M.tags) do
if not lfs.attributes(filename) then goto continue end
for line in io.lines(filename) do
local name = line:match('^%S+')
if not name:find(name_patt) or list[name] then goto continue end
local fields = line:match(';"\t(.*)$')
local k, class = fields:sub(1, 1), fields:match('class:(%S+)') or ''
if class == symbol then list[#list + 1], list[name] = name .. sep .. xpms[k], true end
::continue::
end
::continue::
end
return #part, list
end
textadept.editing.api_files.python = {
_HOME .. '/modules/python/api', _USERHOME .. '/modules/python/api'
}
-- Commands.
-- Indent on 'Enter' after a ':' or auto-indent on ':'.
events.connect(events.CHAR_ADDED, function(ch)
if buffer.lexer_language ~= 'python' or (ch ~= 10 and ch ~= 58) then return end
local l = buffer:line_from_position(buffer.current_pos)
if l > 1 then
local line = buffer:get_line(l - (ch == 10 and 1 or 0))
if ch == 10 and line:find(':%s+$') then
buffer.line_indentation[l] = buffer.line_indentation[l - 1] + buffer.tab_width
buffer:goto_pos(buffer.line_indent_position[l])
elseif ch == 58 and
(line:find('^%s*else%s*:') or line:find('^%s*elif[^:]+:') or line:find('^%s*except[^:]*:') or
line:find('^%s*finally%s*:')) then
local try = not line:find('^%s*el')
for i = l - 1, 1, -1 do
line = buffer:get_line(i)
if buffer.line_indentation[i] <= buffer.line_indentation[l] and (not try and
(line:find('^%s*if[^:]+:%s+$') or line:find('^%s*while[^:]+:%s+$') or
line:find('^%s*for[^:]+:%s+$')) or line:find('^%s*try%s*:%s+$')) then
local pos, s = buffer.current_pos, buffer.line_indent_position[l]
buffer.line_indentation[l] = buffer.line_indentation[i]
buffer:goto_pos(pos + buffer.line_indent_position[l] - s)
break
end
end
end
end
end)
keys.python['shift+\n'] = function()
buffer:line_end()
buffer:add_text(':')
buffer:new_line()
end
-- Snippets.
local snip = snippets.python
snip['.'] = 'self.'
snip.__ = '__%1(init)__'
snip.def = [[
def %1(name)(%2(arg)):
%3('''%4'''
)]]
snip.defs = [[
def %1(name)(self%2(, %3(arg))):
%4('''%5'''
)]]
snip.ifmain = [[
if __name__ == '__main__':
%1(main())]]
snip.class = [[
class %1(ClassName)%2((%3(object))):
%4('''%5(documentation)'''
)def __init__(self%6(, %7(arg))):
%8(super(%1, self).__init__())]]
snip.try = [[
try:
%0
except %2(Exception) as %3(e):
%4(pass)%5(
finally:
%6(pass))]]
return M