]> git.gir.st - VimFx.git/blob - documentation/api.md
Merge pull request #512 from akhodakivskiy/multi-process
[VimFx.git] / documentation / api.md
1 <!--
2 This is part of the VimFx documentation.
3 Copyright Simon Lydell 2015.
4 See the file README.md for copying conditions.
5 -->
6
7 # Public API
8
9 VimFx has a public API. It is intended to be used by:
10
11 - Users who prefer to configure things using text files.
12 - Users who would like to add custom commands.
13 - Users who would like to set [special options].
14 - Users who would like to make site-specific customizations.
15 - Extension authors who would like to extend VimFx.
16
17 VimFx users who use the public API should write a so-called [config file].
18
19
20 ## Getting the API
21
22 ```js
23 let {classes: Cc, interfaces: Ci, utils: Cu} = Components
24 Cu.import('resource://gre/modules/Services.jsm')
25 let apiPref = 'extensions.VimFx.api_url'
26 let apiUrl = Services.prefs.getComplexValue(apiPref, Ci.nsISupportsString).data
27 Cu.import(apiUrl, {}).getAPI(vimfx => {
28
29 // Do things with the `vimfx` object here.
30
31 })
32 ```
33
34 You might also want to take a look at the [config file bootstrap.js
35 example][bootstrap.js].
36
37
38 ## API
39
40 The following sub-sections assume that you store VimFx’s public API in a
41 variable called `vimfx`.
42
43 ### `vimfx.get(pref)` and `vimfx.set(pref, value)`
44
45 Gets or sets the value of the VimFx pref `pref`.
46
47 You can see all prefs in [defaults.coffee], or by opening [about:config] and
48 filtering by `extensions.vimfx`. Note that you can also access the [special
49 options], which may not be accessed in [about:config], using `vimfx.get()` and
50 `vimfx.set()`—in fact, this is the _only_ way of accessing those options.
51
52 #### `vimfx.get(pref)`
53
54 Gets the value of the VimFx pref `pref`.
55
56 ```js
57 // Get the value of the Hint chars option:
58 vimfx.get('hint_chars')
59 // Get all keyboard shortcuts (as a string) for the `f` command:
60 vimfx.get('modes.normal.follow')
61 ```
62
63 #### `vimfx.set(pref, value)`
64
65 Sets the value of the VimFx pref `pref` to `value`.
66
67 ```js
68 // Set the value of the Hint chars option:
69 vimfx.set('hint_chars', 'abcdefghijklmnopqrstuvwxyz')
70 // Add yet a keyboard shortcut for the `f` command:
71 vimfx.set('modes.normal.follow', vimfx.get('modes.normal.follow') + ' e');
72 ```
73
74 ### `vimfx.addCommand(options, fn)`
75
76 Creates a new command.
77
78 **Note:** This should only be used by config file users, not by extension
79 authors who wish to extend VimFx. They should add commands manually to
80 [`vimfx.modes`] instead.
81
82 `options`:
83
84 - name: `String`. The name used when accessing the command via
85 `vimfx.modes[options.mode].commands[options.name]`. It is also used for the
86 pref used to store the shortcuts for the command:
87 `` `custom.mode.${options.mode}.${options.name}` ``.
88 - description: `String`. Shown in the help dialog and VimFx’s settings page in
89 the Add-ons Manager.
90 - mode: `String`. Defaults to `'normal'`. The mode to add the command to. The
91 value has to be one of the keys of [`vimfx.modes`].
92 - category: `String`. Defaults to `'misc'` for Normal mode and `''`
93 (uncategorized) otherwise. The category to add the command to. The
94 value has to be one of the keys of [`vimfx.get('categories')`][categories].
95 - order: `Number`. Defaults to putting the command at the end of the category.
96 The first of the default commands has the order `100` and then they increase
97 by `100` per command. This allows to put new commands between two already
98 existing ones.
99
100 `fn` is called when the command is activated. See the [onInput] documentation
101 below for more information.
102
103 Note that you have to give the new command a shortcut in VimFx’s settings page
104 in the Add-ons Manager or set one using `vimfx.set()` to able to use the new
105 command.
106
107 ```js
108 vimfx.addCommand({
109 name: 'hello',
110 description: 'Log Hello World',
111 }, => {
112 console.log('Hello World!')
113 })
114 // Optional:
115 vimfx.set('custom.mode.normal.hello', 'gö')
116 ```
117
118 ### `vimfx.addOptionOverrides(...rules)` and `vimfx.addKeyOverrides(...rules)`
119
120 These methods take any number of arguments. Each argument is a rule. The rules
121 are added in order. The methods may be run multiple times.
122
123 A rule is an `Array` of length 2:
124
125 1. The first item is a function that returns `true` if the rule should be
126 applied and `false` if not. This is called the matching function.
127 2. The second item is the value that should be used if the rule is applied. This
128 is called the override.
129
130 The rules are tried in the same order they were added. When a matching rule is
131 found it is applied. No more rules will be applied.
132
133 #### `vimfx.addOptionOverrides(...rules)`
134
135 The rules are matched any time the value of a VimFx pref is needed.
136
137 The matching function receives a [location object].
138
139 The override is an object whose keys are VimFx pref names and whose values
140 override the pref in question. The values should be formatted as in an [options
141 object].
142
143 ```js
144 vimfx.addOptionOverrides(
145 [ ({hostname, pathname, hash}) =>
146 `${hostname}${pathname}${hash}` === 'google.com/',
147 {prevent_autofocus: false}
148 ]
149 )
150 ```
151
152 #### `vimfx.addKeyOverrides(...rules)`
153
154 The rules are matched any time you press a key that is not part of the tail of a
155 multi-key shortcut.
156
157 The matching function receives a [location object] as well as the current
158 mode name (one of the keys of [`vimfx.modes`]).
159
160 The override is an array of keys which should not activate VimFx commands but be
161 sent to the page.
162
163 This allows to disable commands on specific sites. To _add_ commands on specific
164 sites, add them globally and then disable them on all _other_ sites.
165
166 ```js
167 vimfx.addKeyOverrides(
168 [ location => location.hostname === 'facebook.com',
169 ['j', 'k']
170 ]
171 )
172 ```
173
174 ### `vimfx.on(eventName, listener)`
175
176 Runs `listener(data)` when `eventName` is fired.
177
178 #### The `load` event
179
180 Occurs when opening a new tab or navigating to a new URL. The data passed to
181 listeners is an object with the following properties:
182
183 - vim: The current [vim object].
184 - location: A [location object].
185
186 This can be used to enter a different mode by default on some pages (which can
187 be used to replace the blacklist option).
188
189 ```js
190 vimfx.on('load', ({vim, location}) => {
191 if (location.hostname === 'example.com') {
192 vim.enterMode('ignore')
193 }
194 })
195 ```
196
197 #### The `modeChange` event
198
199 Occurs whenever the current mode in any tab changes. The initial entering of the
200 default mode in new tabs also counts as a mode change. The data passed to
201 listeners is the current [vim object].
202
203 ```js
204 vimfx.on('modeChange', vim => {
205 let mode = vimfx.modes[vim.mode].name()
206 vim.notify(`Entering mode: ${mode}`)
207 })
208 ```
209
210 ### `vimfx.refresh()`
211
212 If you make changes to [`vimfx.modes`] directly you need to call
213 `vimfx.refresh()` for your changes to take effect.
214
215 ### `vimfx.modes`
216
217 An object whose keys are mode names and whose values are [mode object]s.
218
219 This is a very low-level part of the API. It allows to:
220
221 - Access all commands and run them. This is the only thing that a config file
222 user needs it for.
223
224 ```js
225 let {commands} = vimfx.modes.normal
226 // Inside a custom command:
227 commands.tab_new.run(args)
228 ```
229
230 - Adding new commands. This is intended to be used by extension authors who wish
231 to extend VimFx, not config file users. They should use the
232 `vimfx.addCommand()` helper instead.
233
234 ```js
235 vimfx.modes.normal.commands.new_command = {
236 pref: 'extensions.my_extension.mode.normal.new_command',
237 category: 'misc',
238 order: 10000,
239 description: () => translate('mode.normal.new_command'),
240 run: args => console.log('New command! args:', args)
241 }
242 ```
243
244 - Adding new modes. This is intended to be used by extension authors who wish to
245 extend VimFx, not config file users.
246
247 ```js
248 vimfx.modes.new_mode = {
249 name: () => translate('mode.new_mode'),
250 order: 10000,
251 commands: {},
252 onEnter(args) {},
253 onLeave(args) {},
254 onInput(args, match) {
255 if (match.type === 'full') {
256 match.command.run(args)
257 }
258 return (match.type !== 'none')
259 },
260 }
261 ```
262
263 When you’re done modifying `vimfx.modes` directly, you need to call
264 `vimfx.refresh()`. (That’s taken care of automatically in the
265 `vimfx.addCommand()` helper.)
266
267 Have a look at [modes.coffee] and [commands.coffee] for more information.
268
269 ### `vimfx.get('categories')`
270
271 An object whose keys are category names and whose values are [category object]s.
272
273 ```js
274 let categories = vimfx.get('categories')
275
276 // Add a new category.
277 categories.custom = {
278 name: () => 'Custom commands',
279 order: 10000,
280 }
281
282 // Swap the order of the Location and Tabs categories.
283 ;[categories.location.order, categories.tabs.order] =
284 [categories.tabs.order, categories.location.order]
285 ```
286
287 ### Mode object
288
289 A mode is an object with the follwing properties:
290
291 - name(): `Function`. Returns a human readable name of the mode used in the help
292 dialog and VimFx’s settings page in the Add-ons Manager.
293 - order: `Number`. The first of the default modes has the order `100` and then
294 they increase by `100` per mode. This allows to put new modes between two
295 already existing ones.
296 - commands: `Object`. The keys are command names and the values are [command
297 object]s.
298 - onEnter(data, ...args): `Function`. Called when the mode is entered.
299 - onLeave(data): `Function`. Called when the mode is left.
300 - onInput(data, match): `Function`. Called when a key is pressed.
301
302 #### onEnter, onLeave and onInput
303
304 These methods are called with an object (called `data` above) with the following
305 properties:
306
307 - vim: The current [vim object].
308 - storage: An object unique to the current [vim object] and to the current mode.
309 Allows to share things between commands of the same mode by getting and
310 setting keys on it.
311
312 ##### onEnter
313
314 This method is called with an object as mentioned above, and after that there
315 may be any number of arguments (`args` in `vim.enterMode(modeName, ...args)`)
316 that the mode is free to do whatever it wants with.
317
318 ##### onInput
319
320 The object passed to this method (see above) also has the following properties:
321
322 - isFrameEvent: `Boolean`. `true` if the event occured in web page content,
323 `false` otherwise (if the event occured in the browser UI).
324 - count: `Number`. The count for the command. `undefined` if no count. (This is
325 simply a copy of `match.count`. `match` is defined below.)
326
327 The above object should be passed to commands when running them. The mode is
328 free to do whatever it wants with the return value (if any) of the commands it
329 runs.
330
331 It also receives a [match object] as the second argument.
332
333 `onInput` should return `true` if the current keypress should not be passed on
334 to the browser and web pages, and `false` otherwise.
335
336 ### Category object
337
338 A category is an object with the follwing properties:
339
340 - name(): `Function`. Returns a human readable name of the category used in the
341 help dialog and VimFx’s settings page in the Add-ons Manager. Config file
342 users adding custom categories could simply return a string; extension authors
343 are encouraged to look up the name from a locale file.
344 - order: `Number`. The first of the default categories is the “uncategorized”
345 category. It has the order `100` and then they increase by `100` per category.
346 This allows to put new categories between two already existing ones.
347
348 ### Command object
349
350 A command is an object with the following properties:
351
352 - pref: `String`. The pref used to store the shortcuts for the command.
353 - run(args): `Function`. Called when the command is activated.
354 - description(): `Function`. Returns a description of the command (as a string),
355 shown in the help dialog and VimFx’s settings page in the Add-ons Manager.
356 - category: `String`. The category to add the command to. The value has to be
357 one of the keys of [`vimfx.get('categories')`][categories].
358 - order: `Number`. The first of the default commands has the order `100` and
359 then they increase by `100` per command. This allows to put new commands
360 between two already existing ones.
361
362 ### Match object
363
364 A `match` object has the following properties:
365
366 - type: `String`. It has one of the following values:
367
368 - `'full'`: The current keypress, together with previous keypresses, fully
369 matches a command shortcut.
370 - `'partial'`: The current keypress, together with previous keypresses,
371 partially matches a command shortcut.
372 - `'count'`: The current keypress is not part of a command shortcut, but is a
373 digit and contributes to the count of a future matched command.
374 - `'none'`: The current keypress is not part of a command shortcut and does
375 not contribute to a count.
376
377 - focus: `String` or `null`. The type of currently focused _element_ plus
378 current pressed _key_ combo. You might not want to run commands and suppress
379 the event if this value is anything other than null. It has one of the
380 following values, depending on what kind of _element_ is focused and which
381 _key_ was pressed:
382
383 - `'editable'`: element: a text input or a `contenteditable` element.
384 key: any pressed key.
385 - `'activatable'`: element: an “activatable” element (link or button).
386 key: see the [`activatable_element_keys`] option.
387 - `'adjustable'`: element: an “adjustable” element (form control or video
388 player). key: see the [`adjustable_element_keys`] option.
389 - `'other'`: element: some other kind of element that can receive keystrokes,
390 for example an element in fullscreen mode. key: any pressed key.
391
392 If none of the above criteria is met, the value is `null`, which means that
393 the currently focused element does not appear to respond to keystrokes in any
394 special way.
395
396 - command: `null` unless `type` is `'full'`. Then it is the matched command.
397
398 The matched command should usually be run at this point. It is suitable to
399 pass on the object passed to [onInput] to the command. Some modes might choose
400 to add extra properties to the object first. (That is favored over passing
401 several arguments, since it makes it easier for the command to in turn pass
402 the same data it got on to another command, if needed.)
403
404 Usually the return value of the command isn’t used, but that’s up to the mode.
405
406 - count: `Number`. The count for the command. `undefined` if no count.
407
408 - force: `Boolean`. Indicates if the current key sequence started with
409 `<force>`.
410
411 - keyStr: `String`. The current keypress represented as a string.
412
413 - unmodifiedKey: `String`. `keyStr` without modifiers.
414
415 - toplevel: `Boolean`. Whether or not the match was a toplevel match in the
416 shortcut key tree. This is `true` unless the match is part of the tail of a
417 multi-key shortcut.
418
419 ### Vim object
420
421 There is one `vim` object per tab.
422
423 A `vim` object has the following properties:
424
425 - window: [`Window`]. The current Firefox window object. Most commands
426 interacting with Firefox’s UI use this.
427
428 - browser: [`Browser`]. The `browser` that this vim object handles.
429
430 - options: `Object`. Provides access to all of VimFx’s options. It is an
431 [options object].
432
433 - mode: `String`. The current mode name.
434
435 - enterMode(modeName, ...args): `Function`. Enter mode `modeName`, passing
436 `...args` to the mode. It is up to every mode to do whatever it wants to with
437 `...args`.
438
439 - isBlacklisted(): `Function`. Returns `true` if the current URL is
440 [blacklisted], and `false` otherwise.
441
442 - isFrameEvent(event): `Function`. Returns `true` if `event` occurred in web
443 page content, and `false` otherwise (if it occurred in Firefox’s UI).
444
445 - notify(title, options = {}): `Function`. Display a notification with the title
446 `title` (a `String`). If you need more text than a title, use `options.body`.
447 See [`Notification`] for more information.
448
449 **Warning:** There are also properties starting with an underscore on `vim`
450 objects. They are private, and not supposed to be used outside of VimFx’s own
451 source code. They may change at any time.
452
453 ### Options object
454
455 An `options` object provides access to all of VimFx’s options. It is an object
456 whose keys are VimFx pref names.
457
458 Note that the values are not just simply `vimfx.get(pref)` for the `pref` in
459 question; they are _parsed_ (`parse(vimfx.get(pref))`):
460
461 - Space-separated prefs are parsed into arrays of strings.
462
463 - `black_list` and `{prev,next}_patterns` are parsed into arrays of regular
464 expressions.
465
466 (See [parse-prefs.coffee] for all details.)
467
468 Any [option overrides] are automatically taken into account when getting an
469 option value.
470
471 The [special options] are also available on this object.
472
473
474 ### Location object
475
476 A location object is very similar to [`window.location`] in web pages.
477 Technically, it is a [`URL`] instance. You can experient with the current
478 location object by opening the [web console] and entering `location`.
479
480
481 ## Stability
482
483 The public API is currently **experimental** and therefore **unstable.** Things
484 might break with new VimFx versions.
485
486 As soon as VimFx 1.0.0 is released backwards compatibility will be a priority
487 and won’t be broken until VimFx 2.0.0.
488
489 [option overrides]: #vimfxaddOptionOverridesrules
490 [categories]: #vimfxgetcategories
491 [`vimfx.modes`]: #vimfxmodes
492 [onInput]: #oninput
493 [mode object]: #mode-object
494 [category object]: #category-object
495 [command object]: #command-object
496 [match object]: #match-object
497 [vim object]: #vim-object
498 [options object]: #options-object
499 [location object]: #location-object
500
501 [blacklisted]: options.md#blacklist
502 [special options]: options.md#special-options
503 [config file]: config-file.md
504 [bootstrap.js]: config-file.md#bootstrapjs
505 [`activatable_element_keys`]: options.md#activatable_element_keys
506 [`adjustable_element_keys`]: options.md#adjustable_element_keys
507
508 [defaults.coffee]: ../extension/lib/defaults.coffee
509 [parse-prefs.coffee]: ../extension/lib/parse-prefs.coffee
510 [modes.coffee]: ../extension/lib/modes.coffee
511 [commands.coffee]: ../extension/lib/commands.coffee
512 [vim.coffee]: ../extension/lib/vim.coffee
513
514 [`Window`]: https://developer.mozilla.org/en-US/docs/Web/API/Window
515 [`Browser`]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
516 [`Notification`]: https://developer.mozilla.org/en-US/docs/Web/API/Notification
517 [`window.location`]: https://developer.mozilla.org/en-US/docs/Web/API/Location
518 [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
519 [web console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console
520 [about:config]: http://kb.mozillazine.org/About:config
Imprint / Impressum