]> git.gir.st - VimFx.git/blob - documentation/api.md
Consistently name the help dialog is user-facing code
[VimFx.git] / documentation / api.md
1 <!--
2 This is part of the VimFx documentation.
3 Copyright Simon Lydell 2015, 2016.
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 users who would like to
10 write a so-called [config file].
11
12 Some parts of the API is also intended to be used by authors who would like to
13 extend VimFx.
14
15
16 ## Getting the API
17
18 ```js
19 let {classes: Cc, interfaces: Ci, utils: Cu} = Components
20 Cu.import('resource://gre/modules/Services.jsm')
21 let apiPref = 'extensions.VimFx.api_url'
22 let apiUrl = Services.prefs.getComplexValue(apiPref, Ci.nsISupportsString).data
23 Cu.import(apiUrl, {}).getAPI(vimfx => {
24
25 // Do things with the `vimfx` object here.
26
27 })
28 ```
29
30 You might also want to take a look at the [config file bootstrap.js
31 example][bootstrap.js].
32
33 Note that the callback passed to `getAPI` is called once every time VimFx starts
34 up, not once per Firefox session! This means that if you update VimFx (or
35 disable and then enable it), the callback is re-run with the new version.
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)`, `vimfx.getDefault(pref)` and `vimfx.set(pref, value)`
44
45 Gets or sets the (default) 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('mode.normal.follow')
61 ```
62
63 #### `vimfx.getDefault(pref)`
64
65 Gets the default value of the VimFx pref `pref`.
66
67 Useful when you wish to extend a default, rather than replacing it. See below.
68
69 #### `vimfx.set(pref, value)`
70
71 Sets the value of the VimFx pref `pref` to `value`.
72
73 ```js
74 // Set the value of the Hint chars option:
75 vimfx.set('hint_chars', 'abcdefghijklmnopqrstuvwxyz')
76 // Add yet a keyboard shortcut for the `f` command:
77 vimfx.set('mode.normal.follow', vimfx.getDefault('mode.normal.follow') + ' e')
78 ```
79
80 When extending a pref (as in the second example above), be sure to use
81 `vimfx.getDefault` rather than `vimfx.get`. Otherwise you get a multiplying
82 effect. In the above example, after starting Firefox a few times the pref would
83 be `f e e e e`. Also, if you find that example very verbose: Remember that
84 you’re using a programming language! Write a small helper function that suits
85 your needs.
86
87 Note: If you produce conflicting keyboard shortcuts, the order of your code does
88 not matter. The command that comes first in VimFx’s settings page in the Add-ons
89 Manager (and in the Keyboard Shortcuts help dialog) gets the shortcut; the other
90 one(s) do(es) not. See the notes about order in [mode object], [category object]
91 and [command object] for more information about order.
92
93 ```js
94 // Even though we set the shortcut for focusing the search bar last, the command
95 // for focusing the location bar “wins”, because it comes first in VimFx’s
96 // settings page in the Add-ons Manager.
97 vimfx.set('mode.normal.focus_location_bar', 'ö')
98 vimfx.set('mode.normal.focus_search_bar', 'ö')
99
100 // Swapping their orders also swaps the “winner”.
101 let {commands} = vimfx.modes.normal
102 ;[commands.focus_location_bar.order, commands.focus_search_bar.order] =
103 [commands.focus_search_bar.order, commands.focus_location_bar.order]
104 ```
105
106 ### `vimfx.addCommand(options, fn)`
107
108 Creates a new command.
109
110 **Note:** This should only be used by config file users, not by extension
111 authors who wish to extend VimFx. They should add commands manually to
112 [`vimfx.modes`] instead.
113
114 `options`:
115
116 - name: `String`. The name used when accessing the command via
117 `vimfx.modes[options.mode].commands[options.name]`. It is also used for the
118 pref used to store the shortcuts for the command:
119 `` `custom.mode.${options.mode}.${options.name}` ``.
120 - description: `String`. Shown in the Keyboard Shortcuts help dialog and VimFx’s
121 settings page in the Add-ons Manager.
122 - mode: `String`. Defaults to `'normal'`. The mode to add the command to. The
123 value has to be one of the keys of [`vimfx.modes`].
124 - category: `String`. Defaults to `'misc'` for Normal mode and `''`
125 (uncategorized) otherwise. The category to add the command to. The
126 value has to be one of the keys of [`vimfx.get('categories')`][categories].
127 - order: `Number`. Defaults to putting the command at the end of the category.
128 The first of the default commands has the order `100` and then they increase
129 by `100` per command. This allows to put new commands between two already
130 existing ones.
131
132 `fn` is called when the command is activated. See the [onInput] documentation
133 below for more information.
134
135 <strong id="custom-command-shortcuts">Note</strong> that you have to give the
136 new command a shortcut in VimFx’s settings page in the Add-ons Manager or set
137 one using `vimfx.set()` to able to use the new command.
138
139 ```js
140 vimfx.addCommand({
141 name: 'hello',
142 description: 'Log Hello World',
143 }, => {
144 console.log('Hello World!')
145 })
146 // Optional:
147 vimfx.set('custom.mode.normal.hello', 'gö')
148 ```
149
150 ### `vimfx.addOptionOverrides(...rules)` and `vimfx.addKeyOverrides(...rules)`
151
152 These methods take any number of arguments. Each argument is a rule. The rules
153 are added in order. The methods may be run multiple times.
154
155 A rule is an `Array` of length 2:
156
157 1. The first item is a function that returns `true` if the rule should be
158 applied and `false` if not. This is called the matching function.
159 2. The second item is the value that should be used if the rule is applied. This
160 is called the override.
161
162 The rules are tried in the same order they were added. When a matching rule is
163 found it is applied. No more rules will be applied.
164
165 #### `vimfx.addOptionOverrides(...rules)`
166
167 The rules are matched any time the value of a VimFx pref is needed.
168
169 The matching function receives a [location object].
170
171 The override is an object whose keys are VimFx pref names and whose values
172 override the pref in question. The values should be formatted as in an [options
173 object].
174
175 ```js
176 vimfx.addOptionOverrides(
177 [ ({hostname, pathname, hash}) =>
178 `${hostname}${pathname}${hash}` === 'google.com/',
179 {prevent_autofocus: false}
180 ]
181 )
182 ```
183
184 #### `vimfx.addKeyOverrides(...rules)`
185
186 The rules are matched any time you press a key that is not part of the tail of a
187 multi-key shortcut.
188
189 The matching function receives a [location object] as well as the current
190 mode name (one of the keys of [`vimfx.modes`]).
191
192 The override is an array of keys which should not activate VimFx commands but be
193 sent to the page.
194
195 This allows to disable commands on specific sites. To _add_ commands on specific
196 sites, add them globally and then disable them on all _other_ sites.
197
198 ```js
199 vimfx.addKeyOverrides(
200 [ location => location.hostname === 'facebook.com',
201 ['j', 'k']
202 ]
203 )
204 ```
205
206 ### `vimfx.on(eventName, listener)`
207
208 Runs `listener(data)` when `eventName` is fired.
209
210 #### The `locationChange` event
211
212 Occurs when opening a new tab, navigating to a new URL or refreshing the page,
213 causing a full page load. The data passed to listeners is an object with the
214 following properties:
215
216 - vim: The current [vim object].
217 - location: A [location object].
218
219 This can be used to enter a different mode by default on some pages (which can
220 be used to replace the blacklist option).
221
222 ```js
223 vimfx.on('locationChange', ({vim, location}) => {
224 if (location.hostname === 'example.com') {
225 vim.enterMode('ignore')
226 }
227 })
228 ```
229
230 #### The `notification` and `hideNotification` events
231
232 The `notification` event occurs when `vim.notify(message)` is called, and means
233 that `message` should be displayed to the user.
234
235 The `hideNotification` event occurs when the `vim.hideNotification()` is called,
236 and means that the current notification is requested to be hidden.
237
238 The data passed to listeners is an object with the following properties:
239
240 - vim: The current [vim object].
241 - message: The message that should be notified. Only for the `notification`
242 event.
243
244 Both of these events are emitted even if the [`notifications_enabled`] option is
245 disabled, allowing you to display notifications in any way you want.
246
247 #### The `modeChange` event
248
249 Occurs whenever the current mode in any tab changes. The initial entering of the
250 default mode in new tabs also counts as a mode change. The data passed to
251 listeners is the current [vim object].
252
253 ```js
254 vimfx.on('modeChange', vim => {
255 let mode = vimfx.modes[vim.mode].name
256 vim.notify(`Entering mode: ${mode}`)
257 })
258 ```
259
260 #### The `TabSelect` event
261
262 Occurs whenever any tab in any window is selected. This is also fired when
263 Firefox starts for the currently selected tab. The data passed to listeners is
264 the `event` object passed to the standard Firefox [TabSelect] event.
265
266 ### The `modeDisplayChange` event
267
268 This is basically a combination of the `modeChange` and the `TabSelect` events.
269 The event is useful for knowing when to update UI showing the current mode. The
270 data passed to listeners is the current [vim object].
271
272 (VimFx itself uses this event to update the toolbar [button], by setting
273 `#main-window[vimfx-mode]` to the current mode. You may use this with custom
274 [styling].)
275
276 #### The `focusTypeChange` event
277
278 Occurs when focusing or blurring any element. The data passed to listeners is an
279 object with the following properties:
280
281 - vim: The current [vim object].
282 - focusType: A string similar to `match.focus` of a [match object], with the
283 following differences:
284
285 - The current pressed key is _not_ taken into account, because focus and blur
286 events have no current key.
287 - The value is never `null` or `'other'`, but `'none'` instead.
288
289 (VimFx itself uses this event to update the toolbar [button], by setting
290 `#main-window[vimfx-focus-type]` to the current focus type. You may use this
291 with custom [styling].)
292
293
294
295 ### `vimfx.modes`
296
297 An object whose keys are mode names and whose values are [mode object]s.
298
299 This is a very low-level part of the API. It allows to:
300
301 - Access all commands and run them. This is the only thing that a config file
302 user needs it for.
303
304 ```js
305 let {commands} = vimfx.modes.normal
306 // Inside a custom command:
307 commands.tab_new.run(args)
308 ```
309
310 - Adding new commands. This is intended to be used by extension authors who wish
311 to extend VimFx, not config file users. They should use the
312 `vimfx.addCommand()` helper instead.
313
314 ```js
315 vimfx.modes.normal.commands.new_command = {
316 pref: 'extensions.my_extension.mode.normal.new_command',
317 category: 'misc',
318 order: 10000,
319 description: translate('mode.normal.new_command'),
320 run: args => console.log('New command! args:', args)
321 }
322 ```
323
324 - Adding new modes. This is intended to be used by extension authors who wish to
325 extend VimFx, not config file users.
326
327 ```js
328 vimfx.modes.new_mode = {
329 name: () => translate('mode.new_mode'),
330 order: 10000,
331 commands: {},
332 onEnter(args) {},
333 onLeave(args) {},
334 onInput(args, match) {
335 if (match.type === 'full') {
336 match.command.run(args)
337 }
338 return (match.type !== 'none')
339 },
340 }
341 ```
342
343 Have a look at [modes.coffee] and [commands.coffee] for more information.
344
345 ### `vimfx.get('categories')`
346
347 An object whose keys are category names and whose values are [category object]s.
348
349 ```js
350 let categories = vimfx.get('categories')
351
352 // Add a new category.
353 categories.custom = {
354 name: () => 'Custom commands',
355 order: 10000,
356 }
357
358 // Swap the order of the Location and Tabs categories.
359 ;[commands.focus_location_bar.order, categories.tabs.order] =
360 [categories.tabs.order, commands.focus_location_bar.order]
361 ```
362
363 ### Mode object
364
365 A mode is an object with the following properties:
366
367 - name: `String`. A human readable name of the mode used in the Keyboard
368 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
369 file users adding custom modes could simply use a hard-coded string; extension
370 authors are encouraged to look up the name from a locale file.
371 - order: `Number`. The first of the default modes has the order `100` and then
372 they increase by `100` per mode. This allows to put new modes between two
373 already existing ones.
374 - commands: `Object`. The keys are command names and the values are [command
375 object]s.
376 - onEnter(data, ...args): `Function`. Called when the mode is entered.
377 - onLeave(data): `Function`. Called when the mode is left.
378 - onInput(data, match): `Function`. Called when a key is pressed.
379
380 #### onEnter, onLeave and onInput
381
382 These methods are called with an object (called `data` above) with the following
383 properties:
384
385 - vim: The current [vim object].
386 - storage: An object unique to the current [vim object] and to the current mode.
387 Allows to share things between commands of the same mode by getting and
388 setting keys on it.
389
390 ##### onEnter
391
392 This method is called with an object as mentioned above, and after that there
393 may be any number of arguments (`args` in `vim.enterMode(modeName, ...args)`)
394 that the mode is free to do whatever it wants with.
395
396 Whatever is returned from `onEnter` will be returned from
397 `vim.enterMode(modeName, ...args)`.
398
399 ##### onInput
400
401 The object passed to this method (see above) also has the following properties:
402
403 - uiEvent: `Event` or `false`. The keydown event object if the event occurred in
404 the browser UI, `false` otherwise (if the event occurred in web page content).
405 - count: `Number`. The count for the command. `undefined` if no count. (This is
406 simply a copy of `match.count`. `match` is defined below.)
407
408 The above object should be passed to commands when running them. The mode is
409 free to do whatever it wants with the return value (if any) of the commands it
410 runs.
411
412 It also receives a [match object] as the second argument.
413
414 `onInput` should return `true` if the current keypress should not be passed on
415 to the browser and web pages, and `false` otherwise.
416
417 ### Category object
418
419 A category is an object with the following properties:
420
421 - name: `String`. A human readable name of the category used in the Keyboard
422 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
423 file users adding custom categories could simply a use hard-coded string;
424 extension authors are encouraged to look up the name from a locale file.
425 - order: `Number`. The first of the default categories is the “uncategorized”
426 category. It has the order `100` and then they increase by `100` per category.
427 This allows to put new categories between two already existing ones.
428
429 ### Command object
430
431 A command is an object with the following properties:
432
433 - pref: `String`. The pref used to store the shortcuts for the command.
434 - run(args): `Function`. Called when the command is activated.
435 - description: `String`. A description of the command, shown in the Keyboard
436 Shortcuts help dialog and VimFx’s settings page in the Add-ons Manager. Config
437 file users adding custom commands could simply use a hard-coded string;
438 extension authors are encouraged to look up the name from a locale file.
439 - category: `String`. The category to add the command to. The value has to be
440 one of the keys of [`vimfx.get('categories')`][categories].
441 - order: `Number`. The first of the default commands has the order `100` and
442 then they increase by `100` per command. This allows to put new commands
443 between two already existing ones.
444
445 ### Match object
446
447 A `match` object has the following properties:
448
449 - type: `String`. It has one of the following values:
450
451 - `'full'`: The current keypress, together with previous keypresses, fully
452 matches a command shortcut.
453 - `'partial'`: The current keypress, together with previous keypresses,
454 partially matches a command shortcut.
455 - `'count'`: The current keypress is not part of a command shortcut, but is a
456 digit and contributes to the count of a future matched command.
457 - `'none'`: The current keypress is not part of a command shortcut and does
458 not contribute to a count.
459
460 - focus: `String` or `null`. The type of currently focused _element_ plus
461 current pressed _key_ combo. You might not want to run commands and suppress
462 the event if this value is anything other than null. It has one of the
463 following values, depending on what kind of _element_ is focused and which
464 _key_ was pressed:
465
466 - `'editable'`: element: some kind of text input, a `<select>` element or a
467 “contenteditable” element. key: any pressed key.
468 - `'activatable'`: element: an “activatable” element (link or button).
469 key: see the [`activatable_element_keys`] option.
470 - `'adjustable'`: element: an “adjustable” element (form control or video
471 player). key: see the [`adjustable_element_keys`] option.
472 - `'other'`: element: some other kind of element that can receive keystrokes,
473 for example an element in fullscreen mode. key: any pressed key.
474
475 If none of the above criteria is met, the value is `null`, which means that
476 the currently focused element does not appear to respond to keystrokes in any
477 special way.
478
479 - command: `null` unless `type` is `'full'`. Then it is the matched command (a
480 [command object]).
481
482 The matched command should usually be run at this point. It is suitable to
483 pass on the object passed to [onInput] to the command. Some modes might choose
484 to add extra properties to the object first. (That is favored over passing
485 several arguments, since it makes it easier for the command to in turn pass
486 the same data it got on to another command, if needed.)
487
488 Usually the return value of the command isn’t used, but that’s up to the mode.
489
490 - count: `Number`. The count for the command. `undefined` if no count.
491
492 - specialKeys: `Object`. The keys may be any of the following:
493
494 - `<force>`
495 - `<late>`
496
497 If a key exists, its value is always `true`. The keys that exist indicate the
498 [special keys] for the sequence used for the matched command (if any).
499
500 - keyStr: `String`. The current keypress represented as a string.
501
502 - unmodifiedKey: `String`. `keyStr` without modifiers.
503
504 - toplevel: `Boolean`. Whether or not the match was a toplevel match in the
505 shortcut key tree. This is `true` unless the match is part of the tail of a
506 multi-key shortcut.
507
508 - discard(): `Function`. Discards keys pressed so far: If `type` is `'partial'`
509 or `'count'`. For example, if you have typed `12g`, run `match.discard()` and
510 then press `$`, the `$` command will be run instead of `12g$`.
511
512 ### Vim object
513
514 There is one `vim` object per tab.
515
516 A `vim` object has the following properties:
517
518 - window: [`Window`]. The current Firefox window object. Most commands
519 interacting with Firefox’s UI use this.
520
521 - browser: [`Browser`]. The `browser` that this vim object handles.
522
523 - options: `Object`. Provides access to all of VimFx’s options. It is an
524 [options object].
525
526 - mode: `String`. The current mode name.
527
528 - enterMode(modeName, ...args): `Function`. Enter mode `modeName`, passing
529 `...args` to the mode. It is up to every mode to do whatever it wants to with
530 `...args`. If `modeName` was already the current mode, nothing is done and
531 `undefined` is returned. Otherwise it us up to the mode to return whatever it
532 wants to.
533
534 - isUIEvent(event): `Function`. Returns `true` if `event` occurred in the
535 browser UI, and `false` otherwise (if it occurred in web page content).
536
537 - notify(message): `Function`. Display a notification with the text `message`.
538
539 - hideNotification(): `Function`. Hide the current notification (if any).
540
541 - markPageInteraction(value=true): `Function`. When `value` is `true` (as it is
542 by default when the argument is omitted), marks that the user has interacted
543 with the page. After that [autofocus prevention] is not done anymore. Commands
544 interacting with web page content might want to do this. If `value` is
545 `false`, the state is reset and autofocus prevention _will_ be done again.
546
547 **Warning:** There are also properties starting with an underscore on `vim`
548 objects. They are private, and not supposed to be used outside of VimFx’s own
549 source code. They may change at any time.
550
551 ### Options object
552
553 An `options` object provides access to all of VimFx’s options. It is an object
554 whose keys are VimFx pref names.
555
556 Note that the values are not just simply `vimfx.get(pref)` for the `pref` in
557 question; they are _parsed_ (`parse(vimfx.get(pref))`):
558
559 - Space-separated prefs are parsed into arrays of strings.
560
561 - `black_list` and `{prev,next}_patterns` are parsed into arrays of regular
562 expressions.
563
564 (See [parse-prefs.coffee] for all details.)
565
566 Any [option overrides] are automatically taken into account when getting an
567 option value.
568
569 The [special options] are also available on this object.
570
571
572 ### Location object
573
574 A location object is very similar to [`window.location`] in web pages.
575 Technically, it is a [`URL`] instance. You can experiment with the current
576 location object by opening the [web console] and entering `location`.
577
578
579 ## Frame script API
580
581 In frame scripts, the API consists of assigning global variables prefixed with
582 `VimFx`. VimFx then uses these when needed.
583
584 ```js
585 this.VimFxSomething = ...
586 ```
587
588 ### `VimFxHintMatcher(...)`
589
590 **Note:** This should only be used by config file users, not by extension
591 authors who wish to extend VimFx.
592
593 If available, it is used to let you customize which elements do and don’t get
594 hints. It might help to read about [the `f` commands] first.
595
596 ```js
597 this.VimFxHintMatcher = (id, element, {type, semantic}) => {
598 // Inspect `element` and change `type` and `semantic` if needed.
599 return {type, semantic}
600 }
601 ```
602
603 The arguments passed to this function are:
604
605 - id: `String`. A string identifying which command is used:
606
607 - `'normal'`: `f` or `af`.
608 - `'tab'`: `F`, `gf` or `gF`.
609 - `'copy'`: `yf`.
610 - `'focus'`: `zf`.
611
612 - element: `Element`. One out of all elements currently inside the viewport.
613
614 - info: `Object`. It has the following properties:
615
616 - type: `String` or `null`. If a string, it means that `element` should get a
617 hint. If `null`, it won’t. See the available strings below. When a marker
618 is matched, `type` decides what happens to `element`.
619 - semantic: `Boolean`. Indicates whether or not the element is “semantic.”
620 Semantic elements get better hints.
621
622 This object contains information on how VimFx has matched `element`. You have
623 the opportunity to change this.
624
625 The available type strings depend on `id`:
626
627 - normal:
628
629 - link: A “proper” link (not used as a button with the help of JavaScript),
630 with an `href` attribute.
631 - text: An element that can you can type in, such as text inputs.
632 - clickable: Some clickable element not falling into another category.
633 - clickable-special: Like “clickable,” but uses a different technique to
634 simulate a click on the element. If “clickable” doesn’t work, try this one.
635 - scrollable: A scrollable element.
636
637 - tab:
638
639 - link: Like “link” when `id` is “normal” (see above).
640
641 - copy:
642
643 - link: Like “link” when `id` is “normal” (see above).
644 - text: Like “text” when `id` is “normal” (see above), except that in this
645 case “contenteditable” elements are not included.
646 - contenteditable: Elements with “contenteditable” turned on.
647
648 - focus:
649
650 - focusable: Any focusable element not falling into another category.
651 - scrollable: Like “scrollable” when `id` is “normal” (see above).
652
653 The function must return an object like the `info` parameter (with the `type`
654 and `semantic` properties).
655
656
657 ## Stability
658
659 The public API is currently **experimental** and therefore **unstable.** Things
660 might break with new VimFx versions. However, no breaking changes are planned,
661 and will be avoided if feasible.
662
663 As soon as VimFx 1.0.0 (which does not seem to be too far away) is released
664 backwards compatibility will be a priority and won’t be broken until VimFx
665 2.0.0.
666
667 [option overrides]: #vimfxaddoptionoverridesrules
668 [categories]: #vimfxgetcategories
669 [`vimfx.modes`]: #vimfxmodes
670 [onInput]: #oninput
671 [mode object]: #mode-object
672 [category object]: #category-object
673 [command object]: #command-object
674 [match object]: #match-object
675 [vim object]: #vim-object
676 [options object]: #options-object
677 [location object]: #location-object
678
679 [blacklisted]: options.md#blacklist
680 [special options]: options.md#special-options
681 [config file]: config-file.md
682 [bootstrap.js]: config-file.md#bootstrapjs
683 [autofocus prevention]: options.md#prevent-autofocus
684 [`activatable_element_keys`]: options.md#activatable_element_keys
685 [`adjustable_element_keys`]: options.md#adjustable_element_keys
686 [`notifications_enabled`]: options.md#notifications_enabled
687
688 [button]: button.md
689 [the `f` commands]: commands.md#the-f-commands-1
690 [special keys]: shortcuts.md#special-keys
691 [styling]: styling.md
692
693 [defaults.coffee]: ../extension/lib/defaults.coffee
694 [parse-prefs.coffee]: ../extension/lib/parse-prefs.coffee
695 [modes.coffee]: ../extension/lib/modes.coffee
696 [commands.coffee]: ../extension/lib/commands.coffee
697 [vim.coffee]: ../extension/lib/vim.coffee
698
699 [`Window`]: https://developer.mozilla.org/en-US/docs/Web/API/Window
700 [`Browser`]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
701 [`window.location`]: https://developer.mozilla.org/en-US/docs/Web/API/Location
702 [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
703 [TabSelect]: https://developer.mozilla.org/en-US/docs/Web/Events/TabSelect
704 [web console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console
705 [about:config]: http://kb.mozillazine.org/About:config
Imprint / Impressum