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
|
-- Copyright 2007-2009 Mitchell mitchell<att>caladbolg.net. See LICENSE.
local textadept = _G.textadept
local locale = _G.locale
---
-- Module for running/executing source files.
module('_m.textadept.run', package.seeall)
---
-- Executes the command line parameter and prints the output to Textadept.
-- @param command The command line string.
-- It can have the following macros:
-- * %(filepath) The full path of the current file.
-- * %(filedir) The current file's directory path.
-- * %(filename) The name of the file including extension.
-- * %(filename_noext) The name of the file excluding extension.
function execute(command)
local filepath = buffer.filename
local filedir, filename = filepath:match('^(.+[/\\])([^/\\]+)$')
local filename_noext = filename:match('^(.+)%.')
command = command:gsub('%%%b()', {
['%(filepath)'] = filepath,
['%(filedir)'] = filedir,
['%(filename)'] = filename,
['%(filename_noext)'] = filename_noext,
})
local current_dir = lfs.currentdir()
lfs.chdir(filedir)
local p = io.popen(command..' 2>&1')
local out = p:read('*all')
p:close()
lfs.chdir(current_dir)
textadept.print('> '..command..'\n'..out)
buffer:goto_pos(buffer.length)
end
---
-- [Local table] File extensions and their associated 'compile' actions.
-- Each key is a file extension whose value is a command line string to execute.
-- @class table
-- @name compile_for_ext
local compile_for_ext = {
c = 'gcc -pedantic -Os -o "%(filename_noext)" %(filename)',
cpp = 'g++ -pedantic -Os -o "%(filename_noext)" %(filename)',
java = 'javac "%(filename)"'
}
---
-- Compiles the file as specified by its extension in the compile_for_ext table.
-- @see compile_for_ext
function compile()
if not buffer.filename then return end
local action = compile_for_ext[buffer.filename:match('[^.]+$')]
if action then execute(action) end
end
---
-- [Local table] File extensions and their associated 'go' actions.
-- Each key is a file extension whose value is a command line string to execute.
-- @class table
-- @name go_for_ext
local go_for_ext = {
c = '%(filedir)%(filename_noext)',
cpp = '%(filedir)%(filename_noext)',
java = 'java %(filename_noext)',
lua = 'lua %(filename)',
pl = 'perl %(filename)',
php = 'php -f %(filename)',
py = 'python %(filename)',
rb = 'ruby %(filename)',
}
---
-- Runs/executes the file as specified by its extension in the go_for_ext table.
-- @see go_for_ext
function go()
if not buffer.filename then return end
local action = go_for_ext[buffer.filename:match('[^.]+$')]
if action then execute(action) end
end
---
-- [Local table] A table of error string details.
-- Each entry is a table with the following fields:
-- pattern: the Lua pattern that matches a specific error string.
-- filename: the index of the Lua capture that contains the filename the error
-- occured in.
-- line: the index of the Lua capture that contains the line number the error
-- occured on.
-- message: [Optional] the index of the Lua capture that contains the error's
-- message. A call tip will be displayed if a message was captured.
-- When an error message is double-clicked, the user is taken to the point of
-- error.
-- @class table
-- @name error_details
local error_details = {
-- c, c++, and java errors and warnings have the same format as ruby ones
lua = {
pattern = '^lua: (.-):(%d+): (.+)$',
filename = 1, line = 2, message = 3
},
perl = {
pattern = '^(.+) at (.-) line (%d+)',
message = 1, filename = 2, line = 3
},
php_error = {
pattern = '^Parse error: (.+) in (.-) on line (%d+)',
message = 1, filename = 2, line = 3
},
php_warning = {
pattern = '^Warning: (.+) in (.-) on line (%d+)',
message = 1, filename = 2, line = 3
},
python = {
pattern = '^%s*File "([^"]+)", line (%d+)',
filename = 1, line = 2
},
ruby = {
pattern = '^(.-):(%d+): (.+)$',
filename = 1, line = 2, message = 3
},
}
---
-- When the user double-clicks an error message, go to the line in the file
-- the error occured at and display a calltip with the error message.
-- @param pos The position of the caret.
-- @param line_num The line double-clicked.
-- @see error_details
function goto_error(pos, line_num)
local type = buffer._type
if type == locale.MESSAGE_BUFFER or type == locale.ERROR_BUFFER then
line = buffer:get_line(line_num)
for _, error_detail in pairs(error_details) do
local captures = { line:match(error_detail.pattern) }
if #captures > 0 then
local lfs = require 'lfs'
local filename = captures[error_detail.filename]
if lfs.attributes(filename) then
textadept.io.open(filename)
_m.textadept.editing.goto_line(captures[error_detail.line])
local msg = captures[error_detail.message]
if msg then buffer:call_tip_show(buffer.current_pos, msg) end
else
error(string.format(
locale.M_TEXTADEPT_RUN_FILE_DOES_NOT_EXIST, filename))
end
break
end
end
end
end
textadept.events.add_handler('double_click', goto_error)
|