]> git.gir.st - VimFx.git/blob - extension/lib/api.coffee
Fix missing hint markers when re-entering Hints mode quickly
[VimFx.git] / extension / lib / api.coffee
1 ###
2 # Copyright Simon Lydell 2015, 2016.
3 #
4 # This file is part of VimFx.
5 #
6 # VimFx is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # VimFx is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
18 ###
19
20 # This file defines VimFx’s config file API.
21
22 defaults = require('./defaults')
23 prefs = require('./prefs')
24 utils = require('./utils')
25 Vim = require('./vim')
26
27 counter = new utils.Counter({start: 10000, step: 100})
28
29 createConfigAPI = (vimfx) -> {
30 get: (pref) -> switch
31 when pref of defaults.parsed_options
32 vimfx.options[pref]
33 when pref of defaults.all_prefs or pref?.startsWith('custom.')
34 prefs.get(pref)
35 else
36 throw new Error("VimFx: Unknown pref: #{pref}")
37
38 getDefault: (pref) -> switch
39 when pref of defaults.parsed_options or pref?.startsWith('custom.')
40 throw new Error("VimFx: No default for pref: #{pref}")
41 when pref of defaults.all_prefs
42 defaults.all_prefs[pref]
43 else
44 throw new Error("VimFx: Unknown pref: #{pref}")
45
46 set: (pref, value) -> switch
47 when pref of defaults.parsed_options
48 previousValue = vimfx.options[pref]
49 vimfx.options[pref] = value
50 onShutdown(vimfx, -> vimfx.options[pref] = previousValue)
51 when pref of defaults.all_prefs or pref?.startsWith('custom.')
52 previousValue = if prefs.has(pref) then prefs.get(pref) else null
53 prefs.set(pref, value)
54 onShutdown(vimfx, -> prefs.set(pref, previousValue))
55 else
56 throw new Error("VimFx: Unknown pref: #{pref}")
57
58 addCommand: ({name, description, mode, category, order} = {}, fn) ->
59 mode ?= 'normal'
60 category ?= if mode == 'normal' then 'misc' else ''
61 order ?= counter.tick()
62
63 unless typeof name == 'string'
64 throw new Error(
65 "VimFx: A command name as a string is required. Got: #{name}"
66 )
67 unless /^[a-z_]+$/.test(name)
68 throw new Error(
69 "VimFx: Command names should only consist of a-z (lowercase) and
70 underscores. Got: #{name}"
71 )
72 unless typeof description == 'string' and description != ''
73 throw new Error(
74 "VimFx: Commands must have a non-empty description. Got: #{description}"
75 )
76 unless utils.has(vimfx.modes, mode)
77 modes = Object.keys(vimfx.modes).join(', ')
78 throw new Error(
79 "VimFx: Unknown mode. Available modes are: #{modes}. Got: #{mode}"
80 )
81 unless utils.has(vimfx.options.categories, category)
82 categories = Object.keys(vimfx.options.categories).join(', ')
83 throw new Error(
84 "VimFx: Unknown category. Available categories are: #{categories}.
85 Got: #{category}"
86 )
87 unless typeof order == 'number'
88 throw new Error("VimFx: Command order must be a number. Got: #{order}")
89 unless typeof fn == 'function'
90 throw new Error("VimFx: Commands need a function to run. Got: #{fn}")
91
92 pref = "#{defaults.BRANCH}custom.mode.#{mode}.#{name}"
93 prefs.root.default.set(pref, '')
94 vimfx.modes[mode].commands[name] = {
95 pref, category, order, run: fn, description
96 }
97 onShutdown(vimfx, -> delete vimfx.modes[mode].commands[name])
98
99 addOptionOverrides: (rules...) ->
100 unless vimfx.optionOverrides
101 vimfx.optionOverrides = []
102 vimfx.options = new Proxy(vimfx.options, {
103 get: (options, pref) ->
104 location = utils.getCurrentLocation()
105 return options[pref] unless location
106 overrides = getOverrides(vimfx.optionOverrides, location)
107 return overrides?[pref] ? options[pref]
108 })
109 onShutdown(vimfx, -> vimfx.optionOverrides = [])
110 vimfx.optionOverrides.push(rules...)
111
112 addKeyOverrides: (rules...) ->
113 unless vimfx.keyOverrides
114 vimfx.keyOverrides = []
115 vimfx.options.keyValidator = (keyStr, mode) ->
116 location = utils.getCurrentLocation()
117 return true unless location
118 overrides = getOverrides(vimfx.keyOverrides, location, mode)
119 return keyStr not in (overrides ? [])
120 onShutdown(vimfx, -> vimfx.keyOverrides = [])
121 vimfx.keyOverrides.push(rules...)
122
123 send: (vim, message, data = null, callback = null) ->
124 unless vim instanceof Vim
125 throw new Error(
126 "VimFx: The first argument must be a vim object. Got: #{vim}"
127 )
128 unless typeof message == 'string'
129 throw new Error(
130 "VimFx: The second argument must be a message string. Got: #{message}"
131 )
132 if typeof data == 'function'
133 throw new Error(
134 "VimFx: The third argument must not be a function. Got: #{data}"
135 )
136
137 unless typeof callback == 'function' or callback == null
138 throw Error(
139 "VimFx: If provided, `callback` must be a function. Got: #{callback}"
140 )
141 vim._send(message, data, callback, {prefix: 'config:'})
142
143 on: (event, listener) ->
144 vimfx.on(event, listener)
145 onShutdown(vimfx, -> vimfx.off(event, listener))
146
147 off: vimfx.off.bind(vimfx)
148 modes: vimfx.modes
149 }
150
151 getOverrides = (rules, args...) ->
152 for [match, overrides] in rules
153 return overrides if match(args...)
154 return null
155
156 onShutdown = (vimfx, handler) ->
157 fn = ->
158 handler()
159 vimfx.off('shutdown', fn)
160 vimfx.on('shutdown', fn)
161
162 module.exports = createConfigAPI
Imprint / Impressum