1 { classes: Cc, interfaces: Ci, utils: Cu } = Components
3 utils = require 'utils'
4 hints = require 'hints'
10 , getFirefoxPref } = require 'prefs'
12 # Opens developer toolbar (Default shotrcut: Shift-F2)
13 command_dev = (vim) ->
14 if chromeWindow = utils.getRootWindow vim.window
15 chromeWindow.DeveloperToolbar.show(true)
16 chromeWindow.DeveloperToolbar.focus()
18 # Focus the Address Bar
20 if chromeWindow = utils.getRootWindow vim.window
21 chromeWindow.focusAndSelectUrlBar()
23 # Navigate to the address that is currently stored in the system clipboard
25 url = utils.readFromClipboard(vim.window)
27 if not utils.isURL(url) and submission = utils.browserSearchSubmission url
28 url = submission.uri.spec
29 postData = submission.postData
31 if chromeWindow = utils.getRootWindow vim.window
32 chromeWindow.gBrowser.loadURIWithFlags url, null, null, null, postData
34 # Open new tab and navigate to the address that is currently stored in the system clipboard
36 url = utils.readFromClipboard(vim.window)
38 if not utils.isURL(url) and submission = utils.browserSearchSubmission url
39 url = submission.uri.spec
40 postData = submission.postData
42 if chromeWindow = utils.getRootWindow vim.window
43 chromeWindow.gBrowser.selectedTab = chromeWindow.gBrowser.addTab url, null, null, postData, null, false
45 # Open new tab and focus the address bar
47 if chromeWindow = utils.getRootWindow vim.window
48 if gBrowser = chromeWindow.gBrowser
49 # Get the default url for the new tab
50 newtab_url = getFirefoxPref 'browser.newtab.url'
51 gBrowser.selectedTab = gBrowser.addTab newtab_url
52 # Focus the address bar
53 chromeWindow.focusAndSelectUrlBar()
55 # Copy current URL to the clipboard
57 markers = hints.injectHints vim.window.document
58 if markers?.length > 0
59 # This callback will be called with the selected marker as argument
61 if url = marker.element.href
62 utils.writeToClipboard vim.window, url
64 vim.enterHintsMode(markers, cb)
66 # Copy current URL to the clipboard
68 utils.writeToClipboard vim.window, vim.window.location.toString()
70 # Reload the page, possibly from cache
72 vim.window.location.reload(false)
74 # Reload the page from the server
76 vim.window.location.reload(true)
78 # Reload the page, possibly from cache
80 if rootWindow = utils.getRootWindow vim.window
81 if tabs = rootWindow.gBrowser.tabContainer
82 for i in [0...tabs.itemCount]
83 window = tabs.getItemAtIndex(i).linkedBrowser.contentWindow
84 window.location.reload(false)
86 # Reload the page from the server
88 if rootWindow = utils.getRootWindow vim.window
89 if tabs = rootWindow.gBrowser.tabContainer
90 for i in [0...tabs.itemCount]
91 window = tabs.getItemAtIndex(i).linkedBrowser.contentWindow
92 window.location.reload(true)
94 # Scroll to the top of the page
96 vim.window.scrollTo(0, 0)
98 # Scroll to the bottom of the page
100 if document = vim.window.document
101 # Workaround the pages where body isn't the scrollable element.
102 # In this case we try to scroll 100k pixels
103 vim.window.scrollTo(0, Math.max(document.body.scrollHeight, 100000))
106 command_j_ce = (vim) ->
107 utils.smoothScroll vim.window, 0, (getPref 'scroll_step'), getPref 'scroll_time'
110 command_k_cy = (vim) ->
111 utils.smoothScroll vim.window, 0, -(getPref 'scroll_step'), getPref 'scroll_time'
115 utils.smoothScroll vim.window, -(getPref 'scroll_step'), 0, getPref 'scroll_time'
119 utils.smoothScroll vim.window, (getPref 'scroll_step'), 0, getPref 'scroll_time'
121 # Scroll down half a page
123 utils.smoothScroll vim.window, 0, vim.window.innerHeight / 2, getPref 'scroll_time'
125 # Scroll up half a page
127 utils.smoothScroll vim.window, 0, -vim.window.innerHeight / 2, getPref 'scroll_time'
129 # Scroll down full a page
130 command_cf = (vim) ->
131 step = (vim.window.innerHeight - (getPref 'scroll_step'))
132 utils.smoothScroll vim.window, 0, step, getPref 'scroll_time'
134 # Scroll up full a page
135 command_cb = (vim) ->
136 step = - (vim.window.innerHeight - (getPref 'scroll_step'))
137 utils.smoothScroll vim.window, 0, step, getPref 'scroll_time'
139 # Activate previous tab
140 command_J_gT = (vim) ->
141 if rootWindow = utils.getRootWindow vim.window
142 rootWindow.gBrowser.tabContainer.advanceSelectedTab(-1, true);
145 command_K_gt = (vim) ->
146 if rootWindow = utils.getRootWindow vim.window
147 rootWindow.gBrowser.tabContainer.advanceSelectedTab(1, true);
149 command_gh = (vim) ->
150 homepage_url = getFirefoxPref 'browser.startup.homepage'
151 vim.window.location.assign homepage_url
153 # Go to the first tab
154 command_gH_g0 = (vim) ->
155 if rootWindow = utils.getRootWindow vim.window
156 rootWindow.gBrowser.tabContainer.selectedIndex = 0;
159 command_gL_g$ = (vim) ->
160 if rootWindow = utils.getRootWindow vim.window
161 itemCount = rootWindow.gBrowser.tabContainer.itemCount;
162 rootWindow.gBrowser.tabContainer.selectedIndex = itemCount - 1;
166 vim.window.history.back()
168 # Go forward in history
170 vim.window.history.forward()
174 if rootWindow = utils.getRootWindow vim.window
175 unless rootWindow.gBrowser.selectedTab.pinned
176 rootWindow.gBrowser.removeCurrentTab()
178 # Restore last closed tab
180 if rootWindow = utils.getRootWindow vim.window
181 ss = utils.getSessionStore()
182 if ss and ss.getClosedTabCount(rootWindow) > 0
183 ss.undoCloseTab rootWindow, 0
185 # Follow links with hint markers
187 if document = vim.window.document
188 markers = hints.injectHints document
189 if markers?.length > 0
190 # This callback will be called with the selected marker as argument
192 marker.element.focus()
193 utils.simulateClick marker.element
195 vim.enterHintsMode markers, cb
197 # Follow links in a new Tab with hint markers
199 markers = hints.injectHints vim.window.document
200 if markers?.length > 0
201 # This callback will be called with the selected marker as argument
203 marker.element.focus()
204 utils.simulateClick marker.element, { metaKey: true, ctrlKey: true }
206 vim.enterHintsMode markers, cb
208 # Move current tab to the left
209 command_cJ = (vim) ->
210 if gBrowser = utils.getRootWindow(vim.window)?.gBrowser
211 if tab = gBrowser.selectedTab
212 index = gBrowser.tabContainer.selectedIndex
213 total = gBrowser.tabContainer.itemCount
215 # `total` is added to deal with negative offset
216 gBrowser.moveTabTo tab, (total + index - 1) % total
218 # Move current tab to the right
219 command_cK = (vim) ->
220 if gBrowser = utils.getRootWindow(vim.window)?.gBrowser
221 if tab = gBrowser.selectedTab
222 index = gBrowser.tabContainer.selectedIndex
223 total = gBrowser.tabContainer.itemCount
225 gBrowser.moveTabTo tab, (index + 1) % total
227 # Display the Help Dialog
228 command_help = (vim) ->
229 help.injectHelp vim.window.document, commandsHelp
231 # Switch into find mode
232 command_find = (vim) ->
233 find.injectFind vim.window.document
235 # Search for the last pattern
237 if vim.findStr.length > 0
238 if rootWindow = utils.getRootWindow vim.window
239 console.expand rootWindow.gBrowser.fastFind
240 rootWindow.gBrowser.fastFind.findAgain(false, false)
241 #if not find.find vim.window, vim.findStr, false
242 #find.flashFind vim.window.document, "#{ vim.findStr } (Not Found)"
244 # Search for the last pattern backwards
246 if vim.findStr.length > 0
247 if rootWindow = utils.getRootWindow vim.window
248 rootWindow.gBrowser.fastFind.findAgain(true, false)
249 #if not find.find vim.window, vim.findStr, true
250 #find.flashFind vim.window.document, "#{ vim.findStr } (Not Found)"
252 # Close the Help dialog and cancel the pending hint marker action
253 command_Esc = (vim) ->
254 # Blur active element if it's editable. Other elements
255 # aren't blurred - we don't want to interfere with
256 # the browser too much
257 activeElement = vim.window.document.activeElement
258 if utils.isElementEditable activeElement
262 find.removeFind vim.window.document
265 hints.removeHints vim.window.document
268 help.removeHelp vim.window.document
270 # Finally enter normal mode
271 vim.enterNormalMode()
273 if not getPref('leave_dt_on_esc')
274 if chromeWindow = utils.getRootWindow vim.window
275 chromeWindow.DeveloperToolbar.hide()
279 'o': [ command_o, _('help_command_o') ]
280 'p': [ command_p, _('help_command_p') ]
281 'P': [ command_P, _('help_command_P') ]
282 'y,f': [ command_yf, _('help_command_yf') ]
283 'y,y': [ command_yy, _('help_command_yy') ]
284 'r': [ command_r, _('help_command_r') ]
285 'R': [ command_R, _('help_command_R') ]
286 'a,r': [ command_ar, _('help_command_ar') ]
287 'a,R': [ command_aR, _('help_command_aR') ]
289 'g,g': [ command_gg , _('help_command_gg') ]
290 'G': [ command_G, _('help_command_G') ]
291 'j|c-e': [ command_j_ce, _('help_command_j_ce') ]
292 'k|c-y': [ command_k_cy, _('help_command_k_cy') ]
293 'h': [ command_h, _('help_command_h') ]
294 'l': [ command_l , _('help_command_l') ]
295 # Can't use c-u/c-d because c-u is widely used for viewing sources
296 'd': [ command_d, _('help_command_d') ]
297 'u': [ command_u, _('help_command_u') ]
298 'c-f': [ command_cf, _('help_command_cf') ]
299 'c-b': [ command_cb, _('help_command_cb') ]
301 't': [ command_t, _('help_command_t') ]
302 'J|g,T': [ command_J_gT, _('help_command_J_gT') ]
303 'K|g,t': [ command_K_gt, _('help_command_K_gt') ]
304 'c-J': [ command_cJ, _('help_command_cJ') ]
305 'c-K': [ command_cK, _('help_command_cK') ]
306 'g,h': [ command_gh, _('help_command_gh') ]
307 "g,H|g,\^": [ command_gH_g0, _('help_command_gH_g0') ]
308 'g,L|g,$': [ command_gL_g$, _('help_command_gL_g$') ]
309 'x': [ command_x, _('help_command_x') ]
310 'X': [ command_X, _('help_command_X') ]
312 'f': [ command_f, _('help_command_f') ]
313 'F': [ command_F, _('help_command_F') ]
314 'H': [ command_H, _('help_command_H') ]
315 'L': [ command_L, _('help_command_L') ]
317 # `.` is added to find command mapping to hack around Russian keyboard layout
318 '\.|/': [ command_find, _('help_command_find') ]
319 'n': [ command_n, _('help_command_n') ]
320 'N': [ command_N, _('help_command_N') ]
321 # `>` is added to help command mapping to hack around Russian keyboard layout
322 # See key-utils.coffee for more info
323 '?|>': [ command_help, _('help_command_help') ]
324 'Esc': [ command_Esc, _('help_command_Esc') ]
325 ':': [ command_dev, _('help_command_dev') ]
327 # Merge groups and split command pipes into individual commands
328 commands = do (commandGroups) ->
330 for group, commandsList of commandGroups
331 for keys, command of commandsList
332 for key in keys.split '|'
333 newCommands[key] = command[0]
337 # Extract the help text from the commands preserving groups formation
338 commandsHelp = do (commandGroups) ->
340 for group, commandsList of commandGroups
342 for keys, command of commandsList
343 helpGroup[keys] = command[1]
345 helpStrings[group] = helpGroup
348 # Called in hints mode. Will process the char, update and hide/show markers
349 hintCharHandler = (vim, keyStr, charCode) ->
350 if keyStr and charCode > 0
351 # Get char and escape it to avoid problems with String.search
352 key = regexpEscape keyStr
354 # First do a pre match - count how many markers will match with the new character entered
355 if vim.markers.reduce ((v, marker) -> v or marker.willMatch key), false
356 for marker in vim.markers
357 marker.matchHintChar key
359 if marker.isMatched()
361 hints.removeHints vim.window.document
362 vim.enterNormalMode()
365 # Called in find mode. Will process charCode, update find, or close the
366 findCharHandler = (vim, keyStr, charCode) ->
370 find.removeFind vim.window.document
371 vim.enterNormalMode()
373 if keyStr and keyStr.match(/.*Return/)
374 return toNormalMode()
375 else if keyStr == 'Backspace'
376 # Delete last available character from the query string
377 if vim.findStr.length > 0
378 vim.findStr = vim.findStr.substr(0, vim.findStr.length - 1)
379 # Leave Find Mode the query string is already empty
381 return toNormalMode()
383 vim.findStr += String.fromCharCode(charCode)
387 # Update the interface string
389 # Clear selection to avoid jumping between matching search results
390 vim.window.getSelection().removeAllRanges()
392 # Search only if the query string isn't emply.
393 # Otherwise it will pop up Find dialog
394 rootWindow = utils.getRootWindow vim.window
395 if rootWindow?.gBrowser.fastFind.find vim.findStr, false
396 find.setFindStr vim.window.document, vim.findStr
398 find.setFindStr vim.window.document, "#{ vim.findStr } (Not Found)"
401 exports.hintCharHandler = hintCharHandler
402 exports.findCharHandler = findCharHandler
403 exports.commands = commands
404 exports.commandsHelp = commandsHelp