aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md5
-rw-r--r--plugins/language_tcl.lua68
-rw-r--r--plugins/minimap.lua299
3 files changed, 371 insertions, 1 deletions
diff --git a/README.md b/README.md
index d6a71c0..37a5b92 100644
--- a/README.md
+++ b/README.md
@@ -81,9 +81,11 @@ Plugin | Description
[`language_ruby`](plugins/language_ruby.lua?raw=1) | Syntax for the [Ruby](https://www.ruby-lang.org/) programming language
[`language sass`](plugins/language_sass.lua?raw=1) | Syntax for the [Sass](https://sass-lang.com/) CSS preprocessor
[`language_sh`](plugins/language_sh.lua?raw=1) | Syntax for shell scripting language
+[`language_tcl`](plugins/language_tcl.lua?raw=1) | Syntax for the [Tcl](https://www.tcl.tk/) programming language
[`language_teal`](plugins/language_teal.lua?raw=1) | Syntax for the [Teal](https://github.com/teal-language/tl) programming language, a typed dialect of Lua.
[`language_ts`](plugins/language_ts.lua?raw=1) | Syntax for the [TypeScript](https://www.typescriptlang.org/) programming language, a typed dialect of JavaScript.
[`language_tex`](plugins/language_tex.lua?raw=1) | Syntax for the [LaTeX](https://www.latex-project.org/) typesetting language
+[`language_tsx`](plugins/language_tsx.lua?raw=1) | Syntax for [TSX](https://www.typescriptlang.org/docs/handbook/jsx.html) language
[`language_v`](plugins/language_v.lua?raw=1) | Syntax for the [V](https://vlang.io/) programming language
[`language_wren`](plugins/language_wren.lua?raw=1) | Syntax for the [Wren](http://wren.io/) programming language
[`language_zig`](plugins/language_zig.lua?raw=1) | Syntax for the [Zig](https://ziglang.org/) programming language
@@ -96,8 +98,9 @@ Plugin | Description
[`macmodkeys`](plugins/macmodkeys.lua?raw=1) | Remaps mac modkeys `command/option` to `ctrl/alt`
[`markers`](plugins/markers.lua?raw=1) | Add markers to docs and jump between them quickly *([screenshot](https://user-images.githubusercontent.com/3920290/82252149-5faaa200-9946-11ea-9199-bea2efb7ee23.png))*
[`memoryusage`](plugins/memoryusage.lua?raw=1) | Show memory usage in the status view
+[`minimap`](plugins/minimap.lua?raw=1) | Shows a minimap on the right-hand side of the docview. Taken from [@andsve](https://github.com/andsve/lite-plugins/tree/minimap-plugin), and improved upon.
[`motiontrail`](plugins/motiontrail.lua?raw=1) | Adds a motion-trail to the caret *([screenshot](https://user-images.githubusercontent.com/3920290/83256814-085ccb00-a1ab-11ea-9e35-e6633cbed1a9.gif))*
-[`nagbar`](https://github.com/takase1121/lite-nagbar)* | consistent and _beautiful_ confirmation dialogs for lite and lite-xl *([gif](https://raw.githubusercontent.com/takase1121/lite-nagbar/master/assets/preview.gif))*
+~~[`nagbar`](https://github.com/takase1121/lite-nagbar)*~~ | integrated in lite-xl ~~consistent and _beautiful_ confirmation dialogs for lite and lite-xl *([gif](https://raw.githubusercontent.com/takase1121/lite-nagbar/master/assets/preview.gif))*~~
[`navigate`](plugins/navigate.lua?raw=1) | Allows moving back and forward between document positions, reducing the amount of scrolling
[`openfilelocation`](plugins/openfilelocation.lua?raw=1) | Opens the parent directory of the current file in the file manager
[`openselected`](plugins/openselected.lua?raw=1) | Opens the selected filename or url
diff --git a/plugins/language_tcl.lua b/plugins/language_tcl.lua
new file mode 100644
index 0000000..31efa84
--- /dev/null
+++ b/plugins/language_tcl.lua
@@ -0,0 +1,68 @@
+-- mod-version:1 -- lite-xl 1.16
+local syntax = require "core.syntax"
+
+syntax.add {
+ files = { "%.tcl$" },
+ comment = "#",
+ patterns = {
+ { pattern = "#.-\n", type = "comment" },
+ { pattern = { '"', '"', '\\' }, type = "string" },
+ { pattern = "0x%x+", type = "number" },
+ { pattern = "%d+[%d%.eE]*f?", type = "number" },
+ { pattern = "%.?%d+f?", type = "number" },
+ { pattern = "%$[%a_][%w_]*", type = "literal" },
+ { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" },
+ { pattern = "::[%a_][%w_]*", type = "function" },
+ { pattern = "[%a_][%w_]*%f[:]", type = "function" },
+ { pattern = "[%a_][%w_]*", type = "symbol" },
+ },
+ symbols = {
+ ["set"] = "keyword",
+ ["unset"] = "keyword",
+ ["rename"] = "keyword",
+ ["upvar"] = "keyword",
+ ["incr"] = "keyword",
+ ["source"] = "keyword",
+ ["expr"] = "keyword",
+ ["gets"] = "keyword",
+ ["puts"] = "keyword",
+ ["package"] = "keyword",
+ ["list"] = "keyword",
+ ["dict"] = "keyword",
+ ["split"] = "join",
+ ["concat"] = "join",
+ ["lappend"] = "keyword",
+ ["lset"] = "keyword",
+ ["lassign"] = "keyword",
+ ["lindex"] = "keyword",
+ ["llength"] = "keyword",
+ ["lsearch"] = "keyword",
+ ["lrange"] = "keyword",
+ ["linsert"] = "keyword",
+ ["lreplace"] = "keyword",
+ ["lrepeat"] = "keyword",
+ ["lsort"] = "keyword",
+ ["lreverse"] = "keyword",
+ ["array"] = "keyword",
+ ["concat"] = "keyword",
+ ["regexp"] = "keyword",
+ ["for"] = "keyword",
+ ["foreach"] = "keyword",
+ ["while"] = "keyword",
+ ["case"] = "keyword",
+ ["proc"] = "keyword",
+ ["if"] = "keyword",
+ ["else"] = "keyword",
+ ["elseif"] = "keyword",
+ ["break"] = "keyword",
+ ["continue"] = "keyword",
+ ["return"] = "keyword",
+ ["eval"] = "keyword",
+ ["try"] = "keyword2",
+ ["on"] = "keyword2",
+ ["finally"] = "keyword2",
+ ["throw"] = "keyword2",
+ ["error"] = "keyword2",
+ },
+}
+
diff --git a/plugins/minimap.lua b/plugins/minimap.lua
new file mode 100644
index 0000000..ecae5eb
--- /dev/null
+++ b/plugins/minimap.lua
@@ -0,0 +1,299 @@
+-- mod-version:1
+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
+
+-- how many spaces one tab is equivalent to
+config.minimap_tab_width = 4
+
+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
+ local batch_syntax_type = nil
+ local function flush_batch(type)
+ local old_color = color
+ color = style.syntax[batch_syntax_type]
+ if config.minimap_syntax_highlight and color ~= nil then
+ -- fetch and dim colors
+ color = {color[1], color[2], color[3], color[4] * 0.5}
+ else
+ color = old_color
+ end
+ if batch_width > 0 then
+ 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
+
+ -- 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
+ batch_syntax_type = nil
+
+ -- 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 char == " " then
+ flush_batch(type)
+ batch_start = batch_start + (char_spacing * config.minimap_tab_width)
+ 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
+ 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
+})