]> git.gir.st - VimFx.git/blob - extension/lib/commands.coffee
Add missing `require` in commands.coffee
[VimFx.git] / extension / lib / commands.coffee
1 ###
2 # Copyright Anton Khodakivskiy 2012, 2013, 2014.
3 # Copyright Simon Lydell 2013, 2014, 2015, 2016.
4 # Copyright Wang Zhuochun 2013, 2014.
5 #
6 # This file is part of VimFx.
7 #
8 # VimFx is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # VimFx is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
20 ###
21
22 # This file defines all Normal mode commands. Commands that need to interact
23 # with web page content do so by running `vim._run(name)`, which invokes `name`
24 # in commands-frame.coffee.
25
26 # NOTE: Most tab related commands need to do their actual tab manipulations in
27 # the next tick (`utils.nextTick`) to work around bug 1200334.
28
29 config = require('./config')
30 help = require('./help')
31 hints = require('./hints')
32 prefs = require('./prefs')
33 translate = require('./l10n')
34 utils = require('./utils')
35 viewportUtils = require('./viewport')
36
37 {ContentClick} = Cu.import('resource:///modules/ContentClick.jsm', {})
38
39 commands = {}
40
41
42
43 commands.focus_location_bar = ({vim}) ->
44 vim.window.focusAndSelectUrlBar()
45
46 commands.focus_search_bar = ({vim, count}) ->
47 # The `.webSearch()` method opens a search engine in a tab if the search bar
48 # has been removed. Therefore we first check if it exists.
49 if vim.window.BrowserSearch.searchBar
50 vim.window.BrowserSearch.webSearch()
51 else
52 vim.notify(translate('notification.focus_search_bar.none'))
53
54 helper_paste_and_go = (props, {vim}) ->
55 {gURLBar} = vim.window
56 gURLBar.value = vim.window.readFromClipboard()
57 gURLBar.handleCommand(new vim.window.KeyboardEvent('keydown', props))
58
59 commands.paste_and_go = helper_paste_and_go.bind(null, null)
60
61 commands.paste_and_go_in_tab = helper_paste_and_go.bind(null, {altKey: true})
62
63 commands.copy_current_url = ({vim}) ->
64 utils.writeToClipboard(vim.window.gBrowser.currentURI.spec)
65 vim.notify(translate('notification.copy_current_url.success'))
66
67 commands.go_up_path = ({vim, count}) ->
68 vim._run('go_up_path', {count})
69
70 commands.go_to_root = ({vim}) ->
71 vim._run('go_to_root')
72
73 commands.go_home = ({vim}) ->
74 vim.window.BrowserHome()
75
76 helper_go_history = (direction, {vim, count = 1}) ->
77 {window} = vim
78 {SessionStore, gBrowser} = window
79
80 if (direction == 'back' and not gBrowser.canGoBack) or
81 (direction == 'forward' and not gBrowser.canGoForward)
82 vim.notify(translate("notification.history_#{direction}.limit"))
83 return
84
85 # `SessionStore.getSessionHistory()` (used below to support counts) starts
86 # lots of asynchronous tasks internally, which is a bit unreliable, it has
87 # turned out. The primary use of the `history_back` and `history_forward`
88 # commands is to go _one_ step back or forward, though, so those cases are
89 # optimized to use more reliable ways of going back and forward. Also, some
90 # extensions override the following functions, so calling them also gives
91 # better interoperability.
92 if count == 1
93 if direction == 'back'
94 window.BrowserBack()
95 else
96 window.BrowserForward()
97 return
98
99 SessionStore.getSessionHistory(gBrowser.selectedTab, (sessionHistory) ->
100 {index} = sessionHistory
101 newIndex = index + count * (if direction == 'back' then -1 else 1)
102 newIndex = Math.max(newIndex, 0)
103 newIndex = Math.min(newIndex, sessionHistory.entries.length - 1)
104 gBrowser.gotoIndex(newIndex)
105 )
106
107 commands.history_back = helper_go_history.bind(null, 'back')
108
109 commands.history_forward = helper_go_history.bind(null, 'forward')
110
111 commands.history_list = ({vim}) ->
112 menu = vim.window.document.getElementById('backForwardMenu')
113 utils.openPopup(menu)
114 if menu.childElementCount == 0
115 vim.notify(translate('notification.history_list.none'))
116
117 commands.reload = ({vim}) ->
118 vim.window.BrowserReload()
119
120 commands.reload_force = ({vim}) ->
121 vim.window.BrowserReloadSkipCache()
122
123 commands.reload_all = ({vim}) ->
124 vim.window.gBrowser.reloadAllTabs()
125
126 commands.reload_all_force = ({vim}) ->
127 for tab in vim.window.gBrowser.visibleTabs
128 gBrowser = tab.linkedBrowser
129 consts = gBrowser.webNavigation
130 flags = consts.LOAD_FLAGS_BYPASS_PROXY | consts.LOAD_FLAGS_BYPASS_CACHE
131 gBrowser.reload(flags)
132 return
133
134 commands.stop = ({vim}) ->
135 vim.window.BrowserStop()
136
137 commands.stop_all = ({vim}) ->
138 for tab in vim.window.gBrowser.visibleTabs
139 tab.linkedBrowser.stop()
140 return
141
142
143
144 helper_scroll = (vim, uiEvent, args...) ->
145 [
146 method, type, directions, amounts
147 properties = null, adjustment = 0, name = 'scroll'
148 ] = args
149 options = {
150 method, type, directions, amounts, properties, adjustment
151 smooth: (
152 prefs.root.get('general.smoothScroll') and
153 prefs.root.get("general.smoothScroll.#{type}")
154 )
155 }
156 reset = prefs.root.tmp(
157 'layout.css.scroll-behavior.spring-constant',
158 vim.options["smoothScroll.#{type}.spring-constant"]
159 )
160
161 helpScroll = help.getHelp(vim.window)?.querySelector('.wrapper')
162 if uiEvent or helpScroll
163 activeElement = helpScroll or utils.getActiveElement(vim.window)
164 if vim._state.scrollableElements.has(activeElement) or helpScroll
165 viewportUtils.scroll(activeElement, options)
166 reset()
167 return
168
169 vim._run(name, options, reset)
170
171
172 helper_scrollByLinesX = (amount, {vim, uiEvent, count = 1}) ->
173 distance = prefs.root.get('toolkit.scrollbox.horizontalScrollDistance')
174 helper_scroll(
175 vim, uiEvent, 'scrollBy', 'lines', ['left'], [amount * distance * count * 5]
176 )
177
178 helper_scrollByLinesY = (amount, {vim, uiEvent, count = 1}) ->
179 distance = prefs.root.get('toolkit.scrollbox.verticalScrollDistance')
180 helper_scroll(
181 vim, uiEvent, 'scrollBy', 'lines', ['top'], [amount * distance * count * 20]
182 )
183
184 helper_scrollByPagesY = (amount, type, {vim, uiEvent, count = 1}) ->
185 adjustment = vim.options["scroll.#{type}_page_adjustment"]
186 helper_scroll(
187 vim, uiEvent, 'scrollBy', 'pages', ['top'], [amount * count],
188 ['clientHeight'], adjustment
189 )
190
191 helper_scrollToX = (amount, {vim, uiEvent}) ->
192 helper_mark_last_scroll_position(vim)
193 helper_scroll(
194 vim, uiEvent, 'scrollTo', 'other', ['left'], [amount], ['scrollLeftMax']
195 )
196
197 helper_scrollToY = (amount, {vim, uiEvent}) ->
198 helper_mark_last_scroll_position(vim)
199 helper_scroll(
200 vim, uiEvent, 'scrollTo', 'other', ['top'], [amount], ['scrollTopMax']
201 )
202
203 commands.scroll_left = helper_scrollByLinesX.bind(null, -1)
204 commands.scroll_right = helper_scrollByLinesX.bind(null, +1)
205 commands.scroll_down = helper_scrollByLinesY.bind(null, +1)
206 commands.scroll_up = helper_scrollByLinesY.bind(null, -1)
207 commands.scroll_page_down = helper_scrollByPagesY.bind(null, +1, 'full')
208 commands.scroll_page_up = helper_scrollByPagesY.bind(null, -1, 'full')
209 commands.scroll_half_page_down = helper_scrollByPagesY.bind(null, +0.5, 'half')
210 commands.scroll_half_page_up = helper_scrollByPagesY.bind(null, -0.5, 'half')
211 commands.scroll_to_top = helper_scrollToY.bind(null, 0)
212 commands.scroll_to_bottom = helper_scrollToY.bind(null, Infinity)
213 commands.scroll_to_left = helper_scrollToX.bind(null, 0)
214 commands.scroll_to_right = helper_scrollToX.bind(null, Infinity)
215
216 helper_mark_last_scroll_position = (vim) ->
217 keyStr = vim.options['scroll.last_position_mark']
218 vim._run('mark_scroll_position', {keyStr, notify: false})
219
220 commands.mark_scroll_position = ({vim}) ->
221 vim.enterMode('marks', (keyStr) -> vim._run('mark_scroll_position', {keyStr}))
222 vim.notify(translate('notification.mark_scroll_position.enter'))
223
224 commands.scroll_to_mark = ({vim}) ->
225 vim.enterMode('marks', (keyStr) ->
226 unless keyStr == vim.options['scroll.last_position_mark']
227 helper_mark_last_scroll_position(vim)
228 helper_scroll(
229 vim, null, 'scrollTo', 'other', ['top', 'left'], keyStr,
230 ['scrollTopMax', 'scrollLeftMax'], 0, 'scroll_to_mark'
231 )
232 )
233 vim.notify(translate('notification.scroll_to_mark.enter'))
234
235
236
237 commands.tab_new = ({vim}) ->
238 utils.nextTick(vim.window, ->
239 vim.window.BrowserOpenTab()
240 )
241
242 commands.tab_new_after_current = ({vim}) ->
243 {window} = vim
244 newTabPosition = window.gBrowser.selectedTab._tPos + 1
245 utils.nextTick(window, ->
246 utils.listenOnce(window, 'TabOpen', (event) ->
247 newTab = event.originalTarget
248 window.gBrowser.moveTabTo(newTab, newTabPosition)
249 )
250 window.BrowserOpenTab()
251 )
252
253 commands.tab_duplicate = ({vim}) ->
254 {gBrowser} = vim.window
255 utils.nextTick(vim.window, ->
256 gBrowser.duplicateTab(gBrowser.selectedTab)
257 )
258
259 absoluteTabIndex = (relativeIndex, gBrowser, {pinnedSeparate}) ->
260 tabs = gBrowser.visibleTabs
261 {selectedTab} = gBrowser
262
263 currentIndex = tabs.indexOf(selectedTab)
264 absoluteIndex = currentIndex + relativeIndex
265 numTabsTotal = tabs.length
266 numPinnedTabs = gBrowser._numPinnedTabs
267
268 [numTabs, min] = switch
269 when not pinnedSeparate
270 [numTabsTotal, 0]
271 when selectedTab.pinned
272 [numPinnedTabs, 0]
273 else
274 [numTabsTotal - numPinnedTabs, numPinnedTabs]
275
276 # Wrap _once_ if at one of the ends of the tab bar and cannot move in the
277 # current direction.
278 if (relativeIndex < 0 and currentIndex == min) or
279 (relativeIndex > 0 and currentIndex == min + numTabs - 1)
280 if absoluteIndex < min
281 absoluteIndex += numTabs
282 else if absoluteIndex >= min + numTabs
283 absoluteIndex -= numTabs
284
285 absoluteIndex = Math.max(min, absoluteIndex)
286 absoluteIndex = Math.min(absoluteIndex, min + numTabs - 1)
287
288 return absoluteIndex
289
290 helper_switch_tab = (direction, {vim, count = 1}) ->
291 {gBrowser} = vim.window
292 index = absoluteTabIndex(direction * count, gBrowser, {pinnedSeparate: false})
293 utils.nextTick(vim.window, ->
294 gBrowser.selectTabAtIndex(index)
295 )
296
297 commands.tab_select_previous = helper_switch_tab.bind(null, -1)
298
299 commands.tab_select_next = helper_switch_tab.bind(null, +1)
300
301 helper_is_visited = (tab) ->
302 return tab.getAttribute('VimFx-visited') or not tab.getAttribute('unread')
303
304 commands.tab_select_most_recent = ({vim, count = 1}) ->
305 {gBrowser} = vim.window
306 tabsSorted =
307 Array.filter(
308 gBrowser.tabs,
309 (tab) -> not tab.closing and helper_is_visited(tab)
310 ).sort((a, b) -> b.lastAccessed - a.lastAccessed)[1..] # Remove current tab.
311 tab = tabsSorted[Math.min(count - 1, tabsSorted.length - 1)]
312 if tab
313 gBrowser.selectedTab = tab
314 else
315 vim.notify(translate('notification.tab_select_most_recent.none'))
316
317 commands.tab_select_oldest_unvisited = ({vim, count = 1}) ->
318 {gBrowser} = vim.window
319 tabsSorted =
320 Array.filter(
321 gBrowser.tabs,
322 (tab) -> not tab.closing and not helper_is_visited(tab)
323 ).sort((a, b) -> a.lastAccessed - b.lastAccessed)
324 tab = tabsSorted[Math.min(count - 1, tabsSorted.length - 1)]
325 if tab
326 gBrowser.selectedTab = tab
327 else
328 vim.notify(translate('notification.tab_select_oldest_unvisited.none'))
329
330 helper_move_tab = (direction, {vim, count = 1}) ->
331 {gBrowser} = vim.window
332 index = absoluteTabIndex(direction * count, gBrowser, {pinnedSeparate: true})
333 utils.nextTick(vim.window, ->
334 gBrowser.moveTabTo(gBrowser.selectedTab, index)
335 )
336
337 commands.tab_move_backward = helper_move_tab.bind(null, -1)
338
339 commands.tab_move_forward = helper_move_tab.bind(null, +1)
340
341 commands.tab_move_to_window = ({vim}) ->
342 {gBrowser} = vim.window
343 gBrowser.replaceTabWithWindow(gBrowser.selectedTab)
344
345 commands.tab_select_first = ({vim, count = 1}) ->
346 utils.nextTick(vim.window, ->
347 vim.window.gBrowser.selectTabAtIndex(count - 1)
348 )
349
350 commands.tab_select_first_non_pinned = ({vim, count = 1}) ->
351 firstNonPinned = vim.window.gBrowser._numPinnedTabs
352 utils.nextTick(vim.window, ->
353 vim.window.gBrowser.selectTabAtIndex(firstNonPinned + count - 1)
354 )
355
356 commands.tab_select_last = ({vim, count = 1}) ->
357 utils.nextTick(vim.window, ->
358 vim.window.gBrowser.selectTabAtIndex(-count)
359 )
360
361 commands.tab_toggle_pinned = ({vim}) ->
362 currentTab = vim.window.gBrowser.selectedTab
363 if currentTab.pinned
364 vim.window.gBrowser.unpinTab(currentTab)
365 else
366 vim.window.gBrowser.pinTab(currentTab)
367
368 commands.tab_close = ({vim, count = 1}) ->
369 {gBrowser} = vim.window
370 return if gBrowser.selectedTab.pinned
371 currentIndex = gBrowser.visibleTabs.indexOf(gBrowser.selectedTab)
372 utils.nextTick(vim.window, ->
373 for tab in gBrowser.visibleTabs[currentIndex...(currentIndex + count)]
374 gBrowser.removeTab(tab)
375 return
376 )
377
378 commands.tab_restore = ({vim, count = 1}) ->
379 utils.nextTick(vim.window, ->
380 for index in [0...count] by 1
381 restoredTab = vim.window.undoCloseTab()
382 if not restoredTab and index == 0
383 vim.notify(translate('notification.tab_restore.none'))
384 break
385 return
386 )
387
388 commands.tab_restore_list = ({vim}) ->
389 {window} = vim
390 fragment = window.RecentlyClosedTabsAndWindowsMenuUtils.getTabsFragment(
391 window, 'menuitem'
392 )
393 if fragment.childElementCount == 0
394 vim.notify(translate('notification.tab_restore.none'))
395 else
396 utils.openPopup(utils.injectTemporaryPopup(window.document, fragment))
397
398 commands.tab_close_to_end = ({vim}) ->
399 {gBrowser} = vim.window
400 gBrowser.removeTabsToTheEndFrom(gBrowser.selectedTab)
401
402 commands.tab_close_other = ({vim}) ->
403 {gBrowser} = vim.window
404 gBrowser.removeAllTabsBut(gBrowser.selectedTab)
405
406
407
408 helper_follow = (name, vim, callback, count = null) ->
409 vim.markPageInteraction()
410 help.removeHelp(vim.window)
411
412 # Enter hints mode immediately, with an empty set of markers. The user might
413 # press keys before the `vim._run` callback is invoked. Those key presses
414 # should be handled in hints mode, not normal mode.
415 initialMarkers = []
416 storage = vim.enterMode(
417 'hints', initialMarkers, callback, count, vim.options.hints_sleep
418 )
419
420 setMarkers = ({wrappers, viewport}) ->
421 if wrappers.length > 0
422 {markers, markerMap} = hints.injectHints(
423 vim.window, wrappers, viewport, vim.options
424 )
425 storage.markers = markers
426 storage.markerMap = markerMap
427 else
428 vim.notify(translate('notification.follow.none'))
429 vim.enterMode('normal')
430
431 vim._run(name, {}, (result) ->
432 # The user might have exited hints mode (and perhaps even entered it again)
433 # before this callback is invoked. If so, `storage.markers` has been
434 # cleared, or set to a new value. Only proceed if it is unchanged.
435 return unless storage.markers == initialMarkers
436 setMarkers(result)
437 storage.markEverything = ->
438 lastMarkers = storage.markers
439 vim._run(name, {markEverything: true}, (newResult) ->
440 return unless storage.markers == lastMarkers
441 setMarkers(newResult)
442 )
443 )
444
445 helper_follow_clickable = (options, {vim, count = 1}) ->
446 callback = (marker, timesLeft, keyStr) ->
447 {inTab, inBackground} = options
448 {type, elementIndex} = marker.wrapper
449 isLast = (timesLeft == 1)
450 isLink = (type == 'link')
451
452 switch
453 when keyStr.startsWith(vim.options.hints_toggle_in_tab)
454 inTab = not inTab
455 when keyStr.startsWith(vim.options.hints_toggle_in_background)
456 inTab = true
457 inBackground = not inBackground
458 else
459 unless isLast
460 inTab = true
461 inBackground = true
462
463 inTab = false unless isLink
464
465 if type == 'text' or (isLink and not (inTab and inBackground))
466 isLast = true
467
468 vim._focusMarkerElement(elementIndex)
469
470 if inTab
471 utils.nextTick(vim.window, ->
472 # `ContentClick.contentAreaClick` is what Firefox invokes when you click
473 # links using the mouse. Using that instead of simply
474 # `gBrowser.loadOneTab(url, options)` gives better interoperability with
475 # other add-ons, such as Tree Style Tab and BackTrack Tab History.
476 reset = prefs.root.tmp('browser.tabs.loadInBackground', true)
477 ContentClick.contentAreaClick({
478 href: marker.wrapper.href
479 shiftKey: not inBackground
480 ctrlKey: true
481 metaKey: true
482 }, vim.browser)
483 reset()
484 )
485 else
486 vim._run('click_marker_element', {
487 elementIndex, type
488 preventTargetBlank: vim.options.prevent_target_blank
489 })
490
491 return not isLast
492
493 name = if options.inTab then 'follow_in_tab' else 'follow'
494 helper_follow(name, vim, callback, count)
495
496 commands.follow =
497 helper_follow_clickable.bind(null, {inTab: false, inBackground: true})
498
499 commands.follow_in_tab =
500 helper_follow_clickable.bind(null, {inTab: true, inBackground: true})
501
502 commands.follow_in_focused_tab =
503 helper_follow_clickable.bind(null, {inTab: true, inBackground: false})
504
505 commands.follow_in_window = ({vim}) ->
506 callback = (marker) ->
507 vim._focusMarkerElement(marker.wrapper.elementIndex)
508 {href} = marker.wrapper
509 vim.window.openLinkIn(href, 'window', {}) if href
510 helper_follow('follow_in_tab', vim, callback)
511
512 commands.follow_multiple = (args) ->
513 args.count = Infinity
514 commands.follow(args)
515
516 commands.follow_copy = ({vim}) ->
517 callback = (marker) ->
518 {elementIndex} = marker.wrapper
519 property = switch marker.wrapper.type
520 when 'link'
521 'href'
522 when 'text'
523 'value'
524 when 'contenteditable', 'other'
525 'textContent'
526 vim._run('copy_marker_element', {elementIndex, property})
527 helper_follow('follow_copy', vim, callback)
528
529 commands.follow_focus = ({vim}) ->
530 callback = (marker) ->
531 vim._focusMarkerElement(marker.wrapper.elementIndex, {select: true})
532 helper_follow('follow_focus', vim, callback)
533
534 commands.click_browser_element = ({vim}) ->
535 markerElements = []
536
537 filter = ({markEverything}, element, getElementShape) ->
538 document = element.ownerDocument
539 semantic = true
540 type = switch
541 when vim._state.scrollableElements.has(element)
542 'scrollable'
543 when utils.isFocusable(element) or
544 (element.onclick and element.localName != 'statuspanel')
545 'clickable'
546
547 if markEverything and not type
548 type = 'other'
549 semantic = false
550
551 return unless type
552 return unless shape = getElementShape(element)
553 length = markerElements.push(element)
554 return {type, semantic, shape, elementIndex: length - 1}
555
556 callback = (marker) ->
557 element = markerElements[marker.wrapper.elementIndex]
558 switch marker.wrapper.type
559 when 'scrollable'
560 utils.focusElement(element, {flag: 'FLAG_BYKEY'})
561 when 'clickable', 'other'
562 sequence =
563 if element.localName == 'tab'
564 ['mousedown']
565 else
566 'click-xul'
567 utils.focusElement(element)
568 utils.simulateMouseEvents(element, sequence)
569
570 createMarkers = (wrappers) ->
571 viewport = viewportUtils.getWindowViewport(vim.window)
572 {markers} = hints.injectHints(vim.window, wrappers, viewport, {
573 hint_chars: vim.options.hint_chars
574 ui: true
575 })
576 return markers
577
578 wrappers = hints.getMarkableElements(
579 vim.window, filter.bind(null, {markEverything: false})
580 )
581
582 if wrappers.length > 0
583 storage = vim.enterMode('hints', createMarkers(wrappers), callback)
584 storage.markEverything = ->
585 newWrappers = hints.getMarkableElements(
586 vim.window, filter.bind(null, {markEverything: true})
587 )
588 storage.markers = createMarkers(newWrappers)
589 else
590 vim.notify(translate('notification.follow.none'))
591
592 helper_follow_pattern = (type, {vim}) ->
593 options = {
594 pattern_selector: vim.options.pattern_selector
595 pattern_attrs: vim.options.pattern_attrs
596 patterns: vim.options["#{type}_patterns"]
597 }
598 vim._run('follow_pattern', {type, options})
599
600 commands.follow_previous = helper_follow_pattern.bind(null, 'prev')
601
602 commands.follow_next = helper_follow_pattern.bind(null, 'next')
603
604 commands.focus_text_input = ({vim, count}) ->
605 vim.markPageInteraction()
606 vim._run('focus_text_input', {count})
607
608 helper_follow_selectable = ({select}, {vim}) ->
609 callback = (marker) ->
610 vim._run('element_text_select', {
611 elementIndex: marker.wrapper.elementIndex
612 full: select
613 })
614 vim.enterMode('caret', select)
615 helper_follow('follow_selectable', vim, callback)
616
617 commands.element_text_caret =
618 helper_follow_selectable.bind(null, {select: false})
619
620 commands.element_text_select =
621 helper_follow_selectable.bind(null, {select: true})
622
623 commands.element_text_copy = ({vim}) ->
624 callback = (marker) ->
625 vim._run('copy_marker_element', {
626 elementIndex: marker.wrapper.elementIndex
627 property: 'textContent'
628 })
629 helper_follow('follow_selectable', vim, callback)
630
631
632
633 findStorage = {lastSearchString: ''}
634
635 helper_find = ({highlight, linksOnly = false}, {vim}) ->
636 helpSearchInput = help.getSearchInput(vim.window)
637 if helpSearchInput
638 helpSearchInput.select()
639 return
640
641 helper_mark_last_scroll_position(vim)
642 findBar = vim.window.gBrowser.getFindBar()
643
644 mode = if linksOnly then findBar.FIND_LINKS else findBar.FIND_NORMAL
645 findBar.startFind(mode)
646 utils.focusElement(findBar._findField, {select: true})
647
648 return if linksOnly
649 return unless highlightButton = findBar.getElement('highlight')
650 if highlightButton.checked != highlight
651 highlightButton.click()
652
653 commands.find = helper_find.bind(null, {highlight: false})
654
655 commands.find_highlight_all = helper_find.bind(null, {highlight: true})
656
657 commands.find_links_only = helper_find.bind(null, {linksOnly: true})
658
659 helper_find_again = (direction, {vim}) ->
660 findBar = vim.window.gBrowser.getFindBar()
661 if findStorage.lastSearchString.length == 0
662 vim.notify(translate('notification.find_again.none'))
663 return
664 helper_mark_last_scroll_position(vim)
665 findBar._findField.value = findStorage.lastSearchString
666 findBar.onFindAgainCommand(direction)
667 message = findBar._findStatusDesc.textContent
668 vim.notify(message) if message
669
670 commands.find_next = helper_find_again.bind(null, false)
671
672 commands.find_previous = helper_find_again.bind(null, true)
673
674
675
676 commands.window_new = ({vim}) ->
677 vim.window.OpenBrowserWindow()
678
679 commands.window_new_private = ({vim}) ->
680 vim.window.OpenBrowserWindow({private: true})
681
682 commands.enter_mode_ignore = ({vim}) ->
683 vim.enterMode('ignore', {type: 'explicit'})
684
685 # Quote next keypress (pass it through to the page).
686 commands.quote = ({vim, count = 1}) ->
687 vim.enterMode('ignore', {type: 'explicit', count})
688
689 commands.enter_reader_view = ({vim}) ->
690 button = vim.window.document.getElementById('reader-mode-button')
691 if not button?.hidden
692 button.click()
693 else
694 vim.notify(translate('notification.enter_reader_view.none'))
695
696 commands.reload_config_file = ({vim}) ->
697 vim._parent.emit('shutdown')
698 config.load(vim._parent, (status) -> switch status
699 when null
700 vim.notify(translate('notification.reload_config_file.none'))
701 when true
702 vim.notify(translate('notification.reload_config_file.success'))
703 else
704 vim.notify(translate('notification.reload_config_file.failure'))
705 )
706
707 commands.help = ({vim}) ->
708 help.injectHelp(vim.window, vim._parent)
709
710 commands.dev = ({vim}) ->
711 vim.window.DeveloperToolbar.show(true) # `true` to focus.
712
713 commands.esc = ({vim}) ->
714 vim._run('esc')
715 utils.blurActiveBrowserElement(vim)
716 vim.window.DeveloperToolbar.hide()
717 vim.window.gBrowser.getFindBar().close()
718 hints.removeHints(vim.window) # Better safe than sorry.
719
720 unless help.getSearchInput(vim.window)?.getAttribute('focused')
721 help.removeHelp(vim.window)
722
723
724
725 module.exports = {
726 commands
727 findStorage
728 }
Imprint / Impressum