aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/textadept/bookmarks.lua
blob: 9f2d1c10f44ead23fb4231f621be9a264587b749 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
-- Copyright 2007-2016 Mitchell mitchell.att.foicica.com. See LICENSE.

local M = {}

--[[ This comment is for LuaDoc.
---
-- Bookmarks for Textadept.
-- @field MARK_BOOKMARK (number)
--   The bookmark mark number.
module('textadept.bookmarks')]]

M.MARK_BOOKMARK = _SCINTILLA.next_marker_number()

---
-- Toggles the bookmark on line number *line* or the current line, unless *on*
-- is given.
-- If *on* is `true` or `false`, adds or removes the bookmark, respectively.
-- @param on Optional flag indicating whether to add or remove a bookmark on
--   line *line* or the current line. The default value is `nil`, toggling a
--   bookmark.
-- @param line Optional line number to add or remove a bookmark on.
-- @name toggle
function M.toggle(on, line)
  if not line then line = buffer:line_from_position(buffer.current_pos) end
  local f = on and buffer.marker_add or buffer.marker_delete
  if on == nil then -- toggle
    local bit, marker_mask = 2^M.MARK_BOOKMARK, buffer:marker_get(line)
    if bit32.band(marker_mask, bit) == 0 then f = buffer.marker_add end
  end
  f(buffer, line, M.MARK_BOOKMARK)
end

---
-- Clears all bookmarks in the current buffer.
-- @name clear
function M.clear() buffer:marker_delete_all(M.MARK_BOOKMARK) end

---
-- Prompts the user to select a bookmarked line to move the caret to the
-- beginning of unless *next* is given.
-- If *next* is `true` or `false`, moves the caret to the beginning of the next
-- or previously bookmarked line, respectively.
-- @param next Optional flag indicating whether to go to the next or previous
--   bookmarked line relative to the current line. The default value is `nil`,
--   prompting the user for a bookmarked line to go to.
-- @name goto_mark
function M.goto_mark(next)
  if next == nil then
    local utf8_list, buffers = {}, {}
    -- List the current buffer's marks, and then all other buffers' marks.
    for _, current_buffer_first in ipairs{true, false} do
      for i = 1, #_BUFFERS do
        if current_buffer_first and _BUFFERS[i] == buffer or
           not current_buffer_first and _BUFFERS[i] ~= buffer then
          local buffer = _BUFFERS[i]
          local basename = (buffer.filename or ''):match('[^/\\]+$') or
                           buffer._type or _L['Untitled']
          if buffer.filename then
            basename = basename:iconv('UTF-8', _CHARSET)
          end
          local line = buffer:marker_next(0, 2^M.MARK_BOOKMARK)
          while line >= 0 do
            local mark = string.format('%s:%d: %s', basename, line + 1,
                                       buffer:get_line(line):match('^[^\r\n]*'))
            utf8_list[#utf8_list + 1], buffers[#utf8_list + 1] = mark, i
            line = buffer:marker_next(line + 1, 2^M.MARK_BOOKMARK)
          end
        end
      end
    end
    if #utf8_list == 0 then return end
    local button, mark = ui.dialogs.filteredlist{
      title = _L['Select Bookmark'], columns = _L['Bookmark'], items = utf8_list
    }
    if button ~= 1 or not mark then return end
    view:goto_buffer(buffers[mark])
    textadept.editing.goto_line(utf8_list[mark]:match('^[^:]+:(%d+):') - 1)
  else
    local f = next and buffer.marker_next or buffer.marker_previous
    local current_line = buffer:line_from_position(buffer.current_pos)
    local line = f(buffer, current_line + (next and 1 or -1), 2^M.MARK_BOOKMARK)
    if line == -1 then
      line = f(buffer, (next and 0 or buffer.line_count), 2^M.MARK_BOOKMARK)
    end
    if line >= 0 then textadept.editing.goto_line(line) end
  end
end

return M