main
Dominik Madarász 2024-03-26 17:15:02 +01:00
parent b14c31b4e0
commit b841064174
196 changed files with 1133249 additions and 1136958 deletions

0
MAKE.sh 100755 → 100644
View File

View File

@ -1,182 +0,0 @@
<!DOCTYPE html>
<!-- This file license is CC0 (https://creativecommons.org/publicdomain/zero/1.0/). -->
<!-- Original code by @SpartanJ https://github.com/SpartanJ/eepp/blob/8552941da19380d7a629c4da80a976aec5d39e5c/bin/emscripten-fs.html -->
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
<!-- <title>Example</title> -->
<style>
body { margin: 0; background-color: black }
.emscripten {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
.loader {
width: 48px;
height: 48px;
border-radius: 50%;
display: inline-block;
border-top: 3px solid #3daee9;
border-right: 3px solid transparent;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
.loader-cont {
display: flex;
width: 100vw;
justify-content: center;
height: 100vh;
align-items: center;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<div id="cont" class="loader-cont">
<span class="loader"></span>
</div>
<script type='text/javascript'>
var loaderCont;
function getDemoScript(name) {
if (name)
return name;
return "index.js";
}
function getParameter(name) {
let url_string = window.location.href;
let url = new URL(url_string);
return url.searchParams.get(name);
}
function loadScript(url, callback) {
loaderCont = document.getElementById('cont');
let head = document.head;
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.onreadystatechange = callback;
script.onload = callback;
head.appendChild(script);
}
var Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
};
})(),
printErr: function(text) {
text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.getElementById('canvas');
var dpi = window.devicePixelRatio;
canvas.width = window.innerWidth*dpi;
canvas.height = window.innerHeight*dpi;
window.addEventListener('resize', () => {
if (canvas.canResize) {
dpi = window.devicePixelRatio;
canvas.width = window.innerWidth*dpi;
canvas.height = window.innerHeight*dpi;
}
})
return canvas;
})(),
setStatus: function(text) {
console.log("status: " + text);
if (text == "Running...")
loaderCont.style.display = 'none';
},
monitorRunDependencies: function(left) {
// no run dependencies to log
},
arguments: window.location.search.substr(1).split('&')
};
window.onerror = function() {
console.log("onerror: " + event);
};
(function() {
loadScript(getDemoScript(getParameter("run")));
})();
</script>
{{{ SCRIPT }}}
<button onclick="openFullscreen();" style="position:relative; z-index: 1000; float: right;">&#x26F6;</button>
<!-- <button id="btn-audio" onclick="toggleAudio();" style="position:relative; z-index: 1000; float: right;">M</button> -->
<script>
function openFullscreen() {
var canvas = document.getElementById("canvas");
if (canvas.requestFullscreen) {
canvas.requestFullscreen();
} else if (canvas.webkitRequestFullscreen) { /* Safari */
canvas.webkitRequestFullscreen();
} else if (canvas.msRequestFullscreen) { /* IE11 */
canvas.msRequestFullscreen();
}
}
</script>
<!-- <script type='text/javascript'>
var audioBtn = document.querySelector('#btn-audio');
// An array of all contexts to resume on the page
const audioContexList = [];
(function() {
// A proxy object to intercept AudioContexts and
// add them to the array for tracking and resuming later
self.AudioContext = new Proxy(self.AudioContext, {
construct(target, args) {
const result = new target(...args);
audioContexList.push(result);
if (result.state == "suspended") audioBtn.value = "RESUME";
return result;
}
});
})();
function toggleAudio() {
var resumed = false;
audioContexList.forEach(ctx => {
if (ctx.state == "suspended") { ctx.resume(); resumed = true; }
else if (ctx.state == "running") ctx.suspend();
});
if (resumed) audioBtn.value = "SUSPEND";
else audioBtn.value = "RESUME";
}
</script> -->
</body>
</html>

View File

@ -1,284 +0,0 @@
local core = require "core"
local common = require "core.common"
local config = require "core.config"
local command = require "core.command"
local style = require "core.style"
local keymap = require "core.keymap"
local translate = require "core.doc.translate"
local RootView = require "core.rootview"
local DocView = require "core.docview"
config.autocomplete_max_suggestions = 6
local autocomplete = {}
autocomplete.map = {}
local mt = { __tostring = function(t) return t.text end }
function autocomplete.add(t)
local items = {}
for text, info in pairs(t.items) do
info = (type(info) == "string") and info
table.insert(items, setmetatable({ text = text, info = info }, mt))
end
autocomplete.map[t.name] = { files = t.files or ".*", items = items }
end
core.add_thread(function()
local cache = setmetatable({}, { __mode = "k" })
local function get_symbols(doc)
local i = 1
local s = {}
while i < #doc.lines do
for sym in doc.lines[i]:gmatch(config.symbol_pattern) do
s[sym] = true
end
i = i + 1
if i % 100 == 0 then coroutine.yield() end
end
return s
end
local function cache_is_valid(doc)
local c = cache[doc]
return c and c.last_change_id == doc:get_change_id()
end
while true do
local symbols = {}
-- lift all symbols from all docs
for _, doc in ipairs(core.docs) do
-- update the cache if the doc has changed since the last iteration
if not cache_is_valid(doc) then
cache[doc] = {
last_change_id = doc:get_change_id(),
symbols = get_symbols(doc)
}
end
-- update symbol set with doc's symbol set
for sym in pairs(cache[doc].symbols) do
symbols[sym] = true
end
coroutine.yield()
end
-- update symbols list
autocomplete.add { name = "open-docs", items = symbols }
-- wait for next scan
local valid = true
while valid do
coroutine.yield(1)
for _, doc in ipairs(core.docs) do
if not cache_is_valid(doc) then
valid = false
end
end
end
end
end)
local partial = ""
local suggestions_idx = 1
local suggestions = {}
local last_line, last_col
local function reset_suggestions()
suggestions_idx = 1
suggestions = {}
end
local function update_suggestions()
local doc = core.active_view.doc
local filename = doc and doc.filename or ""
-- get all relevant suggestions for given filename
local items = {}
for _, v in pairs(autocomplete.map) do
if common.match_pattern(filename, v.files) then
for _, item in pairs(v.items) do
table.insert(items, item)
end
end
end
-- fuzzy match, remove duplicates and store
items = common.fuzzy_match(items, partial)
local j = 1
for i = 1, config.autocomplete_max_suggestions do
suggestions[i] = items[j]
while items[j] and items[i].text == items[j].text do
items[i].info = items[i].info or items[j].info
j = j + 1
end
end
end
local function get_partial_symbol()
local doc = core.active_view.doc
local line2, col2 = doc:get_selection()
local line1, col1 = doc:position_offset(line2, col2, translate.start_of_word)
return doc:get_text(line1, col1, line2, col2)
end
local function get_active_view()
if getmetatable(core.active_view) == DocView then
return core.active_view
end
end
local function get_suggestions_rect(av)
if #suggestions == 0 then
return 0, 0, 0, 0
end
local line, col = av.doc:get_selection()
local x, y = av:get_line_screen_position(line)
x = x + av:get_col_x_offset(line, col - #partial)
y = y + av:get_line_height() + style.padding.y
local font = av:get_font()
local th = font:get_height()
local max_width = 0
for _, s in ipairs(suggestions) do
local w = font:get_width(s.text)
if s.info then
w = w + style.font:get_width(s.info) + style.padding.x
end
max_width = math.max(max_width, w)
end
return
x - style.padding.x,
y - style.padding.y,
max_width + style.padding.x * 2,
#suggestions * (th + style.padding.y) + style.padding.y
end
local function draw_suggestions_box(av)
-- draw background rect
local rx, ry, rw, rh = get_suggestions_rect(av)
renderer.draw_rect(rx, ry, rw, rh, style.background3)
-- draw text
local font = av:get_font()
local lh = font:get_height() + style.padding.y
local y = ry + style.padding.y / 2
for i, s in ipairs(suggestions) do
local color = (i == suggestions_idx) and style.accent or style.text
common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh)
if s.info then
color = (i == suggestions_idx) and style.text or style.dim
common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh)
end
y = y + lh
end
end
-- patch event logic into RootView
local on_text_input = RootView.on_text_input
local update = RootView.update
local draw = RootView.draw
RootView.on_text_input = function(...)
on_text_input(...)
local av = get_active_view()
if av then
-- update partial symbol and suggestions
partial = get_partial_symbol()
if #partial >= 3 then
update_suggestions()
last_line, last_col = av.doc:get_selection()
else
reset_suggestions()
end
-- scroll if rect is out of bounds of view
local _, y, _, h = get_suggestions_rect(av)
local limit = av.position.y + av.size.y
if y + h > limit then
av.scroll.to.y = av.scroll.y + y + h - limit
end
end
end
RootView.update = function(...)
update(...)
local av = get_active_view()
if av then
-- reset suggestions if caret was moved
local line, col = av.doc:get_selection()
if line ~= last_line or col ~= last_col then
reset_suggestions()
end
end
end
RootView.draw = function(...)
draw(...)
local av = get_active_view()
if av then
-- draw suggestions box after everything else
core.root_view:defer_draw(draw_suggestions_box, av)
end
end
local function predicate()
return get_active_view() and #suggestions > 0
end
command.add(predicate, {
["autocomplete:complete"] = function()
local doc = core.active_view.doc
local line, col = doc:get_selection()
local text = suggestions[suggestions_idx].text
doc:insert(line, col, text)
doc:remove(line, col, line, col - #partial)
doc:set_selection(line, col + #text - #partial)
reset_suggestions()
end,
["autocomplete:previous"] = function()
suggestions_idx = math.max(suggestions_idx - 1, 1)
end,
["autocomplete:next"] = function()
suggestions_idx = math.min(suggestions_idx + 1, #suggestions)
end,
["autocomplete:cancel"] = function()
reset_suggestions()
end,
})
keymap.add {
["tab"] = "autocomplete:complete",
["up"] = "autocomplete:previous",
["down"] = "autocomplete:next",
["escape"] = "autocomplete:cancel",
}
return autocomplete

View File

@ -1,114 +0,0 @@
local core = require "core"
local translate = require "core.doc.translate"
local config = require "core.config"
local DocView = require "core.docview"
local command = require "core.command"
local keymap = require "core.keymap"
config.autoinsert_map = {
["["] = "]",
["{"] = "}",
["("] = ")",
['"'] = '"',
["'"] = "'",
["`"] = "`",
}
local function is_closer(chr)
for _, v in pairs(config.autoinsert_map) do
if v == chr then
return true
end
end
end
local function count_char(text, chr)
local count = 0
for _ in text:gmatch(chr) do
count = count + 1
end
return count
end
local on_text_input = DocView.on_text_input
function DocView:on_text_input(text)
local mapping = config.autoinsert_map[text]
-- prevents plugin from operating on `CommandView`
if getmetatable(self) ~= DocView then
return on_text_input(self, text)
end
-- wrap selection if we have a selection
if mapping and self.doc:has_selection() then
local l1, c1, l2, c2, swap = self.doc:get_selection(true)
self.doc:insert(l2, c2, mapping)
self.doc:insert(l1, c1, text)
self.doc:set_selection(l1, c1, l2, c2 + 2, swap)
return
end
-- skip inserting closing text
local chr = self.doc:get_char(self.doc:get_selection())
if text == chr and is_closer(chr) then
self.doc:move_to(1)
return
end
-- don't insert closing quote if we have a non-even number on this line
local line = self.doc:get_selection()
if text == mapping and count_char(self.doc.lines[line], text) % 2 == 1 then
return on_text_input(self, text)
end
-- auto insert closing bracket
if mapping and (chr:find("%s") or is_closer(chr) and chr ~= '"') then
on_text_input(self, text)
on_text_input(self, mapping)
self.doc:move_to(-1)
return
end
on_text_input(self, text)
end
local function predicate()
return getmetatable(core.active_view) == DocView
and not core.active_view.doc:has_selection()
end
command.add(predicate, {
["autoinsert:backspace"] = function()
local doc = core.active_view.doc
local l, c = doc:get_selection()
local chr = doc:get_char(l, c)
if config.autoinsert_map[doc:get_char(l, c - 1)] and is_closer(chr) then
doc:delete_to(1)
end
command.perform "doc:backspace"
end,
["autoinsert:delete-to-previous-word-start"] = function()
local doc = core.active_view.doc
local le, ce = translate.previous_word_start(doc, doc:get_selection())
while true do
local l, c = doc:get_selection()
if l == le and c == ce then
break
end
command.perform "autoinsert:backspace"
end
end,
})
keymap.add {
["backspace"] = "autoinsert:backspace",
["ctrl+backspace"] = "autoinsert:delete-to-previous-word-start",
["ctrl+shift+backspace"] = "autoinsert:delete-to-previous-word-start",
}

View File

@ -1,61 +0,0 @@
local core = require "core"
local config = require "core.config"
local Doc = require "core.doc"
local times = setmetatable({}, { __mode = "k" })
local function update_time(doc)
local info = system.get_file_info(doc.filename)
times[doc] = info.modified
end
local function reload_doc(doc)
local fp = io.open(doc.filename, "r")
local text = fp:read("*a")
fp:close()
local sel = { doc:get_selection() }
doc:remove(1, 1, math.huge, math.huge)
doc:insert(1, 1, text:gsub("\r", ""):gsub("\n$", ""))
doc:set_selection(table.unpack(sel))
update_time(doc)
doc:clean()
core.log_quiet("Auto-reloaded doc \"%s\"", doc.filename)
end
core.add_thread(function()
while true do
-- check all doc modified times
for _, doc in ipairs(core.docs) do
local info = system.get_file_info(doc.filename or "")
if info and times[doc] ~= info.modified then
reload_doc(doc)
end
coroutine.yield()
end
-- wait for next scan
coroutine.yield(config.project_scan_rate)
end
end)
-- patch `Doc.save|load` to store modified time
local load = Doc.load
local save = Doc.save
Doc.load = function(self, ...)
local res = load(self, ...)
update_time(self)
return res
end
Doc.save = function(self, ...)
local res = save(self, ...)
update_time(self)
return res
end

View File

@ -1,35 +0,0 @@
require "plugins.reflow"
local config = require "core.config"
local command = require "core.command"
local DocView = require "core.docview"
config.autowrap_files = { "%.md$", "%.txt$" }
local on_text_input = DocView.on_text_input
DocView.on_text_input = function(self, ...)
on_text_input(self, ...)
-- early-exit if the filename does not match a file type pattern
local filename = self.doc.filename or ""
local matched = false
for _, ptn in ipairs(config.autowrap_files) do
if filename:match(ptn) then
matched = true
break
end
end
if not matched then return end
-- do automatic reflow on line if we're typing at the end of the line and have
-- reached the line limit
local line, col = self.doc:get_selection()
local text = self.doc:get_text(line, 1, line, math.huge)
if #text >= config.line_limit and col > #text then
command.perform("doc:select-lines")
command.perform("reflow:reflow")
command.perform("doc:move-to-next-char")
command.perform("doc:move-to-previous-char")
end
end

View File

@ -1,117 +0,0 @@
local core = require "core"
local style = require "core.style"
local command = require "core.command"
local keymap = require "core.keymap"
local DocView = require "core.docview"
local bracket_maps = {
-- [ ] ( ) { }
{ [91] = 93, [40] = 41, [123] = 125, step = 1 },
-- ] [ ) ( } {
{ [93] = 91, [41] = 40, [125] = 123, step = -1 },
}
local function get_matching_bracket(doc, line, col, line_limit, open_byte, close_byte, step)
local end_line = line + line_limit * step
local depth = 0
while line ~= end_line do
local byte = doc.lines[line]:byte(col)
if byte == open_byte then
depth = depth + 1
elseif byte == close_byte then
depth = depth - 1
if depth == 0 then return line, col end
end
local prev_line, prev_col = line, col
line, col = doc:position_offset(line, col, step)
if line == prev_line and col == prev_col then
break
end
end
end
local state = {}
local function update_state(line_limit)
line_limit = line_limit or math.huge
-- reset if we don't have a document (eg. DocView isn't focused)
local doc = core.active_view.doc
if not doc then
state = {}
return
end
-- early exit if nothing has changed since the last call
local line, col = doc:get_selection()
local change_id = doc:get_change_id()
if state.doc == doc and state.line == line and state.col == col
and state.change_id == change_id and state.limit == line_limit then
return
end
-- find matching bracket if we're on a bracket
local line2, col2
for _, map in ipairs(bracket_maps) do
for i = 0, -1, -1 do
local line, col = doc:position_offset(line, col, i)
local open = doc.lines[line]:byte(col)
local close = map[open]
if close then
line2, col2 = get_matching_bracket(doc, line, col, line_limit, open, close, map.step)
goto found
end
end
end
::found::
-- update
state = {
change_id = change_id,
doc = doc,
line = line,
col = col,
line2 = line2,
col2 = col2,
limit = line_limit,
}
end
local update = DocView.update
function DocView:update(...)
update(self, ...)
update_state(100)
end
local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
draw_line_text(self, idx, x, y)
if self.doc == state.doc and idx == state.line2 then
local color = style.bracketmatch_color or style.syntax["function"]
local x1 = x + self:get_col_x_offset(idx, state.col2)
local x2 = x + self:get_col_x_offset(idx, state.col2 + 1)
local h = math.ceil(1 * SCALE)
renderer.draw_rect(x1, y + self:get_line_height() - h, x2 - x1, h, color)
end
end
command.add("core.docview", {
["bracket-match:move-to-matching"] = function()
update_state()
if state.line2 then
core.active_view.doc:set_selection(state.line2, state.col2)
end
end,
})
keymap.add { ["ctrl+m"] = "bracket-match:move-to-matching" }

View File

@ -1,53 +0,0 @@
-- CloseConfirmX plugin for lite text editor
-- implementation by chekoopa
local core = require "core"
local config = require "core.config"
config.closeconfirmx_use_legacy = false
config.closeconfirmx_use_short_name = true
local legacy_confirm = core.confirm_close_all
local function commandful_confirm()
local dirty_count = 0
local dirty_name
for _, doc in ipairs(core.docs) do
if doc:is_dirty() then
dirty_count = dirty_count + 1
dirty_name = doc:get_name()
end
end
if dirty_count > 0 then
local text
if dirty_count == 1 then
if config.closeconfirmx_use_short_name then
dirty_name = dirty_name:match("[^/%\\]*$")
end
text = string.format("Unsaved changes in \"%s\"; Confirm Exit", dirty_name)
else
text = string.format("Unsaved changes in %d docs; Confirm Exit", dirty_count)
end
core.command_view:enter(text, function(_, item)
if item.text:match("^[cC]") then
core.quit(true)
end
end, function(text)
local items = {}
if not text:find("^[^sS]") then table.insert(items, "Stay here") end
if not text:find("^[^cC]") then table.insert(items, "Close Without Saving") end
return items
end)
-- as we delegate a choice inside the callback,
return false
end
return true
end
function core.confirm_close_all()
if config.closeconfirmx_use_legacy then
return legacy_confirm()
else
return commandful_confirm()
end
end

View File

@ -1,54 +0,0 @@
local common = require "core.common"
local DocView = require "core.docview"
local white = { common.color "#ffffff" }
local black = { common.color "#000000" }
local tmp = {}
local function draw_color_previews(self, idx, x, y, ptn, base, nibbles)
local text = self.doc.lines[idx]
local s, e = 0, 0
while true do
s, e = text:find(ptn, e + 1)
if not s then break end
local str = text:sub(s, e)
local r, g, b = str:match(ptn)
r, g, b = tonumber(r, base), tonumber(g, base), tonumber(b, base)
-- #123 becomes #112233
if nibbles then
r = r * 16
g = g * 16
b = b * 16
end
local x1 = x + self:get_col_x_offset(idx, s)
local x2 = x + self:get_col_x_offset(idx, e + 1)
local oy = self:get_line_text_y_offset()
local text_color = math.max(r, g, b) < 128 and white or black
tmp[1], tmp[2], tmp[3] = r, g, b
local l1, _, l2, _ = self.doc:get_selection(true)
if not (self.doc:has_selection() and idx >= l1 and idx <= l2) then
renderer.draw_rect(x1, y, x2 - x1, self:get_line_height(), tmp)
renderer.draw_text(self:get_font(), str, x1, y + oy, text_color)
end
end
end
local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
draw_line_text(self, idx, x, y)
draw_color_previews(self, idx, x, y, "#(%x%x)(%x%x)(%x%x)%f[%W]", 16)
draw_color_previews(self, idx, x, y, "#(%x)(%x)(%x)%f[%W]", 16, true) -- support #fff css format
draw_color_previews(self, idx, x, y, "rgb?%((%d+)%D+(%d+)%D+(%d+).-%)", 10)
draw_color_previews(self, idx, x, y, "rgba?%((%d+)%D+(%d+)%D+(%d+).-%)", 10)
end

View File

@ -1,383 +0,0 @@
local core = require "core"
local keymap = require "core.keymap"
local command = require "core.command"
local common = require "core.common"
local config = require "core.config"
local style = require "core.style"
local View = require "core.view"
config.console_size = 250 * SCALE
config.max_console_lines = 200
config.autoscroll_console = true
local files = {
script = core.temp_filename(PLATFORM == "Windows" and ".bat"),
script2 = core.temp_filename(PLATFORM == "Windows" and ".bat"),
output = core.temp_filename(),
complete = core.temp_filename(),
}
local console = {}
local views = {}
local pending_threads = {}
local thread_active = false
local output = nil
local output_id = 0
local visible = false
function console.clear()
output = { { text = "", time = 0 } }
end
local function read_file(filename, offset)
local fp = io.open(filename, "rb")
fp:seek("set", offset or 0)
local res = fp:read("*a")
fp:close()
return res
end
local function write_file(filename, text)
local fp = io.open(filename, "w")
fp:write(text)
fp:close()
end
local function lines(text)
return (text .. "\n"):gmatch("(.-)\n")
end
local function push_output(str, opt)
local first = true
for line in lines(str) do
if first then
line = table.remove(output).text .. line
end
line = line:gsub("\x1b%[[%d;]+m", "") -- strip ANSI colors
table.insert(output, {
text = line,
time = os.time(),
icon = line:find(opt.error_pattern) and "!"
or line:find(opt.warning_pattern) and "i",
file_pattern = opt.file_pattern,
})
if #output > config.max_console_lines then
table.remove(output, 1)
for view in pairs(views) do
view:on_line_removed()
end
end
first = false
end
output_id = output_id + 1
core.redraw = true
end
local function init_opt(opt)
local res = {
command = "",
file_pattern = "[^?:%s]+%.[^?:%s]+",
error_pattern = "error",
warning_pattern = "warning",
on_complete = function() end,
}
for k, v in pairs(res) do
res[k] = opt[k] or v
end
return res
end
function console.run(opt)
opt = init_opt(opt)
local function thread()
-- init script file(s)
if PLATFORM == "Windows" then
write_file(files.script, opt.command .. "\n")
write_file(files.script2, string.format([[
@echo off
call %q >%q 2>&1
echo "" >%q
exit
]], files.script, files.output, files.complete))
system.exec(string.format("call %q", files.script2))
else
write_file(files.script, string.format([[
%s
touch %q
]], opt.command, files.complete))
system.exec(string.format("bash %q >%q 2>&1", files.script, files.output))
end
-- checks output file for change and reads
local last_size = 0
local function check_output_file()
if PLATFORM == "Windows" then
local fp = io.open(files.output)
if fp then fp:close() end
end
local info = system.get_file_info(files.output)
if info and info.size > last_size then
local text = read_file(files.output, last_size)
push_output(text, opt)
last_size = info.size
end
end
-- read output file until we get a file indicating completion
while not system.get_file_info(files.complete) do
check_output_file()
coroutine.yield(0.1)
end
check_output_file()
if output[#output].text ~= "" then
push_output("\n", opt)
end
push_output("!DIVIDER\n", opt)
-- clean up and finish
for _, file in pairs(files) do
os.remove(file)
end
opt.on_complete()
-- handle pending thread
local pending = table.remove(pending_threads, 1)
if pending then
core.add_thread(pending)
else
thread_active = false
end
end
-- push/init thread
if thread_active then
table.insert(pending_threads, thread)
else
core.add_thread(thread)
thread_active = true
end
-- make sure static console is visible if it's the only ConsoleView
local count = 0
for _ in pairs(views) do count = count + 1 end
if count == 1 then visible = true end
end
local ConsoleView = View:extend()
function ConsoleView:new()
ConsoleView.super.new(self)
self.scrollable = true
self.hovered_idx = -1
views[self] = true
end
function ConsoleView:try_close(...)
ConsoleView.super.try_close(self, ...)
views[self] = nil
end
function ConsoleView:get_name()
return "Console"
end
function ConsoleView:get_line_height()
return style.code_font:get_height() * config.line_height
end
function ConsoleView:get_line_count()
return #output - (output[#output].text == "" and 1 or 0)
end
function ConsoleView:get_scrollable_size()
return self:get_line_count() * self:get_line_height() + style.padding.y * 2
end
function ConsoleView:get_visible_line_range()
local lh = self:get_line_height()
local min = math.max(1, math.floor(self.scroll.y / lh))
return min, min + math.floor(self.size.y / lh) + 1
end
function ConsoleView:on_mouse_moved(mx, my, ...)
ConsoleView.super.on_mouse_moved(self, mx, my, ...)
self.hovered_idx = 0
for i, item, x,y,w,h in self:each_visible_line() do
if mx >= x and my >= y and mx < x + w and my < y + h then
if item.text:find(item.file_pattern) then
self.hovered_idx = i
end
break
end
end
end
local function resolve_file(name)
if system.get_file_info(name) then
return name
end
local filenames = {}
for _, f in ipairs(core.project_files) do
table.insert(filenames, f.filename)
end
local t = common.fuzzy_match(filenames, name)
return t[1]
end
function ConsoleView:on_line_removed()
local diff = self:get_line_height()
self.scroll.y = self.scroll.y - diff
self.scroll.to.y = self.scroll.to.y - diff
end
function ConsoleView:on_mouse_pressed(...)
local caught = ConsoleView.super.on_mouse_pressed(self, ...)
if caught then
return
end
local item = output[self.hovered_idx]
if item then
local file, line, col = item.text:match(item.file_pattern)
local resolved_file = resolve_file(file)
if not resolved_file then
core.error("Couldn't resolve file \"%s\"", file)
return
end
core.try(function()
core.set_active_view(core.last_active_view)
local dv = core.root_view:open_doc(core.open_doc(resolved_file))
if line then
dv.doc:set_selection(line, col or 0)
dv:scroll_to_line(line, false, true)
end
end)
end
end
function ConsoleView:each_visible_line()
return coroutine.wrap(function()
local x, y = self:get_content_offset()
local lh = self:get_line_height()
local min, max = self:get_visible_line_range()
y = y + lh * (min - 1) + style.padding.y
max = math.min(max, self:get_line_count())
for i = min, max do
local item = output[i]
if not item then break end
coroutine.yield(i, item, x, y, self.size.x, lh)
y = y + lh
end
end)
end
function ConsoleView:update(...)
if self.last_output_id ~= output_id then
if config.autoscroll_console then
self.scroll.to.y = self:get_scrollable_size()
end
self.last_output_id = output_id
end
ConsoleView.super.update(self, ...)
end
function ConsoleView:draw()
self:draw_background(style.background)
local icon_w = style.icon_font:get_width("!")
for i, item, x, y, w, h in self:each_visible_line() do
local tx = x + style.padding.x
local time = os.date("%H:%M:%S", item.time)
local color = style.text
if self.hovered_idx == i then
color = style.accent
renderer.draw_rect(x, y, w, h, style.line_highlight)
end
if item.text == "!DIVIDER" then
local w = style.font:get_width(time)
renderer.draw_rect(tx, y + h / 2, w, math.ceil(SCALE * 1), style.dim)
else
tx = common.draw_text(style.font, style.dim, time, "left", tx, y, w, h)
tx = tx + style.padding.x
if item.icon then
common.draw_text(style.icon_font, color, item.icon, "left", tx, y, w, h)
end
tx = tx + icon_w + style.padding.x
common.draw_text(style.code_font, color, item.text, "left", tx, y, w, h)
end
end
self:draw_scrollbar(self)
end
-- init static bottom-of-screen console
local view = ConsoleView()
local node = core.root_view:get_active_node()
node:split("down", view, true)
function view:update(...)
local dest = visible and config.console_size or 0
self:move_towards(self.size, "y", dest)
ConsoleView.update(self, ...)
end
local last_command = ""
command.add(nil, {
["console:reset-output"] = function()
output = { { text = "", time = 0 } }
end,
["console:open-console"] = function()
local node = core.root_view:get_active_node()
node:add_view(ConsoleView())
end,
["console:toggle"] = function()
visible = not visible
end,
["console:run"] = function()
core.command_view:set_text(last_command, true)
core.command_view:enter("Run Console Command", function(cmd)
console.run { command = cmd }
last_command = cmd
end)
end
})
keymap.add {
["ctrl+."] = "console:toggle",
["ctrl+shift+."] = "console:run",
}
-- for `workspace` plugin:
package.loaded["plugins.console.view"] = ConsoleView
console.clear()
return console

View File

@ -1,271 +0,0 @@
local core = require "core"
local common = require "core.common"
local config = require "core.config"
local command = require "core.command"
local keymap = require "core.keymap"
local style = require "core.style"
local Object = require "core.object"
local RootView = require "core.rootview"
local border_width = 1
local divider_width = 1
local DIVIDER = {}
local ContextMenu = Object:extend()
ContextMenu.DIVIDER = DIVIDER
function ContextMenu:new()
self.itemset = {}
self.show_context_menu = false
self.selected = -1
self.height = 0
self.position = { x = 0, y = 0 }
end
local function get_item_size(item)
local lw, lh
if item == DIVIDER then
lw = 0
lh = divider_width
else
lw = style.font:get_width(item.text)
if item.info then
lw = lw + style.padding.x + style.font:get_width(item.info)
end
lh = style.font:get_height() + style.padding.y
end
return lw, lh
end
function ContextMenu:register(predicate, items)
if type(predicate) == "string" then
predicate = require(predicate)
end
if type(predicate) == "table" then
local class = predicate
predicate = function() return core.active_view:is(class) end
end
local width, height = 0, 0 --precalculate the size of context menu
for i, item in ipairs(items) do
if item ~= DIVIDER then
item.info = keymap.reverse_map[item.command]
end
local lw, lh = get_item_size(item)
width = math.max(width, lw)
height = height + lh
end
width = width + style.padding.x * 2
items.width, items.height = width, height
table.insert(self.itemset, { predicate = predicate, items = items })
end
function ContextMenu:show(x, y)
self.items = nil
for _, items in ipairs(self.itemset) do
if items.predicate(x, y) then
self.items = items.items
break
end
end
if self.items then
local w, h = self.items.width, self.items.height
-- by default the box is opened on the right and below
if x + w >= core.root_view.size.x then
x = x - w
end
if y + h >= core.root_view.size.y then
y = y - h
end
self.position.x, self.position.y = x, y
self.show_context_menu = true
return true
end
return false
end
function ContextMenu:hide()
self.show_context_menu = false
self.items = nil
self.selected = -1
self.height = 0
end
function ContextMenu:each_item()
local x, y, w = self.position.x, self.position.y, self.items.width
local oy = y
return coroutine.wrap(function()
for i, item in ipairs(self.items) do
local _, lh = get_item_size(item)
if y - oy > self.height then break end
coroutine.yield(i, item, x, y, w, lh)
y = y + lh
end
end)
end
function ContextMenu:on_mouse_moved(px, py)
if not self.show_context_menu then return end
for i, item, x, y, w, h in self:each_item() do
if px > x and px <= x + w and py > y and py <= y + h then
system.set_cursor("arrow")
self.selected = i
return true
end
end
self.selected = -1
return true
end
function ContextMenu:on_selected(item)
if type(item.command) == "string" then
command.perform(item.command)
else
item.command()
end
end
function ContextMenu:on_mouse_pressed(button, x, y, clicks)
local selected = (self.items or {})[self.selected]
local caught = false
self:hide()
if button == "left" then
if selected then
self:on_selected(selected)
caught = true
end
end
if button == "right" then
caught = self:show(x, y)
end
return caught
end
-- copied from core.docview
function ContextMenu:move_towards(t, k, dest, rate)
if type(t) ~= "table" then
return self:move_towards(self, t, k, dest, rate)
end
local val = t[k]
if math.abs(val - dest) < 0.5 then
t[k] = dest
else
t[k] = common.lerp(val, dest, rate or 0.5)
end
if val ~= dest then
core.redraw = true
end
end
function ContextMenu:update()
if self.show_context_menu then
self:move_towards("height", self.items.height)
end
end
function ContextMenu:draw()
if not self.show_context_menu then return end
core.root_view:defer_draw(self.draw_context_menu, self)
end
function ContextMenu:draw_context_menu()
if not self.items then return end
local bx, by, bw, bh = self.position.x, self.position.y, self.items.width, self.height
renderer.draw_rect(
bx - border_width,
by - border_width,
bw + (border_width * 2),
bh + (border_width * 2),
style.divider
)
renderer.draw_rect(bx, by, bw, bh, style.background3)
for i, item, x, y, w, h in self:each_item() do
if item == DIVIDER then
renderer.draw_rect(x, y, w, h, style.caret)
else
if i == self.selected then
renderer.draw_rect(x, y, w, h, style.selection)
end
common.draw_text(style.font, style.text, item.text, "left", x + style.padding.x, y, w, h)
if item.info then
common.draw_text(style.font, style.dim, item.info, "right", x, y, w - style.padding.x, h)
end
end
end
end
local menu = ContextMenu()
local root_view_on_mouse_pressed = RootView.on_mouse_pressed
local root_view_on_mouse_moved = RootView.on_mouse_moved
local root_view_update = RootView.update
local root_view_draw = RootView.draw
function RootView:on_mouse_moved(...)
if menu:on_mouse_moved(...) then return end
root_view_on_mouse_moved(self, ...)
end
-- copied from core.rootview
function RootView:on_mouse_pressed(button, x,y, clicks)
local div = self.root_node:get_divider_overlapping_point(x, y)
if div then
self.dragged_divider = div
return
end
local node = self.root_node:get_child_overlapping_point(x, y)
local idx = node:get_tab_overlapping_point(x, y)
if idx then
node:set_active_view(node.views[idx])
if button == "right" then --< @r-lyeh middle>right
node:close_active_view(self.root_node)
end
else
core.set_active_view(node.active_view)
-- send to context menu first
if not menu:on_mouse_pressed(button, x, y, clicks) then
node.active_view:on_mouse_pressed(button, x, y, clicks)
end
end
end
function RootView:update(...)
root_view_update(self, ...)
menu:update()
end
function RootView:draw(...)
root_view_draw(self, ...)
menu:draw()
end
command.add(nil, {
["context:show"] = function()
menu:show(core.active_view.position.x, core.active_view.position.y)
end
})
keymap.add {
["menu"] = "context:show"
}
-- register some sensible defaults
menu:register("core.docview", {
{ text = "Cut", command = "doc:cut" },
{ text = "Copy", command = "doc:copy" },
{ text = "Paste", command = "doc:paste" },
DIVIDER,
{ text = "Command Palette...", command = "core:find-command" }
})
return menu

View File

@ -1,63 +0,0 @@
local core = require "core"
local command = require "core.command"
local config = require "core.config"
local DocView = require "core.docview"
local Doc = require "core.doc"
local cache = setmetatable({}, { __mode = "k" })
local function detect_indent(doc)
for _, text in ipairs(doc.lines) do
local str = text:match("^ +")
if str then return "soft", #str end
local str = text:match("^\t+")
if str then return "hard" end
end
end
local function update_cache(doc)
local type, size = detect_indent(doc)
if type then
cache[doc] = { type = type, size = size }
end
end
local new = Doc.new
function Doc:new(...)
new(self, ...)
update_cache(self)
end
local clean = Doc.clean
function Doc:clean(...)
clean(self, ...)
update_cache(self)
end
local function with_indent_override(doc, fn, ...)
local c = cache[doc]
if not c then
return fn(...)
end
local type, size = config.tab_type, config.indent_size
config.tab_type, config.indent_size = c.type, c.size or config.indent_size
local r1, r2, r3 = fn(...)
config.tab_type, config.indent_size = type, size
return r1, r2, r3
end
local perform = command.perform
function command.perform(...)
return with_indent_override(core.active_view.doc, perform, ...)
end
local draw = DocView.draw
function DocView:draw(...)
return with_indent_override(self.doc, draw, self, ...)
end

View File

@ -1,37 +0,0 @@
local common = require "core.common"
local config = require "core.config"
local style = require "core.style"
local DocView = require "core.docview"
local command = require "core.command"
-- originally written by luveti
config.whitespace_map = { [" "] = "·", ["\t"] = "»" }
config.draw_whitespace = true
local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
draw_line_text(self, idx, x, y)
if not config.draw_whitespace then return end
local text = self.doc.lines[idx]
local tx, ty = x, y + self:get_line_text_y_offset()
local font = self:get_font()
local color = style.whitespace or style.syntax.comment
local map = config.whitespace_map
for chr in common.utf8_chars(text) do
local rep = map[chr]
if rep then
renderer.draw_text(font, rep, tx, ty, color)
end
tx = tx + font:get_width(chr)
end
end
command.add("core.docview", {
["draw-whitespace:toggle"] = function() config.draw_whitespace = not config.draw_whitespace end,
["draw-whitespace:disable"] = function() config.draw_whitespace = false end,
["draw-whitespace:enable"] = function() config.draw_whitespace = true end,
})

View File

@ -1,29 +0,0 @@
local core = require "core"
local command = require "core.command"
local Doc = require "core.doc"
local function eof_newline(doc)
local leof,neof = #doc.lines,#doc.lines
for i = leof,1,-1 do
if not string.match(doc.lines[i],"^%s*$") then break end
neof = i
end
local eol,_ = string.find(doc.lines[neof],"\n")
if eol then
doc:remove(neof,eol,math.huge,math.huge)
return
end
doc:insert(neof,math.huge,"\n")
end
command.add("core.docview", {
["eof-newline:eof-newline"] = function()
eof_newline(core.active_view.doc)
end,
})
local save = Doc.save
Doc.save = function(self, ...)
eof_newline(self)
save(self, ...)
end

View File

@ -1,167 +0,0 @@
-- mod-version:1 -- lite-xl 1.16
local core = require "core"
local common = require "core.common"
local command = require "core.command"
local fsutils = {}
function fsutils.iterdir(dir)
local stack = { dir }
return function()
local path = table.remove(stack)
if not path then return end
for _, file in ipairs(system.list_dir(path) or {}) do
stack[#stack + 1] = path .. PATHSEP .. file
end
return path, system.get_file_info(path)
end
end
function fsutils.delete(dir, yield)
local dirs = {}
local n = 0
for filename, stat in fsutils.iterdir(dir) do
if stat.type == "dir" then
-- this will later allow us to delete the dirs in correct sequence
table.insert(dirs, filename)
else
os.remove(filename)
if yield then
n = n + 1
coroutine.yield(n)
end
end
end
for i = #dirs, 1, -1 do
os.remove(dirs[i])
if yield then
n = n + 1
coroutine.yield(n)
end
end
end
function fsutils.move(oldname, newname)
os.rename(oldname, newname)
end
function fsutils.split(path)
local segments = {}
local pos = 1
while true do
local s, e = string.find(path, "[/\\]+", pos)
if not s then break end
table.insert(segments, string.sub(path, pos, s - 1))
pos = e + 1
end
table.insert(list, string.sub(path, pos))
if segments[#segments] == '' then
table.remove(segments)
end
return segments
end
function fsutils.normalize(path)
return table.concat(fsutils.split(path), PATHSEP)
end
function fsutils.normalize_posix(path)
return table.concat(fsutils.split(path), '/')
end
function fsutils.mkdir(path)
local segments = fsutils.split(path)
if system.mkdir then
local p = ""
for i = 1, #segments do
p = table.concat(segments, PATHSEP, 1, i)
end
if p == "" then
return nil, "path empty", p
end
local stat = system.get_file_info(p)
if stat and stat.type == "file" then
return nil, "path exists as a file", p
end
local ok, err = system.mkdir(p)
if not ok then
return nil, err, p
end
else
-- just wing it lol
system.exec(string.format(PLATFORM == "Windows" and "setlocal enableextensions & mkdir %q" or "mkdir -p %q", fsutils.normalize(path)))
end
end
local function async_exec(f, cb)
cb = cb or function() end
local co = coroutine.create(f)
local function resolve(...)
local ok, exec_body = coroutine.resume(co, ...)
if not ok then
error(debug.traceback(co, exec_body))
end
if coroutine.status(co) ~= "dead" then
exec_body(resolve)
end
end
resolve(cb)
end
local function prompt(text, suggest)
return coroutine.yield(function(resolve)
core.command_view:enter(text, resolve, suggest)
end)
end
command.add(nil, {
["files:delete"] = function()
async_exec(function()
local path = prompt("Delete", common.path_suggest)
core.add_thread(function()
-- we use a wrapping coroutine to get status
local function delete()
return coroutine.wrap(function() fsutils.delete(path, true) end)
end
for n in delete() do
if n % 100 == 0 then
core.log("Deleted %d items...", n)
coroutine.yield()
end
end
core.log("%q deleted.", path)
end)
end)
end,
["files:move"] = function()
async_exec(function()
local oldname = prompt("Move", common.path_suggest)
local newname = prompt("To", common.path_suggest)
fsutils.move(oldname, newname)
core.log("Moved %q to %q", oldname, newname)
end)
end
})
if not command.map["files:create-directory"] then
command.add(nil, {
["files:create-directory"] = function()
async_exec(function()
local path = prompt("Name", common.path_suggest)
fsutils.mkdir(path)
core.log("%q created.", path)
end)
end
})
end
return fsutils

View File

@ -1,45 +0,0 @@
local style = require "core.style"
local config = require "core.config"
local DocView = require "core.docview"
local function get_line_spaces(doc, idx, dir)
local text = doc.lines[idx]
if not text then
return 0
end
local s, e = text:find("^%s*")
if e == #text then
return get_line_spaces(doc, idx + dir, dir)
end
local n = 0
for i = s, e do
n = n + (text:byte(i) == 9 and config.indent_size or 1)
end
return n
end
local function get_line_indent_guide_spaces(doc, idx)
if doc.lines[idx]:find("^%s*\n") then
return math.max(
get_line_spaces(doc, idx - 1, -1),
get_line_spaces(doc, idx + 1, 1))
end
return get_line_spaces(doc, idx)
end
local draw_line_text = DocView.draw_line_text
function DocView:draw_line_text(idx, x, y)
local spaces = get_line_indent_guide_spaces(self.doc, idx)
local sw = self:get_font():get_width(" ")
local w = math.ceil(1 * SCALE)
local h = self:get_line_height()
for i = 0, spaces - 1, config.indent_size do
local color = style.guide or style.selection
renderer.draw_rect(x + sw * i, y, w, h, color)
end
draw_line_text(self, idx, x, y)
end

View File

@ -1,64 +0,0 @@
local core = require "core"
local command = require "core.command"
local config = require "core.config"
local keymap = require "core.keymap"
config.lfautoinsert_map = {
["{%s*\n"] = "}",
["%(%s*\n"] = ")",
["%f[[]%[%s*\n"] = "]",
["%[%[%s*\n"] = "]]",
["=%s*\n"] = false,
[":%s*\n"] = false,
["^#if.*\n"] = "#endif",
["^#else.*\n"] = "#endif",
["%f[%w]do%s*\n"] = "end",
["%f[%w]then%s*\n"] = "end",
["%f[%w]else%s*\n"] = "end",
["%f[%w]repeat%s*\n"] = "until",
["%f[%w]function.*%)%s*\n"] = "end",
["^%s*<([^/][^%s>]*)[^>]*>%s*\n"] = "</$TEXT>",
}
local function indent_size(doc, line)
local text = doc.lines[line] or ""
local s, e = text:find("^[\t ]*")
return e - s
end
command.add("core.docview", {
["autoinsert:newline"] = function()
command.perform("doc:newline")
local doc = core.active_view.doc
local line, col = doc:get_selection()
local text = doc.lines[line - 1]
for ptn, close in pairs(config.lfautoinsert_map) do
local s, _, str = text:find(ptn)
if s then
if close
and col == #doc.lines[line]
and indent_size(doc, line + 1) <= indent_size(doc, line - 1)
then
close = str and close:gsub("$TEXT", str) or close
command.perform("doc:newline")
core.active_view:on_text_input(close)
command.perform("doc:move-to-previous-line")
if doc.lines[line+1] == doc.lines[line+2] then
doc:remove(line+1, 1, line+2, 1)
end
elseif col < #doc.lines[line] then
command.perform("doc:newline")
command.perform("doc:move-to-previous-line")
end
command.perform("doc:indent")
end
end
end
})
keymap.add {
["return"] = { "command:submit", "autoinsert:newline" }
}

View File

@ -1,18 +0,0 @@
local config = require "core.config"
local style = require "core.style"
local DocView = require "core.docview"
local draw = DocView.draw
function DocView:draw(...)
draw(self, ...)
local offset = self:get_font():get_width("n") * config.line_limit
local x = self:get_line_screen_position(1) + offset
local y = self.position.y
local w = math.ceil(SCALE * 1)
local h = self.size.y
local color = style.guide or style.selection
renderer.draw_rect(x, y, w, h, color)
end

View File

@ -1,70 +0,0 @@
-- mod-version:3
local core = require "core"
local command = require "core.command"
local keymap = require "core.keymap"
local handled_events = {
["keypressed"] = true,
["keyreleased"] = true,
["textinput"] = true,
}
local state = "stopped"
local event_buffer = {}
local modkeys = {}
local on_event = core.on_event
core.on_event = function(type, ...)
local res = on_event(type, ...)
if state == "recording" and handled_events[type] then
table.insert(event_buffer, { type, ... })
end
return res
end
local function clone(t)
local res = {}
for k, v in pairs(t) do res[k] = v end
return res
end
local function predicate()
return state ~= "playing"
end
command.add(predicate, {
["macro:toggle-record"] = function()
if state == "stopped" then
state = "recording"
event_buffer = {}
modkeys = clone(keymap.modkeys)
core.log("Recording macro...")
else
state = "stopped"
core.log("Stopped recording macro (%d events)", #event_buffer)
end
end,
["macro:play"] = function()
state = "playing"
core.log("Playing macro... (%d events)", #event_buffer)
local mk = keymap.modkeys
keymap.modkeys = clone(modkeys)
for _, ev in ipairs(event_buffer) do
on_event(table.unpack(ev))
core.root_view:update()
end
keymap.modkeys = mk
state = "stopped"
end,
})
keymap.add {
["ctrl+shift+;"] = "macro:toggle-record",
["ctrl+;"] = "macro:play",
}

View File

@ -1,103 +0,0 @@
-- Markers plugin for lite text editor
-- original implementation by Petri Häkkinen
local core = require "core"
local command = require "core.command"
local keymap = require "core.keymap"
local style = require "core.style"
local DocView = require "core.docview"
local Doc = require "core.doc"
local cache = {} -- this table contains subtables for each document, each subtable is a set of line numbers
setmetatable(cache, {
__mode = "k",
__index = function(t, k)
t[k] = {}
return t[k]
end,
})
local function shift_lines(doc, at, diff)
if diff == 0 then return end
local t = {}
for line in pairs(cache[doc]) do
line = line >= at and line + diff or line
t[line] = true
end
cache[doc] = t
end
local raw_insert = Doc.raw_insert
function Doc:raw_insert(line, col, text, ...)
raw_insert(self, line, col, text, ...)
local line_count = 0
for _ in text:gmatch("\n") do
line_count = line_count + 1
end
shift_lines(self, line, line_count)
end
local raw_remove = Doc.raw_remove
function Doc:raw_remove(line1, col1, line2, col2, ...)
raw_remove(self, line1, col1, line2, col2, ...)
shift_lines(self, line2, line1 - line2)
end
local draw_line_gutter = DocView.draw_line_gutter
function DocView:draw_line_gutter(idx, x, y)
if cache[self.doc] and cache[self.doc][idx] then
local h = self:get_line_height()
renderer.draw_rect(x, y, style.padding.x * 0.4, h, style.selection)
end
draw_line_gutter(self, idx, x, y)
end
command.add("core.docview", {
["markers:toggle-marker"] = function()
local doc = core.active_view.doc
local line = doc:get_selection()
local markers = cache[doc]
if markers[line] then
markers[line] = nil
else
markers[line] = true
end
end,
["markers:go-to-next-marker"] = function()
local doc = core.active_view.doc
local line = doc:get_selection()
local markers = cache[doc]
local first_marker = math.huge
local next_marker = math.huge
for l, _ in pairs(markers) do
if l > line and l < next_marker then
next_marker = l
end
first_marker = math.min(first_marker, l)
end
if next_marker == math.huge then
next_marker = first_marker
end
if next_marker ~= math.huge then
doc:set_selection(next_marker, 1)
core.active_view:scroll_to_line(next_marker, true)
end
end,
})
keymap.add {
["ctrl+f2"] = "markers:toggle-marker",
["f2"] = "markers:go-to-next-marker",
}

View File

@ -1,295 +0,0 @@
local command = require "core.command"
local common = require "core.common"
local config = require "core.config"
local style = require "core.style"
local DocView = require "core.docview"
-- General plugin settings
config.minimap_enabled = true
config.minimap_width = 100
config.minimap_instant_scroll = false
config.minimap_syntax_highlight = true
config.minimap_scale = 1
config.minimap_draw_background = true
-- Configure size for rendering each char in the minimap
local char_height = 1 * SCALE * config.minimap_scale
local char_spacing = 0.8 * SCALE * config.minimap_scale
local line_spacing = 2 * SCALE * config.minimap_scale
-- Overloaded since the default implementation adds a extra x3 size of hotspot for the mouse to hit the scrollbar.
local prev_scrollbar_overlaps_point = DocView.scrollbar_overlaps_point
DocView.scrollbar_overlaps_point = function(self, x, y)
if not config.minimap_enabled then return prev_scrollbar_overlaps_point(self, x, y) end
local sx, sy, sw, sh = self:get_scrollbar_rect()
return x >= sx and x < sx + sw and y >= sy and y < sy + sh
end
-- Helper function to determine if current file is too large to be shown fully inside the minimap area.
local function is_file_too_large(self)
local line_count = #self.doc.lines
local _, _, _, sh = self:get_scrollbar_rect()
-- check if line count is too large to fit inside the minimap area
local max_minmap_lines = math.floor(sh / line_spacing)
return line_count > 1 and line_count > max_minmap_lines
end
-- Overloaded with an extra check if the user clicked inside the minimap to automatically scroll to that line.
local prev_on_mouse_pressed = DocView.on_mouse_pressed
DocView.on_mouse_pressed = function(self, button, x, y, clicks)
if not config.minimap_enabled then return prev_on_mouse_pressed(self, button, x, y, clicks) end
-- check if user clicked in the minimap area and jump directly to that line
-- unless they are actually trying to perform a drag
local minimap_hit = self:scrollbar_overlaps_point(x, y)
if minimap_hit then
local line_count = #self.doc.lines
local minimap_height = line_count * line_spacing
-- check if line count is too large to fit inside the minimap area
local is_too_large = is_file_too_large(self)
if is_too_large then
local _, _, _, sh = self:get_scrollbar_rect()
minimap_height = sh
end
-- calc which line to jump to
local dy = y - self.position.y
local jump_to_line = math.floor((dy / minimap_height) * line_count) + 1
local _, cy, _, cy2 = self:get_content_bounds()
local lh = self:get_line_height()
local visible_lines_count = math.max(1, (cy2 - cy) / lh)
local visible_lines_start = math.max(1, math.floor(cy / lh))
-- calc if user hit the currently visible area
local hit_visible_area = true
if is_too_large then
local visible_height = visible_lines_count * line_spacing
local scroll_pos = (visible_lines_start-1) / (line_count - visible_lines_count - 1)
scroll_pos = math.min(1.0, scroll_pos) -- 0..1
local visible_y = self.position.y + scroll_pos * (minimap_height - visible_height)
local t = (line_count - visible_lines_start) / visible_lines_count
if t <= 1 then
visible_y = visible_y + visible_height * (1.0 - t)
end
if y < visible_y or y > visible_y + visible_height then
hit_visible_area = false
end
else
-- If the click is on the currently visible line numbers,
-- ignore it since then they probably want to initiate a drag instead.
if jump_to_line < visible_lines_start or jump_to_line > visible_lines_start + visible_lines_count then
hit_visible_area = false
end
end
-- if user didn't click on the visible area (ie not dragging), scroll accordingly
if not hit_visible_area then
self:scroll_to_line(jump_to_line, false, config.minimap_instant_scroll)
return
end
end
return prev_on_mouse_pressed(self, button, x, y, clicks)
end
-- Overloaded with pretty much the same logic as original DocView implementation,
-- with the exception of the dragging scrollbar delta. We want it to behave a bit snappier
-- since the "scrollbar" essentially represents the lines visible in the content view.
local prev_on_mouse_moved = DocView.on_mouse_moved
DocView.on_mouse_moved = function(self, x, y, dx, dy)
if not config.minimap_enabled then return prev_on_mouse_moved(self, x, y, dx, dy) end
if self.dragging_scrollbar then
local line_count = #self.doc.lines
local lh = self:get_line_height()
local delta = lh / line_spacing * dy
if is_file_too_large(self) then
local _, sy, _, sh = self:get_scrollbar_rect()
delta = (line_count * lh) / sh * dy
end
self.scroll.to.y = self.scroll.to.y + delta
end
-- we need to "hide" that the scrollbar is dragging so that View doesnt does its own scrolling logic
local t = self.dragging_scrollbar
self.dragging_scrollbar = false
local r = prev_on_mouse_moved(self, x, y, dx, dy)
self.dragging_scrollbar = t
return r
end
-- Overloaded since we want the mouse to interact with the full size of the minimap area,
-- not juse the scrollbar.
local prev_get_scrollbar_rect = DocView.get_scrollbar_rect
DocView.get_scrollbar_rect = function (self)
if not config.minimap_enabled then return prev_get_scrollbar_rect(self) end
return
self.position.x + self.size.x - config.minimap_width * SCALE,
self.position.y,
config.minimap_width * SCALE,
self.size.y
end
-- Overloaded so we can render the minimap in the "scrollbar area".
local prev_draw_scrollbar = DocView.draw_scrollbar
DocView.draw_scrollbar = function (self)
if not config.minimap_enabled then return prev_draw_scrollbar(self) end
local x, y, w, h = self:get_scrollbar_rect()
local highlight = self.hovered_scrollbar or self.dragging_scrollbar
local visual_color = highlight and style.scrollbar2 or style.scrollbar
local _, cy, _, cy2 = self:get_content_bounds()
local lh = self:get_line_height()
local visible_lines_count = math.max(1, (cy2 - cy) / lh)
local visible_lines_start = math.max(1, math.floor(cy / lh))
local scroller_height = visible_lines_count * line_spacing
local line_count = #self.doc.lines
local visible_y = self.position.y + (visible_lines_start-1) * line_spacing
-- check if file is too large to fit inside the minimap area
local max_minmap_lines = math.floor(h / line_spacing)
local minimap_start_line = 1
if is_file_too_large(self) then
local scroll_pos = (visible_lines_start-1) / (line_count - visible_lines_count - 1)
scroll_pos = math.min(1.0, scroll_pos) -- 0..1, procent of visual area scrolled
local scroll_pos_pixels = scroll_pos * (h - scroller_height)
visible_y = self.position.y + scroll_pos_pixels
-- offset visible area if user is scrolling past end
local t = (line_count - visible_lines_start) / visible_lines_count
if t <= 1 then
visible_y = visible_y + scroller_height * (1.0 - t)
end
minimap_start_line = visible_lines_start - math.floor(scroll_pos_pixels / line_spacing)
minimap_start_line = math.max(1, math.min(minimap_start_line, line_count - max_minmap_lines))
end
if config.minimap_draw_background then
renderer.draw_rect(x, y, w, h, style.minimap_background or style.background)
end
-- draw visual rect
renderer.draw_rect(x, visible_y, w, scroller_height, visual_color)
-- time to draw the actual code, setup some local vars that are used in both highlighted and plain renderind.
local line_y = y
-- when not using syntax highlighted rendering, just use the normal color but dim it 50%.
local color = style.syntax["normal"]
color = { color[1],color[2],color[3],color[4] * 0.5 }
-- we try to "batch" characters so that they can be rendered as just one rectangle instead of one for each.
local batch_width = 0
local batch_start = x
local minimap_cutoff_x = x + config.minimap_width * SCALE
-- render lines with syntax highlighting
if config.minimap_syntax_highlight then
-- keep track of the highlight type, since this needs to break batches as well
local batch_syntax_type = nil
local function flush_batch(type)
if batch_width > 0 then
-- fetch and dim colors
color = style.syntax[batch_syntax_type]
color = { color[1], color[2], color[3], color[4] * 0.5 }
renderer.draw_rect(batch_start, line_y, batch_width, char_height, color)
end
batch_syntax_type = type
batch_start = batch_start + batch_width
batch_width = 0
end
-- per line
local endidx = minimap_start_line + max_minmap_lines
endidx = math.min(endidx, line_count)
for idx=minimap_start_line,endidx do
batch_syntax_type = nil
batch_start = x
batch_width = 0
-- per token
for _, type, text in self.doc.highlighter:each_token(idx) do
-- flush prev batch
if not batch_syntax_type then batch_syntax_type = type end
if batch_syntax_type ~= type then
flush_batch(type)
end
-- per character
for char in common.utf8_chars(text) do
if char == " " or char == "\n" then
flush_batch(type)
batch_start = batch_start + char_spacing
elseif batch_start + batch_width > minimap_cutoff_x then
flush_batch(type)
break
else
batch_width = batch_width + char_spacing
end
end
end
flush_batch(nil)
line_y = line_y + line_spacing
end
else -- render lines without syntax highlighting
local function flush_batch()
if batch_width > 0 then
renderer.draw_rect(batch_start, line_y, batch_width, char_height, color)
end
batch_start = batch_start + batch_width
batch_width = 0
end
for idx=1,line_count-1 do
batch_start = x
batch_width = 0
for char in common.utf8_chars(self.doc.lines[idx]) do
if char == " " or char == "\n" then
flush_batch()
batch_start = batch_start + char_spacing
elseif batch_start + batch_width > minimap_cutoff_x then
flush_batch()
else
batch_width = batch_width + char_spacing
end
end
flush_batch()
line_y = line_y + line_spacing
end
end
end
command.add(nil, {
["minimap:toggle-visibility"] = function()
config.minimap_enabled = not config.minimap_enabled
end,
["minimap:toggle-syntax-highlighting"] = function()
config.minimap_syntax_highlight = not config.minimap_syntax_highlight
end,
})

View File

@ -1,56 +0,0 @@
local core = require "core"
local config = require "core.config"
local style = require "core.style"
local Doc = require "core.doc"
local DocView = require "core.docview"
config.motiontrail_steps = config.motiontrail_steps or 50
local function doc()
return core.active_view.doc
end
local function lerp(a, b, t)
return a + (b - a) * t
end
local function get_caret_rect(dv, idx)
local line1, col1, line2, col2 = doc():get_selection_idx(idx)
local x1, y1 = dv:get_line_screen_position(line1)
x1 = x1 + dv:get_col_x_offset(line1, col1)
return x1, y1, style.caret_width, dv:get_line_height()
end
local last_x = {}
local last_y = {}
local last_view = {}
local draw = DocView.draw
function DocView:draw(...)
draw(self, ...)
if self ~= core.active_view then return end
for idx, line1, col1, line2, col2 in doc():get_selections(true, true) do
--if line1 == line2 and col1 == col2 then return false end
local x, y, w, h = get_caret_rect(self, idx)
if last_view[idx] == self and (x ~= last_x[idx] or y ~= last_y[idx]) then
local lx = x
for i = 0, 1, 1 / config.motiontrail_steps do
local ix = lerp(x, last_x[idx], i)
local iy = lerp(y, last_y[idx], i)
local iw = math.max(w, math.ceil(math.abs(ix - lx)))
renderer.draw_rect(ix, iy, iw, h, style.caret)
lx = ix
end
core.redraw = true
end
last_view[idx], last_x[idx], last_y[idx] = self, x, y
end
end

View File

@ -1,30 +0,0 @@
local core = require "core"
local command = require "core.command"
local config = require "core.config"
if PLATFORM == "Windows" then
config.filemanager = "explorer"
elseif PLATFORM == "Mac OS X" then
config.filemanager = "open"
else
config.filemanager = "xdg-open"
end
command.add("core.docview", {
["open-file-location:open-file-location"] = function()
local doc = core.active_view.doc
if not doc.filename then
core.error "Cannot open location of unsaved doc"
return
end
local folder = doc.filename:match("^(.*)[/\\].*$") or "."
core.log("Opening \"%s\"", folder)
if PLATFORM == "Windows" then
system.exec(string.format("%s %s", config.filemanager, folder))
else
system.exec(string.format("%s %q", config.filemanager, folder))
end
end
})

View File

@ -1,399 +0,0 @@
-- mod-version:3
local core = require "core"
local common = require "core.common"
local keymap = require "core.keymap"
local command = require "core.command"
local style = require "core.style"
local View = require "core.view"
---@class plugins.projectsearch.resultsview : core.view
local ResultsView = View:extend()
ResultsView.context = "session"
function ResultsView:new(path, text, fn)
ResultsView.super.new(self)
self.scrollable = true
self.brightness = 0
self:begin_search(path, text, fn)
end
function ResultsView:get_name()
return "Search Results"
end
local function find_all_matches_in_file(t, filename, fn)
local fp = io.open(filename)
if not fp then return t end
local n = 1
for line in fp:lines() do
local s = fn(line)
if s then
-- Insert maximum 256 characters. If we insert more, for compiled files, which can have very long lines
-- things tend to get sluggish. If our line is longer than 80 characters, begin to truncate the thing.
local start_index = math.max(s - 80, 1)
table.insert(t, { file = filename, text = (start_index > 1 and "..." or "") .. line:sub(start_index, 256 + start_index), line = n, col = s })
core.redraw = true
end
if n % 100 == 0 then coroutine.yield(0) end
n = n + 1
core.redraw = true
end
fp:close()
end
function ResultsView:begin_search(path, text, fn)
self.search_args = { path, text, fn }
self.results = {}
self.last_file_idx = 1
self.query = text
self.searching = true
self.selected_idx = 0
core.add_thread(function()
local i = 1
for dir_name, file in core.get_project_files() do
if file.type == "file" and (not path or (dir_name .. "/" .. file.filename):find(path, 1, true) == 1) then
local truncated_path = (dir_name == core.project_dir and "" or (dir_name .. PATHSEP))
find_all_matches_in_file(self.results, truncated_path .. file.filename, fn)
end
self.last_file_idx = i
i = i + 1
end
self.searching = false
self.brightness = 100
core.redraw = true
end, self.results)
self.scroll.to.y = 0
end
function ResultsView:refresh()
self:begin_search(table.unpack(self.search_args))
end
function ResultsView:on_mouse_moved(mx, my, ...)
ResultsView.super.on_mouse_moved(self, mx, my, ...)
self.selected_idx = 0
for i, item, x,y,w,h in self:each_visible_result() do
if mx >= x and my >= y and mx < x + w and my < y + h then
self.selected_idx = i
break
end
end
end
function ResultsView:on_mouse_pressed(...)
local caught = ResultsView.super.on_mouse_pressed(self, ...)
if not caught then
return self:open_selected_result()
end
end
function ResultsView:open_selected_result()
local res = self.results[self.selected_idx]
if not res then
return
end
core.try(function()
local dv = core.root_view:open_doc(core.open_doc(res.file))
core.root_view.root_node:update_layout()
dv.doc:set_selection(res.line, res.col)
dv:scroll_to_line(res.line, false, true)
end)
return true
end
function ResultsView:update()
self:move_towards("brightness", 0, 0.1)
ResultsView.super.update(self)
end
function ResultsView:get_results_yoffset()
return style.font:get_height() + style.padding.y * 3
end
function ResultsView:get_line_height()
return style.padding.y + style.font:get_height()
end
function ResultsView:get_scrollable_size()
return self:get_results_yoffset() + #self.results * self:get_line_height()
end
function ResultsView:get_visible_results_range()
local lh = self:get_line_height()
local oy = self:get_results_yoffset()
local min = math.max(1, math.floor((self.scroll.y - oy) / lh))
return min, min + math.floor(self.size.y / lh) + 1
end
function ResultsView:each_visible_result()
return coroutine.wrap(function()
local lh = self:get_line_height()
local x, y = self:get_content_offset()
local min, max = self:get_visible_results_range()
y = y + self:get_results_yoffset() + lh * (min - 1)
for i = min, max do
local item = self.results[i]
if not item then break end
coroutine.yield(i, item, x, y, self.size.x, lh)
y = y + lh
end
end)
end
function ResultsView:scroll_to_make_selected_visible()
local h = self:get_line_height()
local y = self:get_results_yoffset() + h * (self.selected_idx - 1)
self.scroll.to.y = math.min(self.scroll.to.y, y)
self.scroll.to.y = math.max(self.scroll.to.y, y + h - self.size.y)
end
function ResultsView:draw()
self:draw_background(style.background)
-- status
local ox, oy = self:get_content_offset()
local x, y = ox + style.padding.x, oy + style.padding.y
local files_number = core.project_files_number()
local per = common.clamp(files_number and self.last_file_idx / files_number or 1, 0, 1)
local text
if self.searching then
if files_number then
text = string.format("Searching %.f%% (%d of %d files, %d matches) for %q...",
per * 100, self.last_file_idx, files_number,
#self.results, self.query)
else
text = string.format("Searching (%d files, %d matches) for %q...",
self.last_file_idx, #self.results, self.query)
end
else
text = string.format("Found %d matches for %q",
#self.results, self.query)
end
local color = common.lerp(style.text, style.accent, self.brightness / 100)
renderer.draw_text(style.font, text, x, y, color)
-- horizontal line
local yoffset = self:get_results_yoffset()
local x = ox + style.padding.x
local w = self.size.x - style.padding.x * 2
local h = style.divider_size
local color = common.lerp(style.dim, style.text, self.brightness / 100)
renderer.draw_rect(x, oy + yoffset - style.padding.y, w, h, color)
if self.searching then
renderer.draw_rect(x, oy + yoffset - style.padding.y, w * per, h, style.text)
end
-- results
local y1, y2 = self.position.y, self.position.y + self.size.y
for i, item, x,y,w,h in self:each_visible_result() do
local color = style.text
if i == self.selected_idx then
color = style.accent
renderer.draw_rect(x, y, w, h, style.line_highlight)
end
x = x + style.padding.x
local text = string.format("%s at line %d (col %d): ", item.file, item.line, item.col)
x = common.draw_text(style.font, style.dim, text, "left", x, y, w, h)
x = common.draw_text(style.code_font, color, item.text, "left", x, y, w, h)
end
self:draw_scrollbar()
end
---@param path string
---@param text string
---@param fn fun(line_text:string):...
---@return plugins.projectsearch.resultsview?
local function begin_search(path, text, fn)
if text == "" then
core.error("Expected non-empty string")
return
end
local rv = ResultsView(path, text, fn)
core.root_view:get_active_node_default():add_view(rv)
return rv
end
local function get_selected_text()
local view = core.active_view
local doc = (view and view.doc) and view.doc or nil
if doc then
return doc:get_text(table.unpack({ doc:get_selection() }))
end
end
local function normalize_path(path)
if not path then return nil end
path = common.normalize_path(path)
for i, project_dir in ipairs(core.project_directories) do
if common.path_belongs_to(path, project_dir.name) then
return project_dir.item.filename .. PATHSEP .. common.relative_path(project_dir.name, path)
end
end
return path
end
---@class plugins.projectsearch
local projectsearch = {}
---@type plugins.projectsearch.resultsview
projectsearch.ResultsView = ResultsView
---@param text string
---@param path string
---@param insensitive? boolean
---@return plugins.projectsearch.resultsview?
function projectsearch.search_plain(text, path, insensitive)
if insensitive then text = text:lower() end
return begin_search(path, text, function(line_text)
if insensitive then
return line_text:lower():find(text, nil, true)
else
return line_text:find(text, nil, true)
end
end)
end
---@param text string
---@param path string
---@param insensitive? boolean
---@return plugins.projectsearch.resultsview?
function projectsearch.search_regex(text, path, insensitive)
local re, errmsg
if insensitive then
re, errmsg = regex.compile(text, "i")
else
re, errmsg = regex.compile(text)
end
if not re then core.log("%s", errmsg) return end
return begin_search(path, text, function(line_text)
return regex.cmatch(re, line_text)
end)
end
---@param text string
---@param path string
---@param insensitive? boolean
---@return plugins.projectsearch.resultsview?
function projectsearch.search_fuzzy(text, path, insensitive)
if insensitive then text = text:lower() end
return begin_search(path, text, function(line_text)
if insensitive then
return common.fuzzy_match(line_text:lower(), text) and 1
else
return common.fuzzy_match(line_text, text) and 1
end
end)
end
command.add(nil, {
["project-search:find"] = function(path)
core.command_view:enter("Find Text In " .. (normalize_path(path) or "Project"), {
text = get_selected_text(),
select_text = true,
submit = function(text)
projectsearch.search_plain(text, path, true)
end
})
end,
["project-search:find-regex"] = function(path)
core.command_view:enter("Find Regex In " .. (normalize_path(path) or "Project"), {
submit = function(text)
projectsearch.search_regex(text, path, true)
end
})
end,
["project-search:fuzzy-find"] = function(path)
core.command_view:enter("Fuzzy Find Text In " .. (normalize_path(path) or "Project"), {
text = get_selected_text(),
select_text = true,
submit = function(text)
projectsearch.search_fuzzy(text, path, true)
end
})
end,
})
command.add(ResultsView, {
["project-search:select-previous"] = function()
local view = core.active_view
view.selected_idx = math.max(view.selected_idx - 1, 1)
view:scroll_to_make_selected_visible()
end,
["project-search:select-next"] = function()
local view = core.active_view
view.selected_idx = math.min(view.selected_idx + 1, #view.results)
view:scroll_to_make_selected_visible()
end,
["project-search:open-selected"] = function()
core.active_view:open_selected_result()
end,
["project-search:refresh"] = function()
core.active_view:refresh()
end,
["project-search:move-to-previous-page"] = function()
local view = core.active_view
view.scroll.to.y = view.scroll.to.y - view.size.y
end,
["project-search:move-to-next-page"] = function()
local view = core.active_view
view.scroll.to.y = view.scroll.to.y + view.size.y
end,
["project-search:move-to-start-of-doc"] = function()
local view = core.active_view
view.scroll.to.y = 0
end,
["project-search:move-to-end-of-doc"] = function()
local view = core.active_view
view.scroll.to.y = view:get_scrollable_size()
end
})
keymap.add {
["f5"] = "project-search:refresh",
["ctrl+shift+f"] = "project-search:find",
["up"] = "project-search:select-previous",
["down"] = "project-search:select-next",
["return"] = "project-search:open-selected",
["pageup"] = "project-search:move-to-previous-page",
["pagedown"] = "project-search:move-to-next-page",
["ctrl+home"] = "project-search:move-to-start-of-doc",
["ctrl+end"] = "project-search:move-to-end-of-doc",
["home"] = "project-search:move-to-start-of-doc",
["end"] = "project-search:move-to-end-of-doc"
}
return projectsearch

View File

@ -1,31 +0,0 @@
-- mod-version:3
local core = require "core"
local command = require "core.command"
local keymap = require "core.keymap"
local escapes = {
["\\"] = "\\\\",
["\""] = "\\\"",
["\n"] = "\\n",
["\r"] = "\\r",
["\t"] = "\\t",
["\b"] = "\\b",
}
local function replace(chr)
return escapes[chr] or string.format("\\x%02x", chr:byte())
end
command.add("core.docview", {
["quote:quote"] = function(dv)
dv.doc:replace(function(text)
return '"' .. text:gsub("[\0-\31\\\"]", replace) .. '"'
end)
end,
})
keymap.add {
["ctrl+'"] = "quote:quote",
}

View File

@ -1,58 +0,0 @@
local tokenizer = require "core.tokenizer"
local style = require "core.style"
local common = require "core.common"
local tokenize = tokenizer.tokenize
local closers = {
["("] = ")",
["["] = "]",
["{"] = "}"
}
local function parenstyle(parenstack)
return "paren" .. ((#parenstack % 5) + 1)
end
function tokenizer.tokenize(syntax, text, state)
state = state or {}
local res, istate = tokenize(syntax, text, state.istate)
local parenstack = state.parenstack or ""
local newres = {}
-- split parens out
-- the stock tokenizer can't do this because it merges identical adjacent tokens
for i, type, text in tokenizer.each_token(res) do
if type == "normal" or type == "symbol" then
for normtext1, paren, normtext2 in text:gmatch("([^%(%[{}%]%)]*)([%(%[{}%]%)]?)([^%(%[{}%]%)]*)") do
if #normtext1 > 0 then
table.insert(newres, type)
table.insert(newres, normtext1)
end
if #paren > 0 then
if paren == parenstack:sub(-1) then -- expected closer
parenstack = parenstack:sub(1, -2)
table.insert(newres, parenstyle(parenstack))
elseif closers[paren] then -- opener
table.insert(newres, parenstyle(parenstack))
parenstack = parenstack .. closers[paren]
else -- unexpected closer
table.insert(newres, "paren_unbalanced")
end
table.insert(newres, paren)
end
if #normtext2 > 0 then
table.insert(newres, type)
table.insert(newres, normtext2)
end
end
else
table.insert(newres, type)
table.insert(newres, text)
end
end
return newres, { parenstack = parenstack, istate = istate }
end
style.syntax.paren_unbalanced = style.syntax.paren_unbalanced or { common.color "#DC0408" }
style.syntax.paren1 = style.syntax.paren1 or { common.color "#FC6F71"}
style.syntax.paren2 = style.syntax.paren2 or { common.color "#fcb053"}
style.syntax.paren3 = style.syntax.paren3 or { common.color "#fcd476"}
style.syntax.paren4 = style.syntax.paren4 or { common.color "#52dab2"}
style.syntax.paren5 = style.syntax.paren5 or { common.color "#5a98cf"}

View File

@ -1,63 +0,0 @@
local core = require "core"
local config = require "core.config"
local command = require "core.command"
local keymap = require "core.keymap"
local function wordwrap_text(text, limit)
local t = {}
local n = 0
for word in text:gmatch("%S+") do
if n + #word > limit then
table.insert(t, "\n")
n = 0
elseif #t > 0 then
table.insert(t, " ")
end
table.insert(t, word)
n = n + #word + 1
end
return table.concat(t)
end
command.add("core.docview", {
["reflow:reflow"] = function()
local doc = core.active_view.doc
doc:replace(function(text)
local prefix_set = "[^%w\n%[%](){}`'\"]*"
-- get line prefix and trailing whitespace
local prefix1 = text:match("^\n*" .. prefix_set)
local prefix2 = text:match("\n(" .. prefix_set .. ")", #prefix1+1)
local trailing = text:match("%s*$")
if not prefix2 or prefix2 == "" then
prefix2 = prefix1
end
-- strip all line prefixes and trailing whitespace
text = text:sub(#prefix1+1, -#trailing - 1):gsub("\n" .. prefix_set, "\n")
-- split into blocks, wordwrap and join
local line_limit = config.line_limit - #prefix1
local blocks = {}
text = text:gsub("\n\n", "\0")
for block in text:gmatch("%Z+") do
table.insert(blocks, wordwrap_text(block, line_limit))
end
text = table.concat(blocks, "\n\n")
-- add prefix to start of lines
text = prefix1 .. text:gsub("\n", "\n" .. prefix2) .. trailing
return text
end)
end,
})
keymap.add {
["ctrl+shift+q"] = "reflow:reflow"
}

View File

@ -1,110 +0,0 @@
local core = require "core"
local common = require "core.common"
local command = require "core.command"
local config = require "core.config"
local keymap = require "core.keymap"
local style = require "core.style"
local RootView = require "core.rootview"
local CommandView = require "core.commandview"
config.scale_mode = "code"
config.scale_use_mousewheel = true
local font_cache = setmetatable({}, { __mode = "k" })
-- the following should be kept in sync with core.style's default font settings
font_cache[style.font] = { DATADIR .. "/data/fonts/font.ttf", 14 * SCALE }
font_cache[style.big_font] = { DATADIR .. "/data/fonts/font.ttf", 34 * SCALE }
font_cache[style.icon_font] = { DATADIR .. "/data/fonts/icons.ttf", 14 * SCALE }
font_cache[style.code_font] = { DATADIR .. "/data/fonts/monospace.ttf", 13.5 * SCALE }
local load_font = renderer.font.load
function renderer.font.load(...)
local res = load_font(...)
font_cache[res] = { ... }
return res
end
local function scale_font(font, s)
local fc = font_cache[font]
return renderer.font.load(fc[1], fc[2] * s)
end
local current_scale = SCALE
local default = current_scale
local function get_scale() return current_scale end
local function set_scale(scale)
scale = common.clamp(scale, 0.2, 6)
-- save scroll positions
local scrolls = {}
for _, view in ipairs(core.root_view.root_node:get_children()) do
local n = view:get_scrollable_size()
if n ~= math.huge and not view:is(CommandView) then
scrolls[view] = view.scroll.y / (n - view.size.y)
end
end
local s = scale / current_scale
current_scale = scale
if config.scale_mode == "ui" then
SCALE = current_scale
style.padding.x = style.padding.x * s
style.padding.y = style.padding.y * s
style.divider_size = style.divider_size * s
style.scrollbar_size = style.scrollbar_size * s
style.caret_width = style.caret_width * s
style.tab_width = style.tab_width * s
style.big_font = scale_font(style.big_font, s)
style.icon_font = scale_font(style.icon_font, s)
style.font = scale_font(style.font, s)
end
style.code_font = scale_font(style.code_font, s)
-- restore scroll positions
for view, n in pairs(scrolls) do
view.scroll.y = n * (view:get_scrollable_size() - view.size.y)
view.scroll.to.y = view.scroll.y
end
core.redraw = true
end
local on_mouse_wheel = RootView.on_mouse_wheel
function RootView:on_mouse_wheel(d, ...)
if keymap.modkeys["ctrl"] and config.scale_use_mousewheel then
if d < 0 then command.perform "scale:decrease" end
if d > 0 then command.perform "scale:increase" end
else
return on_mouse_wheel(self, d, ...)
end
end
command.add(nil, {
["scale:reset" ] = function() set_scale(default) end,
["scale:decrease"] = function() set_scale(current_scale * 0.9) end,
["scale:increase"] = function() set_scale(current_scale * 1.1) end,
})
keymap.add {
["ctrl+0"] = "scale:reset",
["ctrl+-"] = "scale:decrease",
["ctrl++"] = "scale:increase",
}
return { get_scale = get_scale, set_scale = set_scale }

View File

@ -1,40 +0,0 @@
--[[
scalestatus.lua
displays current scale (zoom) in status view
version: 20200628_155804
originally by SwissalpS
Depends on plugin scale.lua version >= 20200628_154010
--]]
local scale = require "plugins.scale"
-- make sure plugin is installed and has get_scale field
if not scale.get_scale then
local core = require "core"
core.error("Plugin 'scale' needs to be updated, scalestatus inactive.")
return false
end
local config = require "core.config"
local StatusView = require "core.statusview"
config.scalestatus_format = '%.0f%%'
local get_items = StatusView.get_items
function StatusView:get_items()
local left, right = get_items(self)
local t = {
self.separator,
string.format(config.scalestatus_format, scale.get_scale() * 100),
}
for _, item in ipairs(t) do
table.insert(right, item)
end
return left, right
end
return true

View File

@ -1,37 +0,0 @@
local style = require "core.style"
local DocView = require "core.docview"
-- originally written by luveti
local function draw_box(x, y, w, h, color)
local r = renderer.draw_rect
local s = math.ceil(SCALE)
r(x, y, w, s, color)
r(x, y + h - s, w, s, color)
r(x, y + s, s, h - s * 2, color)
r(x + w - s, y + s, s, h - s * 2, color)
end
local draw_line_body = DocView.draw_line_body
function DocView:draw_line_body(idx, x, y)
local line1, col1, line2, col2 = self.doc:get_selection(true)
if line1 == line2 and col1 ~= col2 then
local lh = self:get_line_height()
local selected_text = self.doc.lines[line1]:sub(col1, col2 - 1)
local current_line_text = self.doc.lines[idx]
local last_col = 1
while true do
local start_col, end_col = current_line_text:find(selected_text, last_col, true)
if start_col == nil then break end
local x1 = x + self:get_col_x_offset(idx, start_col)
local x2 = x + self:get_col_x_offset(idx, end_col + 1)
local color = style.selectionhighlight or style.syntax.comment
draw_box(x1, y, x2 - x1, lh, color)
last_col = end_col + 1
end
end
draw_line_body(self, idx, x, y)
end

View File

@ -1,30 +0,0 @@
-- mod-version:2 -- lite-xl 2.0
local core = require "core"
local command = require "core.command"
local translate = require "core.doc.translate"
local function split_lines(text)
local res = {}
for line in (text .. "\n"):gmatch("(.-)\n") do
table.insert(res, line)
end
return res
end
command.add("core.docview", {
["sort:sort"] = function()
local doc = core.active_view.doc
local l1, c1, l2, c2, swap = doc:get_selection(true)
l1, c1 = translate.start_of_line(doc, l1, c1)
l2, c2 = translate.end_of_line(doc, l2, c2)
doc:set_selection(l1, c1, l2, c2, swap)
doc:replace(function(text)
local head, body, foot = text:match("(\n*)(.-)(\n*)$")
local lines = split_lines(body)
table.sort(lines, function(a, b) return a:lower() < b:lower() end)
return head .. table.concat(lines, "\n") .. foot
end)
end,
})

View File

@ -1,63 +0,0 @@
-- mod-version:3
local core = require "core"
local command = require "core.command"
local translate = require "core.doc.translate"
local function gmatch_to_array(text, ptn)
local res = {}
for x in text:gmatch(ptn) do
table.insert(res, x)
end
return res
end
local function tabularize_lines(lines, delim)
local rows = {}
local cols = {}
-- split lines at delimiters and get maximum width of columns
local ptn = "[^" .. delim:sub(1,1):gsub("%W", "%%%1") .. "]+"
for i, line in ipairs(lines) do
rows[i] = gmatch_to_array(line, ptn)
for j, col in ipairs(rows[i]) do
cols[j] = math.max(#col, cols[j] or 0)
end
end
-- pad columns with space
for _, row in ipairs(rows) do
for i = 1, #row - 1 do
row[i] = row[i] .. string.rep(" ", cols[i] - #row[i])
end
end
-- write columns back to lines array
for i, line in ipairs(lines) do
lines[i] = table.concat(rows[i], delim)
end
end
command.add("core.docview", {
["tabularize:tabularize"] = function(dv)
core.command_view:enter("Tabularize On Delimiter", {
submit = function(delim)
if delim == "" then delim = " " end
local doc = dv.doc
local line1, col1, line2, col2, swap = doc:get_selection(true)
line1, col1 = doc:position_offset(line1, col1, translate.start_of_line)
line2, col2 = doc:position_offset(line2, col2, translate.end_of_line)
doc:set_selection(line1, col1, line2, col2, swap)
doc:replace(function(text)
local lines = gmatch_to_array(text, "[^\n]*\n?")
tabularize_lines(lines, delim)
return table.concat(lines)
end)
end
})
end,
})

View File

@ -1,389 +0,0 @@
local core = require "core"
local common = require "core.common"
local command = require "core.command"
local config = require "core.config"
local keymap = require "core.keymap"
local style = require "core.style"
local View = require "core.view"
local TodoTreeView = View:extend()
config.todo_tags = { --"TODO", "BUG", "FIX", "FIXME", "IMPROVEMENT",
"@todo", "@fixme", "@testme", "@leak" } --< @r-lyeh
-- Paths or files to be ignored
config.todo_ignore_paths = {
"tools/tcc", --< @r-lyeh
"tools\\tcc", --< @r-lyeh
"engine/fwk", --< @r-lyeh
"engine\\fwk", --< @r-lyeh
"engine/joint", --< @r-lyeh
"engine\\joint", --< @r-lyeh
}
-- 'tag' mode can be used to group the todos by tags
-- 'file' mode can be used to group the todos by files
config.todo_mode = "tag"
-- Tells if the plugin should start with the nodes expanded. default: true for tag mode
config.todo_expanded = config.todo_mode == "tag"
-- list of allowed extensions: items must start and end with a dot character
config.todo_allowed_extensions = '.h.c.m.hh.cc.hpp.cpp.cxx.lua.py.cs.vs.fs.bat.' --< @r-lyeh
-- whether the sidebar treeview is initially visible or not
config.todo_visible = false
function TodoTreeView:new()
TodoTreeView.super.new(self)
self.scrollable = true
self.focusable = false
self.visible = config.todo_visible
self.times_cache = {}
self.cache = {}
self.cache_updated = false
self.init_size = true
-- Items are generated from cache according to the mode
self.items = {}
end
local function is_file_ignored(filename)
for _, path in ipairs(config.todo_ignore_paths) do
local s, _ = filename:find(path)
if s then
return true
end
end
return false
end
function TodoTreeView:refresh_cache()
local items = {}
if not next(self.items) then
items = self.items
end
self.updating_cache = true
core.add_thread(function()
for _, item in ipairs(core.project_files) do
local ignored = is_file_ignored(item.filename)
if not ignored and item.type == "file" then
local cached = self:get_cached(item)
if config.todo_mode == "file" then
items[cached.filename] = cached
else
for _, todo in ipairs(cached.todos) do
local tag = todo.tag
if not items[tag] then
local t = {}
t.expanded = config.todo_expanded
t.type = "group"
t.todos = {}
t.tag = tag
items[tag] = t
end
table.insert(items[tag].todos, todo)
end
end
end
end
-- Copy expanded from old items
if config.todo_mode == "tag" and next(self.items) then
for tag, data in pairs(self.items) do
if items[tag] then
items[tag].expanded = data.expanded
end
end
end
self.items = items
core.redraw = true
self.cache_updated = true
self.updating_cache = false
end, self)
end
local function find_file_todos(t, filename)
--< @r-lyeh
local ext = (filename:match "[^.]+$") .. '.'
if not string.find(config.todo_allowed_extensions,ext) then
return
end
--<
local fp = io.open(filename)
if not fp then return t end
--< @r-lyeh: optimized loops: early exit if quicksearch fails
local function lines(str)
local result = {}
for line in string.gmatch(str, "(.-)%c") do -- line in str:gmatch '[^\n]+' do
-- Add spaces at the start and end of line so the pattern will pick
-- tags at the start and at the end of lines
table.insert(result, " "..line.." ")
end
return result
end
local before = #t
local content = fp:read("*all")
for _, todo_tag in ipairs(config.todo_tags) do
if string.find(content, todo_tag) then
local n = 0
for _, line in ipairs(lines(content)) do
n = n + 1
local match_str = todo_tag[1] == '@' and todo_tag or "[^a-zA-Z_\"'`]"..todo_tag.."[^a-zA-Z_\"'`]+"
local s, e = line:find(match_str)
if s then
local d = {}
d.tag = string.sub(string.upper(todo_tag), todo_tag:byte(1) == 64 and 2 or 1) .. 's'
d.filename = filename
d.text = line:sub(e+1)
if d.text == "" then
d.text = config.todo_mode == "tag" and filename:match("^.+[/\\](.+)$") or "blank"
end
d.line = n
d.col = s
table.insert(t, d)
end
end
end
end
fp:close()
if #t ~= before then
coroutine.yield()
core.redraw = true
end
--<
end
function TodoTreeView:get_cached(item)
local t = self.cache[item.filename]
if not t then
t = {}
t.expanded = config.todo_expanded
t.filename = item.filename
t.abs_filename = system.absolute_path(item.filename)
t.type = item.type
t.todos = {}
find_file_todos(t.todos, t.filename)
self.cache[t.filename] = t
end
return t
end
function TodoTreeView:get_name()
return "Todo Tree"
end
function TodoTreeView:get_item_height()
return style.font:get_height() + style.padding.y
end
function TodoTreeView:get_cached_time(doc)
local t = self.times_cache[doc]
if not t then
local info = system.get_file_info(doc.filename)
if not info then return nil end
self.times_cache[doc] = info.modified
end
return t
end
function TodoTreeView:check_cache()
for _, doc in ipairs(core.docs) do
if doc.filename then
local info = system.get_file_info(doc.filename)
local cached = self:get_cached_time(doc)
if not info and cached then
-- document deleted
self.times_cache[doc] = nil
self.cache[doc.filename] = nil
self.cache_updated = false
elseif cached and cached ~= info.modified then
-- document modified
self.times_cache[doc] = info.modified
self.cache[doc.filename] = nil
self.cache_updated = false
end
end
end
if core.project_files ~= self.last_project_files then
self.last_project_files = core.project_files
self.cache_updated = false
end
end
function TodoTreeView:each_item()
self:check_cache()
if not self.updating_cache and not self.cache_updated then
self:refresh_cache()
end
return coroutine.wrap(function()
local ox, oy = self:get_content_offset()
local y = oy + style.padding.y
local w = self.size.x
local h = self:get_item_height()
for _, item in pairs(self.items) do
if #item.todos > 0 then
coroutine.yield(item, ox, y, w, h)
y = y + h
for _, todo in ipairs(item.todos) do
if item.expanded then
coroutine.yield(todo, ox, y, w, h)
y = y + h
end
end
end
end
end)
end
function TodoTreeView:on_mouse_moved(px, py)
self.hovered_item = nil
for item, x,y,w,h in self:each_item() do
if px > x and py > y and px <= x + w and py <= y + h then
self.hovered_item = item
break
end
end
end
function TodoTreeView:on_mouse_pressed(button, x, y)
if not self.hovered_item then
return
elseif self.hovered_item.type == "file"
or self.hovered_item.type == "group" then
self.hovered_item.expanded = not self.hovered_item.expanded
else
core.try(function()
local i = self.hovered_item
local dv = core.root_view:open_doc(core.open_doc(i.filename))
core.root_view.root_node:update_layout()
dv.doc:set_selection(i.line, i.col)
dv:scroll_to_line(i.line, false, true)
end)
end
end
function TodoTreeView:update()
self.scroll.to.y = math.max(0, self.scroll.to.y)
-- update width
local dest = self.visible and config.treeview_size or 0
if self.init_size then
self.size.x = dest
self.init_size = false
else
self:move_towards(self.size, "x", dest)
end
TodoTreeView.super.update(self)
end
function TodoTreeView:draw()
self:draw_background(style.background2)
--local h = self:get_item_height()
local icon_width = style.icon_font:get_width("D")
local spacing = style.font:get_width(" ") * 2
local root_depth = 0
for item, x,y,w,h in self:each_item() do
local color = style.text
-- hovered item background
if item == self.hovered_item then
renderer.draw_rect(x, y, w, h, style.line_highlight)
color = style.accent
end
-- icons
local item_depth = 0
x = x + (item_depth - root_depth) * style.padding.x + style.padding.x
if item.type == "file" then
local icon1 = item.expanded and "-" or "+"
common.draw_text(style.icon_font, color, icon1, nil, x, y, 0, h)
x = x + style.padding.x
common.draw_text(style.icon_font, color, "f", nil, x, y, 0, h)
x = x + icon_width
elseif item.type == "group" then
local icon1 = item.expanded and "-" or "+"
common.draw_text(style.icon_font, color, icon1, nil, x, y, 0, h)
x = x + icon_width / 2
else
if config.todo_mode == "tag" then
x = x + style.padding.x
else
x = x + style.padding.x * 1.5
end
common.draw_text(style.icon_font, color, "i", nil, x, y, 0, h)
x = x + icon_width
end
-- text
x = x + spacing
if item.type == "file" then
common.draw_text(style.font, color, item.filename, nil, x, y, 0, h)
elseif item.type == "group" then
common.draw_text(style.font, color, item.tag, nil, x, y, 0, h)
else
if config.todo_mode == "file" then
common.draw_text(style.font, color, item.tag.." - "..item.text, nil, x, y, 0, h)
else
common.draw_text(style.font, color, item.text, nil, x, y, 0, h)
end
end
end
end
-- init
local view = TodoTreeView()
local node = core.root_view:get_active_node()
view.size.x = config.treeview_size
node:split("right", view, true)
-- register commands and keymap
command.add(nil, {
["todotreeview:toggle"] = function()
view.visible = not view.visible
end,
["todotreeview:expand-items"] = function()
for _, item in pairs(view.items) do
item.expanded = true
end
end,
["todotreeview:hide-items"] = function()
for _, item in pairs(view.items) do
item.expanded = false
end
end,
})
keymap.add { ["ctrl+shift+t"] = "todotreeview:toggle" }
keymap.add { ["ctrl+shift+e"] = "todotreeview:expand-items" }
keymap.add { ["ctrl+shift+h"] = "todotreeview:hide-items" }

View File

@ -1,294 +0,0 @@
local core = require "core"
local common = require "core.common"
local command = require "core.command"
local config = require "core.config"
local keymap = require "core.keymap"
local style = require "core.style"
local View = require "core.view"
config.treeview_size = 200 * SCALE
local function get_depth(filename)
local n = 0
for sep in filename:gmatch("[\\/]") do
n = n + 1
end
return n
end
local TreeView = View:extend()
function TreeView:new()
TreeView.super.new(self)
self.scrollable = true
self.visible = false --< @r-lyeh true>false
self.init_size = true
self.cache = {}
end
function TreeView:get_cached(item)
local t = self.cache[item.filename]
if not t then
t = {}
t.filename = item.filename
t.abs_filename = system.absolute_path(item.filename)
t.name = t.filename:match("[^\\/]+$")
t.depth = get_depth(t.filename)
t.type = item.type
self.cache[t.filename] = t
end
return t
end
function TreeView:get_name()
return "Project"
end
function TreeView:get_item_height()
return style.font:get_height() + style.padding.y
end
function TreeView:check_cache()
-- invalidate cache's skip values if project_files has changed
if core.project_files ~= self.last_project_files then
for _, v in pairs(self.cache) do
v.skip = nil
end
self.last_project_files = core.project_files
end
end
function TreeView:each_item()
return coroutine.wrap(function()
self:check_cache()
local ox, oy = self:get_content_offset()
local y = oy + style.padding.y
local w = self.size.x
local h = self:get_item_height()
local i = 1
while i <= #core.project_files do
local item = core.project_files[i]
local cached = self:get_cached(item)
coroutine.yield(cached, ox, y, w, h)
y = y + h
i = i + 1
if not cached.expanded then
if cached.skip then
i = cached.skip
else
local depth = cached.depth
while i <= #core.project_files do
local filename = core.project_files[i].filename
if get_depth(filename) <= depth then break end
i = i + 1
end
cached.skip = i
end
end
end
end)
end
function TreeView:on_mouse_moved(px, py)
self.hovered_item = nil
for item, x,y,w,h in self:each_item() do
if px > x and py > y and px <= x + w and py <= y + h then
self.hovered_item = item
break
end
end
end
function TreeView:on_mouse_pressed(button, x, y)
if not self.hovered_item then
return
elseif self.hovered_item.type == "dir" then
self.hovered_item.expanded = not self.hovered_item.expanded
else
core.try(function()
core.root_view:open_doc(core.open_doc(self.hovered_item.filename))
end)
end
end
function TreeView:update()
-- update width
local dest = self.visible and config.treeview_size or 0
if self.init_size then
self.size.x = dest
self.init_size = false
else
self:move_towards(self.size, "x", dest)
end
TreeView.super.update(self)
end
function TreeView:draw()
self:draw_background(style.background2)
local icon_width = style.icon_font:get_width("D")
local spacing = style.font:get_width(" ") * 2
local doc = core.active_view.doc
local active_filename = doc and system.absolute_path(doc.filename or "")
for item, x,y,w,h in self:each_item() do
local color = style.text
-- highlight active_view doc
if item.abs_filename == active_filename then
color = style.accent
end
-- hovered item background
if item == self.hovered_item then
renderer.draw_rect(x, y, w, h, style.line_highlight)
color = style.accent
end
-- icons
x = x + item.depth * style.padding.x + style.padding.x
if item.type == "dir" then
local icon1 = item.expanded and "-" or "+"
local icon2 = item.expanded and "D" or "d"
common.draw_text(style.icon_font, color, icon1, nil, x, y, 0, h)
x = x + style.padding.x
common.draw_text(style.icon_font, color, icon2, nil, x, y, 0, h)
x = x + icon_width
else
x = x + style.padding.x
common.draw_text(style.icon_font, color, "f", nil, x, y, 0, h)
x = x + icon_width
end
-- text
x = x + spacing
x = common.draw_text(style.font, color, item.name, nil, x, y, 0, h)
end
end
-- init
local view = TreeView()
local node = core.root_view:get_active_node()
node:split("left", view, true)
-- register commands and keymap
command.add(nil, {
["treeview:toggle"] = function()
view.visible = not view.visible
end,
})
keymap.add { ["ctrl+t"] = "treeview:toggle" } --< @r-lyeh ctrl+// > ctrl+t
-- register some context menu items, if available
local has_menu, menu = core.try(require, "plugins.contextmenu")
local has_fsutils, fsutils = core.try(require, "plugins.fsutils")
if has_menu and has_fsutils then
local function new_file_f(path)
command.perform "core:new-doc"
end
local function new_file()
new_file_f(view.hovered_item.abs_filename)
end
local function new_dir_f(path)
core.command_view:enter("New directory name", function(dir)
fsutils.mkdir(dir)
end)
core.command_view:set_text(path .. PATHSEP .. "New folder")
end
local function new_dir()
new_dir_f(view.hovered_item.abs_filename)
end
local function delete_f(path)
core.add_thread(function()
local function wrap()
return coroutine.wrap(function() fsutils.delete(path, true) end)
end
for n in wrap() do
if n % 100 == 0 then
core.log("Deleted %d items.", n)
coroutine.yield(0)
end
end
core.log("%q deleted.", path)
end)
end
local function delete()
local path = view.hovered_item.abs_filename
if view.hovered_item.type == "dir"
and system.show_confirm_dialog("Delete confirmation", string.format("Do you really want to delete %q ?", path)) then
delete_f(path)
else
delete_f(path)
end
end
local function dirname(path)
local p = fsutils.split(path)
table.remove(p)
return table.concat(p, PATHSEP)
end
local function rename()
local oldname = view.hovered_item.abs_filename
core.command_view:enter("Rename to", function(newname)
fsutils.move(oldname, newname)
core.log("Moved %q to %q", oldname, newname)
end, common.path_suggest)
core.command_view:set_text(dirname(oldname))
end
local function copy_path()
system.set_clipboard(view.hovered_item.abs_filename)
end
menu:register(function() return view.hovered_item and view.hovered_item.type == "dir" end, {
{ text = "New file", command = new_file },
{ text = "New folder", command = new_dir },
menu.DIVIDER,
{ text = "Rename", command = rename },
{ text = "Delete", command = delete },
menu.DIVIDER,
{ text = "Copy directory name", command = copy_path }
})
menu:register(function() return view.hovered_item and view.hovered_item.type == "file" end, {
{ text = "Rename", command = rename },
{ text = "Delete", command = delete },
menu.DIVIDER,
{ text = "Copy filename", command = copy_path }
})
-- general region of the treeview
menu:register(function(x, y)
local x1, y1, x2, y2 = view:get_content_bounds()
return not view.hovered_item and x > x1 and x <= x2 and y > y1 and y <= y2
end, {
{ text = "New file", command = function() new_file_f(system.absolute_path('.')) end },
{ text = "New folder", command = function() new_dir_f(system.absolute_path('.')) end }
})
end
return view --< @r-lyeh

View File

@ -1,36 +0,0 @@
local core = require "core"
local command = require "core.command"
local Doc = require "core.doc"
local function trim_trailing_whitespace(doc)
local cline, ccol = doc:get_selection()
for i = 1, #doc.lines do
local old_text = doc:get_text(i, 1, i, math.huge)
local new_text = old_text:gsub("%s*$", "")
-- don't remove whitespace which would cause the caret to reposition
if cline == i and ccol > #new_text then
new_text = old_text:sub(1, ccol - 1)
end
if old_text ~= new_text then
doc:insert(i, 1, new_text)
doc:remove(i, #new_text + 1, i, math.huge)
end
end
end
command.add("core.docview", {
["trim-whitespace:trim-trailing-whitespace"] = function()
trim_trailing_whitespace(core.active_view.doc)
end,
})
local save = Doc.save
Doc.save = function(self, ...)
trim_trailing_whitespace(self)
save(self, ...)
end

View File

@ -1,179 +0,0 @@
local core = require "core"
local DocView = require "core.docview"
local workspace_filename = ".lite_workspace.lua"
local function serialize(val)
if type(val) == "string" then
return string.format("%q", val)
elseif type(val) == "table" then
local t = {}
for k, v in pairs(val) do
table.insert(t, "[" .. serialize(k) .. "]=" .. serialize(v))
end
return "{" .. table.concat(t, ",") .. "}"
end
return tostring(val)
end
local function has_no_locked_children(node)
if node.locked then return false end
if node.type == "leaf" then return true end
return has_no_locked_children(node.a) and has_no_locked_children(node.b)
end
local function get_unlocked_root(node)
if node.type == "leaf" then
return not node.locked and node
end
if has_no_locked_children(node) then
return node
end
return get_unlocked_root(node.a) or get_unlocked_root(node.b)
end
local function save_view(view)
local mt = getmetatable(view)
if mt == DocView then
return {
type = "doc",
active = (core.active_view == view),
filename = view.doc.filename,
selection = { view.doc:get_selection() },
scroll = { x = view.scroll.to.x, y = view.scroll.to.y },
text = not view.doc.filename and view.doc:get_text(1, 1, math.huge, math.huge)
}
end
for name, mod in pairs(package.loaded) do
if mod == mt then
return {
type = "view",
active = (core.active_view == view),
module = name
}
end
end
end
local function load_view(t)
if t.type == "doc" then
local ok, doc = pcall(core.open_doc, t.filename)
if not ok then
return DocView(core.open_doc())
end
local dv = DocView(doc)
if t.text then doc:insert(1, 1, t.text) end
doc:set_selection(table.unpack(t.selection))
dv.last_line, dv.last_col = doc:get_selection()
dv.scroll.x, dv.scroll.to.x = t.scroll.x, t.scroll.x
dv.scroll.y, dv.scroll.to.y = t.scroll.y, t.scroll.y
return dv
end
return require(t.module)()
end
local function save_node(node)
local res = {}
res.type = node.type
if node.type == "leaf" then
res.views = {}
for _, view in ipairs(node.views) do
local t = save_view(view)
if t then
table.insert(res.views, t)
if node.active_view == view then
res.active_view = #res.views
end
end
end
else
res.divider = node.divider
res.a = save_node(node.a)
res.b = save_node(node.b)
end
return res
end
local function load_node(node, t)
if t.type == "leaf" then
local res
for _, v in ipairs(t.views) do
local view = load_view(v)
if v.active then res = view end
node:add_view(view)
end
if t.active_view then
node:set_active_view(node.views[t.active_view])
end
return res
else
node:split(t.type == "hsplit" and "right" or "down")
node.divider = t.divider
local res1 = load_node(node.a, t.a)
local res2 = load_node(node.b, t.b)
return res1 or res2
end
end
local function save_workspace()
local root = get_unlocked_root(core.root_view.root_node)
local fp = io.open(workspace_filename, "w")
if fp then
fp:write("return ", serialize(save_node(root)), "\n")
fp:close()
end
end
local function load_workspace()
local ok, t = pcall(dofile, workspace_filename)
os.remove(workspace_filename)
if ok then
local root = get_unlocked_root(core.root_view.root_node)
local active_view = load_node(root, t)
if active_view then
core.set_active_view(active_view)
end
end
end
local run = core.run
function core.run(...)
if #core.docs == 0 then
core.try(load_workspace)
local exit = os.exit
function os.exit(...)
save_workspace()
exit(...)
end
end
core.run = run
return core.run(...)
end
local run1 = core.run1
function core.run1(...)
if #core.docs == 0 then
core.try(load_workspace)
local exit = os.exit
function os.exit(...)
save_workspace()
exit(...)
end
end
core.run1 = run1
return core.run1(...)
end

1265
srgb.patch 100644

File diff suppressed because it is too large Load Diff

0
tools/PVRTexToolCLI.osx 100755 → 100644
View File

0
tools/ass2iqe.osx 100755 → 100644
View File

0
tools/cook.osx 100755 → 100644
View File

0
tools/cuttlefish.osx 100755 → 100644
View File

0
tools/ffmpeg.osx 100755 → 100644
View File

0
tools/furnace.osx 100755 → 100644
View File

0
tools/iqe2iqm.osx 100755 → 100644
View File

0
tools/mid2wav.osx 100755 → 100644
View File

0
tools/mod2wav.osx 100755 → 100644
View File

0
tools/ninja.osx 100755 → 100644
View File

0
tools/premake5.osx 100755 → 100644
View File

View File

@ -1,714 +0,0 @@
//Definitions of default DIALOG and CONTROL classes for the dialog editor.
//This is a text file to enable simple customization and the addition of custom controls
[DIALOG]
//default values for dialogs...
width=300
height=150
fontname=Arial
fontsize=9
style=DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
language=LANG_ENGLISH, SUBLANG_ENGLISH_US
//style flags and MASK values
sf=DS_ABSALIGN
sf=DS_SYSMODAL
sf=DS_LOCALEDIT
sf=DS_SETFONT
sf=DS_MODALFRAME
sf=DS_NOIDLEMSG
sf=DS_SETFOREGROUND
sf=DS_FIXEDSYS
sf=DS_NOFAILCREATE
sf=DS_CONTROL
sf=DS_CENTER
sf=DS_CENTERMOUSE
sf=DS_CONTEXTHELP
sf=WS_CHILD, (WS_POPUP | WS_CHILD) //ie: either WS_POPUP or WS_CHILD but not both!
sf=WS_POPUP, (WS_CHILD | WS_POPUP)
sf=WS_CLIPSIBLINGS
sf=WS_CLIPCHILDREN
sf=WS_DISABLED
sf=WS_VISIBLE
sf=WS_CAPTION
sf=WS_BORDER, WS_CAPTION
sf=WS_DLGFRAME, WS_CAPTION
sf=WS_MINIMIZEBOX
sf=WS_MAXIMIZEBOX
sf=WS_SYSMENU
sf=WS_THICKFRAME
sf=WS_TILEDWINDOW
sf=WS_POPUPWINDOW
sf=WS_MINIMIZE
sf=WS_MAXIMIZE
sf=WS_VSCROLL
sf=WS_HSCROLL
//exstyle flags and MASK values
esf=WS_EX_DLGMODALFRAME
esf=WS_EX_NOPARENTNOTIFY
esf=WS_EX_TOPMOST
esf=WS_EX_ACCEPTFILES
esf=WS_EX_TRANSPARENT
esf=WS_EX_MDICHILD
esf=WS_EX_TOOLWINDOW
esf=WS_EX_WINDOWEDGE
esf=WS_EX_CLIENTEDGE
esf=WS_EX_CONTEXTHELP
esf=WS_EX_RIGHT
esf=WS_EX_LEFT, WS_EX_RIGHT
esf=WS_EX_RTLREADING
esf=WS_EX_LTRREADING, WS_EX_RTLREADING
esf=WS_EX_LEFTSCROLLBAR
esf=WS_EX_RIGHTSCROLLBAR, WS_EX_LEFTSCROLLBAR
esf=WS_EX_CONTROLPARENT
esf=WS_EX_STATICEDGE
esf=WS_EX_APPWINDOW
esf=WS_EX_OVERLAPPEDWINDOW
esf=WS_EX_PALETTEWINDOW
esf=WS_EX_LAYERED
esf=WS_EX_NOINHERITLAYOUT
esf=WS_EX_LAYOUTRTL
esf=WS_EX_NOACTIVATE
[BUTTON]
//default values ...
width=60
height=14
style= WS_CHILD | WS_VISIBLE | WS_TABSTOP
//style flags and MASK values
sf=BS_PUSHBUTTON, 0x1F
sf=BS_DEFPUSHBUTTON, 0x1F
sf=BS_CHECKBOX, 0x1F
sf=BS_AUTOCHECKBOX, 0x1F
sf=BS_3STATE, 0x1F
sf=BS_AUTO3STATE, 0x1F
sf=BS_RADIOBUTTON, 0x1F
sf=BS_AUTORADIOBUTTON, 0x1F
sf=BS_GROUPBOX, 0x1F
sf=BS_USERBUTTON, 0x1F
sf=BS_OWNERDRAW, 0x1F
sf=BS_SPLITBUTTON, 0x1F
sf=BS_DEFSPLITBUTTON, 0x1F
sf=BS_COMMANDLINK, 0x1F
sf=BS_DEFCOMMANDLINK, 0x1F
sf=BS_LEFTTEXT
sf=BS_ICON
sf=BS_BITMAP
sf=BS_LEFT, BS_CENTER
sf=BS_RIGHT, BS_CENTER
sf=BS_CENTER, BS_CENTER
sf=BS_TOP, BS_VCENTER
sf=BS_BOTTOM, BS_VCENTER
sf=BS_VCENTER, BS_VCENTER
sf=BS_PUSHLIKE
sf=BS_MULTILINE
sf=BS_NOTIFY
sf=BS_FLAT
[CHECKBOX]
//default values ...
width=60
height=14
style= BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP
classname=BUTTON
//style flags and MASK values
sf=BS_CHECKBOX, 0x1F
sf=BS_AUTOCHECKBOX, 0x1F
sf=BS_3STATE, 0x1F
sf=BS_AUTO3STATE, 0x1F
sf=BS_LEFTTEXT
sf=BS_LEFT, BS_CENTER
sf=BS_RIGHT, BS_CENTER
sf=BS_CENTER, BS_CENTER
sf=BS_TOP, BS_VCENTER
sf=BS_BOTTOM, BS_VCENTER
sf=BS_VCENTER, BS_VCENTER
sf=BS_PUSHLIKE
sf=BS_MULTILINE
sf=BS_NOTIFY
sf=BS_FLAT
[RADIOBUTTON]
//default values ...
width=60
height=14
style= BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP
classname=BUTTON
//style flags and MASK values
sf=BS_RADIOBUTTON, 0x1F
sf=BS_AUTORADIOBUTTON, 0x1F
sf=BS_LEFTTEXT
sf=BS_LEFT, BS_CENTER
sf=BS_RIGHT, BS_CENTER
sf=BS_CENTER, BS_CENTER
sf=BS_TOP, BS_VCENTER
sf=BS_BOTTOM, BS_VCENTER
sf=BS_VCENTER, BS_VCENTER
sf=BS_PUSHLIKE
sf=BS_MULTILINE
sf=BS_NOTIFY
sf=BS_FLAT
[GROUPBOX]
//default values ...
width=60
height=60
style= BS_GROUPBOX | WS_CHILD | WS_VISIBLE
classname=BUTTON
//style flags and MASK values
sf=BS_GROUPBOX, 0x1F
sf=BS_LEFT, BS_CENTER
sf=BS_RIGHT, BS_CENTER
sf=BS_CENTER, BS_CENTER
sf=BS_NOTIFY
sf=BS_FLAT
[COMBOBOX]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWN
//style flags and MASK values
sf=CBS_SIMPLE, CBS_DROPDOWNLIST
sf=CBS_DROPDOWN, CBS_DROPDOWNLIST
sf=CBS_DROPDOWNLIST, CBS_DROPDOWNLIST
sf=CBS_OWNERDRAWFIXED
sf=CBS_OWNERDRAWVARIABLE
sf=CBS_AUTOHSCROLL
sf=CBS_OEMCONVERT
sf=CBS_SORT
sf=CBS_HASSTRINGS
sf=CBS_NOINTEGRALHEIGHT
sf=CBS_DISABLENOSCROLL
sf=CBS_UPPERCASE
sf=CBS_LOWERCASE
[EDIT]
//default values ...
width=60
height=14
style= WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP
//style flags and MASK values
sf=ES_LEFT, (ES_CENTER | ES_RIGHT)
sf=ES_CENTER, (ES_CENTER | ES_RIGHT)
sf=ES_RIGHT, (ES_CENTER | ES_RIGHT)
sf=ES_MULTILINE
sf=ES_UPPERCASE
sf=ES_LOWERCASE
sf=ES_PASSWORD
sf=ES_AUTOVSCROLL
sf=ES_AUTOHSCROLL
sf=ES_NOHIDESEL
sf=ES_OEMCONVERT
sf=ES_READONLY
sf=ES_WANTRETURN
sf=ES_NUMBER
[MEMO]
//default values ...
width=60
height=60
classname=EDIT
style= ES_MULTILINE | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | WS_HSCROLL | WS_VSCROLL
//style flags and MASK values
sf=ES_LEFT, (ES_CENTER | ES_RIGHT)
sf=ES_CENTER, (ES_CENTER | ES_RIGHT)
sf=ES_RIGHT, (ES_CENTER | ES_RIGHT)
sf=ES_MULTILINE
sf=ES_UPPERCASE
sf=ES_LOWERCASE
sf=ES_PASSWORD
sf=ES_AUTOVSCROLL
sf=ES_AUTOHSCROLL
sf=ES_NOHIDESEL
sf=ES_OEMCONVERT
sf=ES_READONLY
sf=ES_WANTRETURN
sf=ES_NUMBER
[LISTBOX]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_STANDARD
//LBS_STANDARD = (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
//style flags
sf=LBS_NOTIFY
sf=LBS_SORT
sf=LBS_NOREDRAW
sf=LBS_MULTIPLESEL
sf=LBS_OWNERDRAWFIXED
sf=LBS_OWNERDRAWVARIABLE
sf=LBS_HASSTRINGS
sf=LBS_USETABSTOPS
sf=LBS_NOINTEGRALHEIGHT
sf=LBS_MULTICOLUMN
sf=LBS_WANTKEYBOARDINPUT
sf=LBS_EXTENDEDSEL
sf=LBS_DISABLENOSCROLL
sf=LBS_NODATA
sf=LBS_NOSEL
[SCROLLBAR]
//default values ...
width=30
height=14
style= WS_CHILD | WS_VISIBLE
//style flags and MASK values
sf=SBS_HORZ, SBS_VERT
sf=SBS_VERT, SBS_VERT
sf=SBS_TOPALIGN
sf=SBS_LEFTALIGN
sf=SBS_BOTTOMALIGN
sf=SBS_RIGHTALIGN
sf=SBS_SIZEBOXTOPLEFTALIGN
sf=SBS_SIZEBOXBOTTOMRIGHTALIGN
sf=SBS_SIZEBOX
sf=SBS_SIZEGRIP
[STATIC]
//default values ...
width=32
height=32
style= WS_CHILD | WS_VISIBLE | WS_GROUP
//style flags and MASK values
sf=SS_LEFT, 0x1F
sf=SS_CENTER, 0x1F
sf=SS_RIGHT, 0x1F
sf=SS_ICON, 0x1F
sf=SS_BLACKRECT, 0x1F
sf=SS_GRAYRECT, 0x1F
sf=SS_WHITERECT, 0x1F
sf=SS_BLACKFRAME, 0x1F
sf=SS_GRAYFRAME, 0x1F
sf=SS_WHITEFRAME, 0x1F
sf=SS_USERITEM, 0x1F
sf=SS_SIMPLE, 0x1F
sf=SS_LEFTNOWORDWRAP, 0x1F
sf=SS_BITMAP, 0x1F
sf=SS_OWNERDRAW, 0x1F
sf=SS_ENHMETAFILE, 0x1F
sf=SS_ETCHEDHORZ, 0x1F
sf=SS_ETCHEDVERT, 0x1F
sf=SS_ETCHEDFRAME, 0x1F
sf=SS_NOPREFIX
sf=SS_NOTIFY
sf=SS_CENTERIMAGE
sf=SS_RIGHTJUST
sf=SS_REALSIZEIMAGE
sf=SS_SUNKEN
sf=SS_ENDELLIPSIS, SS_ELLIPSISMASK
sf=SS_PATHELLIPSIS, SS_ELLIPSISMASK
sf=SS_WORDELLIPSIS, SS_ELLIPSISMASK
[LTEXT]
//default values ...
width=60
height=18
classname=STATIC
style= WS_CHILD | WS_VISIBLE | WS_GROUP
//style flags
sf=SS_NOPREFIX
sf=SS_NOTIFY
sf=SS_CENTERIMAGE
sf=SS_RIGHTJUST
sf=SS_SUNKEN
[ICON]
//default values ...
width=20
height=20
classname=STATIC
style= WS_CHILD | WS_VISIBLE | WS_GROUP | SS_ICON
//style flags
sf=SS_ICON, 0x1F
sf=SS_NOPREFIX
sf=SS_NOTIFY
sf=SS_CENTERIMAGE
sf=SS_RIGHTJUST
sf=SS_REALSIZEIMAGE
sf=SS_SUNKEN
[BITMAP]
//default values ...
width=60
height=60
classname=STATIC
style= WS_CHILD | WS_VISIBLE | WS_GROUP | SS_BITMAP
//style flags
sf=SS_BITMAP, 0x1F
sf=SS_NOPREFIX
sf=SS_NOTIFY
sf=SS_CENTERIMAGE
sf=SS_RIGHTJUST
sf=SS_REALSIZEIMAGE
sf=SS_SUNKEN
["RICHEDIT"]
//default values ...
width=60
height=60
style= ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
//style flags and MASK values
sf=ES_LEFT, (ES_CENTER | ES_RIGHT)
sf=ES_CENTER, (ES_CENTER | ES_RIGHT)
sf=ES_RIGHT, (ES_CENTER | ES_RIGHT)
sf=ES_MULTILINE
sf=ES_AUTOVSCROLL
sf=ES_AUTOHSCROLL
sf=ES_NOHIDESEL
sf=ES_READONLY
sf=ES_WANTRETURN
sf=ES_PASSWORD
sf=ES_SAVESEL
sf=ES_SUNKEN
sf=ES_DISABLENOSCROLL
sf=ES_SELECTIONBAR
sf=ES_NOOLEDRAGDROP
sf=ES_VERTICAL
sf=ES_NOIME
sf=ES_SELFIME
esf=ES_EX_NOCALLOLEINIT
["SysAnimate32"]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE
sf=ACS_CENTER
sf=ACS_TRANSPARENT
sf=ACS_AUTOPLAY
sf=ACS_TIMER
["SysDateTimePick32"]
//default values ...
width=80
height=14
style= WS_CHILD | WS_VISIBLE
sf=DTS_UPDOWN
sf=DTS_SHOWNONE
sf=DTS_SHORTDATEFORMAT, DTS_LONGDATEFORMAT
sf=DTS_LONGDATEFORMAT, DTS_LONGDATEFORMAT
sf=DTS_TIMEFORMAT //nb: must be DTS_UPDOWN (not calendar) with DTS_TIMEFORMAT
sf=DTS_APPCANPARSE
sf=DTS_RIGHTALIGN
["SysHeader32"]
//default values ...
width=60
height=12
style= WS_CHILD | WS_VISIBLE
//style flags and MASK values
sf=HDS_BUTTONS
sf=HDS_HOTTRACK
sf=HDS_HIDDEN
sf=HDS_DRAGDROP
sf=HDS_FULLDRAG
sf=CCS_TOP, CCS_BOTTOM
sf=CCS_NOMOVEY, CCS_BOTTOM
sf=CCS_BOTTOM, CCS_BOTTOM
sf=CCS_NORESIZE
sf=CCS_NOPARENTALIGN
sf=CCS_ADJUSTABLE
sf=CCS_NODIVIDER
sf=CCS_VERT
sf=CCS_LEFT
sf=CCS_RIGHT
sf=CCS_NOMOVEX
["SysListView32"]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP
//style flags and MASK values
sf=LVS_ICON, LVS_TYPEMASK
sf=LVS_REPORT, LVS_TYPEMASK
sf=LVS_SMALLICON, LVS_TYPEMASK
sf=LVS_LIST, LVS_TYPEMASK
sf=LVS_SINGLESEL
sf=LVS_SHOWSELALWAYS
sf=LVS_SORTASCENDING
sf=LVS_SORTDESCENDING
sf=LVS_SHAREIMAGELISTS
sf=LVS_NOLABELWRAP
sf=LVS_AUTOARRANGE
sf=LVS_EDITLABELS
sf=LVS_OWNERDATA
sf=LVS_NOSCROLL
sf=LVS_ALIGNTOP, LVS_ALIGNLEFT
sf=LVS_ALIGNLEFT, LVS_ALIGNLEFT
sf=LVS_OWNERDRAWFIXED
sf=LVS_NOCOLUMNHEADER
sf=LVS_NOSORTHEADER
esf=LVS_EX_GRIDLINES
esf=LVS_EX_SUBITEMIMAGES
esf=LVS_EX_CHECKBOXES
esf=LVS_EX_TRACKSELECT
esf=LVS_EX_HEADERDRAGDROP
esf=LVS_EX_FULLROWSELECT
esf=LVS_EX_ONECLICKACTIVATE
esf=LVS_EX_TWOCLICKACTIVATE
["SysMonthCal32"]
//default values ...
width=130
height=100
style= WS_CHILD | WS_VISIBLE
sf=MCS_DAYSTATE
sf=MCS_MULTISELECT
sf=MCS_WEEKNUMBERS
sf=MCS_NOTODAY
["SysPager"]
//default values ...
width=60
height=20
style= WS_CHILD | WS_VISIBLE
//style flags and MASK values
sf=PGS_VERT, PGS_HORZ
sf=PGS_HORZ, PGS_HORZ
sf=PGS_AUTOSCROLL
sf=PGS_DRAGNDROP
["SysTabControl32"]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | TCS_RAGGEDRIGHT
sf=TCS_SCROLLOPPOSITE
sf=TCS_BOTTOM
sf=TCS_RIGHT
sf=TCS_FORCEICONLEFT
sf=TCS_FORCELABELLEFT
sf=TCS_HOTTRACK
sf=TCS_VERTICAL
sf=TCS_TABS, TCS_BUTTONS
sf=TCS_BUTTONS, TCS_BUTTONS
sf=TCS_SINGLELINE, TCS_MULTILINE
sf=TCS_MULTILINE, TCS_MULTILINE
sf=TCS_RIGHTJUSTIFY, TCS_FIXEDWIDTH
sf=TCS_FIXEDWIDTH, TCS_FIXEDWIDTH
sf=TCS_RAGGEDRIGHT
sf=TCS_FOCUSONBUTTONDOWN
sf=TCS_OWNERDRAWFIXED
sf=TCS_TOOLTIPS
sf=TCS_FOCUSNEVER
esf=TCS_EX_FLATSEPARATORS
esf=TCS_EX_REGISTERDROP
["SysTreeView32"]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP
//style flags
sf=TVS_HASBUTTONS
sf=TVS_HASLINES
sf=TVS_LINESATROOT
sf=TVS_EDITLABELS
sf=TVS_DISABLEDRAGDROP
sf=TVS_SHOWSELALWAYS
esf=TVS_EX_MULTISELECT
esf=TVS_EX_DOUBLEBUFFER
esf=TVS_EX_NOINDENTSTATE
esf=TVS_EX_RICHTOOLTIP
esf=TVS_EX_AUTOHSCROLL
esf=TVS_EX_FADEINOUTEXPANDOS
esf=TVS_EX_PARTIALCHECKBOXES
esf=TVS_EX_EXCLUSIONCHECKBOXES
esf=TVS_EX_DIMMEDCHECKBOXES
esf=TVS_EX_DRAWIMAGEASYNC
["msctls_hotkey32"]
//default values ...
width=60
height=14
style= WS_CHILD | WS_VISIBLE
["msctls_progress32"]
//default values ...
width=60
height=12
style= WS_CHILD | WS_VISIBLE
sf=PBS_SMOOTH
sf=PBS_VERTICAL
["msctls_statusbar32"]
//default values ...
width=60
height=12
style= WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP
sf=SBARS_SIZEGRIP
sf=SBT_TOOLTIPS
sf=CCS_TOP, CCS_BOTTOM
sf=CCS_NOMOVEY, CCS_BOTTOM
sf=CCS_BOTTOM, CCS_BOTTOM
sf=CCS_NORESIZE
sf=CCS_NOPARENTALIGN
sf=CCS_ADJUSTABLE
sf=CCS_NODIVIDER
sf=CCS_VERT
sf=CCS_LEFT
sf=CCS_RIGHT
sf=CCS_NOMOVEX
["msctls_trackbar32"]
//default values ...
width=60
height=18
style= WS_CHILD | WS_VISIBLE | WS_TABSTOP
//style flags and MASK values
sf=TBS_HORZ, TBS_VERT
sf=TBS_VERT, TBS_VERT
sf=TBS_AUTOTICKS
sf=TBS_BOTTOM, TBS_TOP
sf=TBS_TOP, TBS_TOP
sf=TBS_RIGHT, TBS_LEFT
sf=TBS_LEFT, TBS_LEFT
sf=TBS_BOTH
sf=TBS_NOTICKS
sf=TBS_ENABLESELRANGE
sf=TBS_FIXEDLENGTH
sf=TBS_NOTHUMB
["msctls_updown32"]
//default values ...
width=12
height=20
style= WS_CHILD | WS_VISIBLE
//style flags
sf=UDS_WRAP
sf=UDS_SETBUDDYINT
sf=UDS_ALIGNRIGHT
sf=UDS_ALIGNLEFT
sf=UDS_AUTOBUDDY
sf=UDS_ARROWKEYS
sf=UDS_HORZ
sf=UDS_NOTHOUSANDS
["ComboBoxEx32"]
//default values ...
width=60
height=60
style= WS_CHILD | WS_VISIBLE | WS_TABSTOP
//style flags and MASK values
sf=CBS_SIMPLE, CBS_DROPDOWNLIST
sf=CBS_DROPDOWN, CBS_DROPDOWNLIST
sf=CBS_DROPDOWNLIST, CBS_DROPDOWNLIST
sf=CBS_AUTOHSCROLL
sf=CBS_OEMCONVERT
sf=CBS_SORT
sf=CBS_HASSTRINGS
sf=CBS_NOINTEGRALHEIGHT
sf=CBS_DISABLENOSCROLL
sf=CBS_UPPERCASE
sf=CBS_LOWERCASE
esf=CBES_EX_CASESENSITIVE
esf=CBES_EX_NOEDITIMAGE
esf=CBES_EX_NOEDITIMAGEINDENT
esf=CBES_EX_NOSIZELIMIT
esf=CBES_EX_PATHWORDBREAKPROC
["ReBarWindow32"]
//default values ...
width=60
height=12
style= WS_CHILD | WS_VISIBLE
//style flags
sf=RBS_TOOLTIPS
sf=RBS_VARHEIGHT
sf=RBS_BANDBORDERS
sf=RBS_FIXEDORDER
sf=RBS_REGISTERDROP
sf=RBS_AUTOSIZE
sf=RBS_VERTICALGRIPPER
sf=RBS_DBLCLKTOGGLE
sf=CCS_TOP, CCS_BOTTOM
sf=CCS_NOMOVEY, CCS_BOTTOM
sf=CCS_BOTTOM, CCS_BOTTOM
sf=CCS_NORESIZE
sf=CCS_NOPARENTALIGN
sf=CCS_ADJUSTABLE
sf=CCS_NODIVIDER
sf=CCS_VERT
sf=CCS_LEFT
sf=CCS_RIGHT
sf=CCS_NOMOVEX
["ToolbarWindow32"]
//default values ...
width=60
height=12
style= WS_CHILD | WS_VISIBLE
//style flags and MASK value
sf=TBSTYLE_TOOLTIPS
sf=TBSTYLE_WRAPABLE
sf=TBSTYLE_ALTDRAG
sf=TBSTYLE_FLAT
sf=TBSTYLE_LIST
sf=TBSTYLE_CUSTOMERASE
sf=TBSTYLE_REGISTERDROP
sf=TBSTYLE_TRANSPARENT
sf=CCS_TOP, CCS_BOTTOM
sf=CCS_NOMOVEY, CCS_BOTTOM
sf=CCS_BOTTOM, CCS_BOTTOM
sf=CCS_NORESIZE
sf=CCS_NOPARENTALIGN
sf=CCS_ADJUSTABLE
sf=CCS_NODIVIDER
sf=CCS_VERT
sf=CCS_LEFT
sf=CCS_RIGHT
sf=CCS_NOMOVEX
esf=TBSTYLE_EX_DRAWDDARROWS
//esf=TBSTYLE_EX_HIDECLIPPEDBUTTONS
//esf=TBSTYLE_EX_MIXEDBUTTONS
["RichEdit20W"]
//default values ...
width=60
height=60
style= ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
//style flags and MASK values
sf=ES_LEFT, (ES_CENTER | ES_RIGHT)
sf=ES_CENTER, (ES_CENTER | ES_RIGHT)
sf=ES_RIGHT, (ES_CENTER | ES_RIGHT)
sf=ES_MULTILINE
sf=ES_AUTOVSCROLL
sf=ES_AUTOHSCROLL
sf=ES_NOHIDESEL
sf=ES_READONLY
sf=ES_WANTRETURN
sf=ES_PASSWORD
sf=ES_SAVESEL
sf=ES_SUNKEN
sf=ES_DISABLENOSCROLL
sf=ES_SELECTIONBAR
sf=ES_NOOLEDRAGDROP
sf=ES_VERTICAL
sf=ES_NOIME
sf=ES_SELFIME
esf=ES_EX_NOCALLOLEINIT
["SysLink"]
//default values ...
width=60
height=18
classname="SysLink"
style= WS_CHILD | WS_VISIBLE | WS_GROUP
["SysIPAddress32"]
//default values ...
width=60
height=14
classname="SysIPAddress32"
style= WS_CHILD | WS_VISIBLE | WS_GROUP

0
tools/sfxr2wav.osx 100755 → 100644
View File

Binary file not shown.

0
tools/xlsx2ini.osx 100755 → 100644
View File