aboutsummaryrefslogtreecommitdiff
path: root/plugins/force_syntax.lua
blob: ae5a138b71582e732ece1015b5c8d703867edd48 (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
-- mod-version:3
local core = require "core"
local Doc = require "core.doc"
local syntax = require "core.syntax"
local command = require "core.command"
local common = require "core.common"
local style = require "core.style"
local StatusView = require "core.statusview"
local DocView = require "core.docview"

local function doc()
  if core.active_view and getmetatable(core.active_view) == DocView then return core.active_view.doc end
  if core.last_active_view and getmetatable(core.last_active_view) == DocView then return core.last_active_view.doc end
end

-- Force plaintext syntax to have a name
local plain_text_syntax = syntax.get("", "")
plain_text_syntax.name = plain_text_syntax.name or "Plain Text"

local doc_reset_syntax = Doc.reset_syntax
function Doc:reset_syntax()
  local syntax_get = syntax.get
  if self.force_syntax then
    syntax.get = function() return self.force_syntax end
  end
  doc_reset_syntax(self)
  syntax.get = syntax_get
end

local function get_syntax_name(s)
  if not s then return "Undefined" end
  local name = s.name
  if not name then
    local exts = type(s.files) == "string" and { s.files } or s.files
    if exts then
      name = table.concat(exts, ", ")
    end
  end
  return name or "Undefined"
end

core.status_view:add_item({
  predicate = function()
    return core.active_view and getmetatable(core.active_view) == DocView
  end,
  name = "doc:syntax",
  alignment = StatusView.Item.RIGHT,
  get_item = function()
    local syntax_name = get_syntax_name(doc().syntax)
    return {
      style.text,
      syntax_name
    }
  end,
  command = "force-syntax:select-file-syntax",
  position = -1,
  tooltip = "file syntax",
  separator = core.status_view.separator2
})

local function get_syntax_list()
  local pt_name = plain_text_syntax.name
  if doc().syntax == plain_text_syntax then
    pt_name = "Current: "..pt_name
  end
  local list = { ["Auto detect"] = false,
                 [pt_name] = plain_text_syntax }
  local keylist = { "Auto detect", pt_name }

  for _,s in pairs(syntax.items) do
    local name = get_syntax_name(s)
    local fullname = name
    local i = 1
    while list[fullname] do
      i = i + 1
      fullname = name.." ("..i..")"
    end
    if doc().syntax == s then
      fullname = "Current: "..fullname
    end
    list[fullname] = s
    table.insert(keylist, fullname)
  end

  return list, keylist
end

local function sorter(a, b)
  -- Compare only syntax name
  a = a:gsub("Current: ", "")
  b = b:gsub("Current: ", "")
  return string.upper(a) < string.upper(b)
end

local function bias_sorter(a, b)
  -- Bias towards Current and Auto detect syntax
  if a:match("Current: ") then return true end
  if b:match("Current: ") then return false end
  if a:match("Auto detect") then return true end
  if b:match("Auto detect") then return false end
  return sorter(a, b)
end

command.add("core.docview", {
  ["force-syntax:select-file-syntax"] =
    function()
      core.command_view:enter("Set syntax for this file", {
        submit = function(text, item)
          local list, _ = get_syntax_list()
          doc().force_syntax = list[item.text]
          doc():reset_syntax()
        end,
        suggest = function(text)
          local _, keylist = get_syntax_list()
          local res = common.fuzzy_match(keylist, text)
          -- Force Current and Auto detect syntax to the bottom
          -- if the text is empty
          table.sort(res, #text == 0 and bias_sorter or sorter)
          return res
        end
      })
    end
})