-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathinit.lua
More file actions
128 lines (115 loc) · 5.04 KB
/
init.lua
File metadata and controls
128 lines (115 loc) · 5.04 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
-- Copyright 2016-2026 Mitchell. See LICENSE.
--- Textadept module for outputting source files into various formats like HTML.
-- Install this module by copying it into your *~/.textadept/modules/* directory or Textadept's
-- *modules/* directory, and then putting the following in your *~/.textadept/init.lua*:
--
-- ```lua
-- local export = require('export')
-- ```
--
-- There will be a "File > Export" menu.
-- @module export
local M = {}
--- Command used to open exported HTML files in the user's default web browser.
M.browser = OS == 'windows' and 'start ""' or OS == 'macos' and 'open' or 'xdg-open'
--- Show line numbers in exported output.
-- The default value is `true`.
M.line_numbers = true
--- Exports a file to HTML format and opens the result in a web browser.
-- @param[opt=buffer.filename] filename The filename to export.
-- @param[optchain] out_filename The filename to export to. If `nil`, the user is prompted for one.
function M.to_html(filename, out_filename)
-- Prompt the user for the HTML file to export to, if necessary.
filename = filename or buffer.filename or ''
local dir, name = filename:match('^(.-)[/\\]?([^/\\]-)%.?[^.]*$')
out_filename = out_filename or
ui.dialogs.save{title = _L['Save File'], dir = dir, file = name .. '.html'}
if not out_filename then return end
local buffer = buffer
local format = string.format
local html = {}
html[#html + 1] = '<html><head><meta charset="utf-8"/>'
html[#html + 1] = format('<title>%s</title>',
filename:iconv('UTF-8', _CHARSET) or buffer:untitled())
-- Iterate over defined styles and convert them into CSS.
html[#html + 1] = '<style type="text/css">'
for i = 1, view.STYLE_MAX do
name = buffer:name_of_style(i):gsub('%.', '-')
if name == 'Unknown' then goto continue end
local style = {}
-- Convert style properties to CSS.
style[#style + 1] = name == 'default' and '* {' or format('.%s {', name)
if name == 'default' then style[#style + 1] = 'font-family: Monospace;' end
style[#style + 1] = format('font-size: %dpt;', view.style_size[i])
local fore_color = view.style_fore[i]
local r = tonumber(fore_color) & 0xFF
local g = (tonumber(fore_color) & (0xFF << 8)) >> 8
local b = (tonumber(fore_color) & (0xFF << 16)) >> 16
style[#style + 1] = format('color: rgb(%d,%d,%d);', r, g, b)
local back_color = view.style_back[i]
r = tonumber(back_color) & 0xFF
g = (tonumber(back_color) & (0xFF << 8)) >> 8
b = (tonumber(back_color) & (0xFF << 16)) >> 16
style[#style + 1] = format('background-color: rgb(%d,%d,%d);', r, g, b)
if view.style_bold[i] then style[#style + 1] = 'font-weight: bold;' end
if view.style_italic[i] then style[#style + 1] = 'font-style: italic;' end
if view.style_underline[i] then style[#style + 1] = 'text-decoration: underline;' end
style[#style + 1] = '}\n'
html[#html + 1] = table.concat(style, '\n')
::continue::
end
html[#html + 1] = '</style></head><body>'
-- Start inserting line numbers as necessary.
local line_num = 1
local line_num_fmt = format('%%%dd', #tostring(buffer.line_count))
if M.line_numbers then
html[#html + 1] = format('<span class="line_number">%s </span>',
format(line_num_fmt, line_num):gsub(' ', ' '))
line_num = line_num + 1
end
-- Iterate over characters in the buffer, grouping styles into <span>s whose classes are
-- their respective style names.
local style_at = buffer.style_at
local pos = 1
local prev_pos, prev_style
local text_range = buffer.text_range
local position_after = buffer.position_after
local function format_span(code)
-- Ensure HTML entities are escaped and insert line numbers as necessary.
local function insert_line_number()
local suffix = ''
if M.line_numbers then
suffix = format('<span class="line_number">%s </span>',
format(line_num_fmt, line_num):gsub(' ', ' '))
line_num = line_num + 1
end
return format('\n<br/>%s', suffix)
end
code = code:gsub('[<>& ]', {['<'] = '<', ['>'] = '>', ['&'] = '&', [' '] = ' '})
:gsub('\n', insert_line_number)
return format('%s</span>', code)
end
while pos <= buffer.length do
local style = style_at[pos]
if style ~= prev_style then
-- Start of new <span>. Finish the old one first, if necessary.
if prev_pos then html[#html + 1] = format_span(text_range(buffer, prev_pos, pos)) end
html[#html + 1] = format('<span class="%s">', buffer:name_of_style(style):gsub('%.', '-'))
prev_pos, prev_style = pos, style
end
pos = position_after(buffer, pos)
end
-- Finish any incomplete <span>.
if prev_pos then html[#html + 1] = format_span(text_range(buffer, prev_pos, buffer.length + 1)) end
html[#html + 1] = '</body></html>'
-- Done. Export to the file and show it.
io.open(out_filename, 'wb'):write(table.concat(html)):close()
os.spawn(format('%s "%s"', M.browser, out_filename))
end
-- Add a sub-menu.
_L['Export'] = 'E_xport'
_L['Export to HTML...'] = 'Export to _HTML...'
local m_file = textadept.menu.menubar['File']
table.insert(m_file, #m_file - 1, {''}) -- separator
table.insert(m_file, #m_file - 1, {title = _L['Export'], {_L['Export to HTML...'], M.to_html}})
return M