]> git.gir.st - VimFx.git/blob - extension/packages/commands.coffee
Closes #95. Search will now focus the element that contains the matching text
[VimFx.git] / extension / packages / commands.coffee
1 { classes: Cc, interfaces: Ci, utils: Cu } = Components
2
3 utils = require 'utils'
4 hints = require 'hints'
5 help = require 'help'
6 find = require 'find'
7
8 { getPref
9 , setPref
10 , getFirefoxPref } = require 'prefs'
11
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()
17
18 # Focus the Address Bar
19 command_o = (vim) ->
20 if chromeWindow = utils.getRootWindow vim.window
21 chromeWindow.focusAndSelectUrlBar()
22
23 # Navigate to the address that is currently stored in the system clipboard
24 command_p = (vim) ->
25 url = utils.readFromClipboard(vim.window)
26 postData = null
27 if not utils.isURL(url) and submission = utils.browserSearchSubmission url
28 url = submission.uri.spec
29 postData = submission.postData
30
31 if chromeWindow = utils.getRootWindow vim.window
32 chromeWindow.gBrowser.loadURIWithFlags url, null, null, null, postData
33
34 # Open new tab and navigate to the address that is currently stored in the system clipboard
35 command_P = (vim) ->
36 url = utils.readFromClipboard(vim.window)
37 postData = null
38 if not utils.isURL(url) and submission = utils.browserSearchSubmission url
39 url = submission.uri.spec
40 postData = submission.postData
41
42 if chromeWindow = utils.getRootWindow vim.window
43 chromeWindow.gBrowser.selectedTab = chromeWindow.gBrowser.addTab url, null, null, postData, null, false
44
45 # Open new tab and focus the address bar
46 command_t = (vim) ->
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()
54
55 # Copy element URL to the clipboard
56 command_yf = (vim) ->
57 markers = hints.injectHints vim.window.document
58 if markers?.length > 0
59 cb = (marker) ->
60 if url = marker.element.href
61 marker.element.focus()
62 utils.writeToClipboard vim.window, url
63 else if utils.isTextInputElement marker.element
64 utils.writeToClipboard vim.window, marker.element.value
65
66 vim.enterHintsMode(markers, cb)
67
68 # Focus element
69 command_vf = (vim) ->
70 markers = hints.injectHints vim.window.document
71 if markers?.length > 0
72 vim.enterHintsMode(markers, ((marker) -> marker.element.focus()))
73
74 # Copy current URL to the clipboard
75 command_yy = (vim) ->
76 utils.writeToClipboard vim.window, vim.window.location.toString()
77
78 # Reload the page, possibly from cache
79 command_r = (vim) ->
80 vim.window.location.reload(false)
81
82 # Reload the page from the server
83 command_R = (vim) ->
84 vim.window.location.reload(true)
85
86 # Reload the page, possibly from cache
87 command_ar = (vim) ->
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(false)
93
94 # Reload the page from the server
95 command_aR = (vim) ->
96 if rootWindow = utils.getRootWindow vim.window
97 if tabs = rootWindow.gBrowser.tabContainer
98 for i in [0...tabs.itemCount]
99 window = tabs.getItemAtIndex(i).linkedBrowser.contentWindow
100 window.location.reload(true)
101
102 # Scroll to the top of the page
103 command_gg = (vim) ->
104 vim.window.scrollTo(0, 0)
105
106 # Scroll to the bottom of the page
107 command_G = (vim) ->
108 if document = vim.window.document
109 # Workaround the pages where body isn't the scrollable element.
110 # In this case we try to scroll 100k pixels
111 vim.window.scrollTo(0, Math.max(document.body.scrollHeight, 100000))
112
113 # Scroll down a bit
114 command_j_ce = (vim) ->
115 utils.smoothScroll vim.window, 0, (getPref 'scroll_step'), getPref 'scroll_time'
116
117 # Scroll up a bit
118 command_k_cy = (vim) ->
119 utils.smoothScroll vim.window, 0, -(getPref 'scroll_step'), getPref 'scroll_time'
120
121 # Scroll left a bit
122 command_h = (vim) ->
123 utils.smoothScroll vim.window, -(getPref 'scroll_step'), 0, getPref 'scroll_time'
124
125 # Scroll right a bit
126 command_l = (vim) ->
127 utils.smoothScroll vim.window, (getPref 'scroll_step'), 0, getPref 'scroll_time'
128
129 # Scroll down half a page
130 command_d = (vim) ->
131 utils.smoothScroll vim.window, 0, vim.window.innerHeight / 2, getPref 'scroll_time'
132
133 # Scroll up half a page
134 command_u = (vim) ->
135 utils.smoothScroll vim.window, 0, -vim.window.innerHeight / 2, getPref 'scroll_time'
136
137 # Scroll down full a page
138 command_cf = (vim) ->
139 step = (vim.window.innerHeight - (getPref 'scroll_step'))
140 utils.smoothScroll vim.window, 0, step, getPref 'scroll_time'
141
142 # Scroll up full a page
143 command_cb = (vim) ->
144 step = - (vim.window.innerHeight - (getPref 'scroll_step'))
145 utils.smoothScroll vim.window, 0, step, getPref 'scroll_time'
146
147 # Activate previous tab
148 command_J_gT = (vim) ->
149 if rootWindow = utils.getRootWindow vim.window
150 rootWindow.gBrowser.tabContainer.advanceSelectedTab(-1, true);
151
152 # Activate next tab
153 command_K_gt = (vim) ->
154 if rootWindow = utils.getRootWindow vim.window
155 rootWindow.gBrowser.tabContainer.advanceSelectedTab(1, true);
156
157 command_gh = (vim) ->
158 homepage_url = getFirefoxPref 'browser.startup.homepage'
159 vim.window.location.assign homepage_url
160
161 # Go to the first tab
162 command_gH_g0 = (vim) ->
163 if rootWindow = utils.getRootWindow vim.window
164 rootWindow.gBrowser.tabContainer.selectedIndex = 0;
165
166 # Go to the last tab
167 command_gL_g$ = (vim) ->
168 if rootWindow = utils.getRootWindow vim.window
169 itemCount = rootWindow.gBrowser.tabContainer.itemCount;
170 rootWindow.gBrowser.tabContainer.selectedIndex = itemCount - 1;
171
172 # Go back in history
173 command_H = (vim) ->
174 vim.window.history.back()
175
176 # Go forward in history
177 command_L = (vim) ->
178 vim.window.history.forward()
179
180 # Close current tab
181 command_x = (vim) ->
182 if rootWindow = utils.getRootWindow vim.window
183 unless rootWindow.gBrowser.selectedTab.pinned
184 rootWindow.gBrowser.removeCurrentTab()
185
186 # Restore last closed tab
187 command_X = (vim) ->
188 if rootWindow = utils.getRootWindow vim.window
189 ss = utils.getSessionStore()
190 if ss and ss.getClosedTabCount(rootWindow) > 0
191 ss.undoCloseTab rootWindow, 0
192
193 # Follow links with hint markers
194 command_f = (vim) ->
195 if document = vim.window.document
196 markers = hints.injectHints document
197 if markers?.length > 0
198 # This callback will be called with the selected marker as argument
199 cb = (marker) ->
200 marker.element.focus()
201 utils.simulateClick marker.element
202
203 vim.enterHintsMode markers, cb
204
205 # Follow links in a new Tab with hint markers
206 command_F = (vim) ->
207 markers = hints.injectHints vim.window.document
208 if markers?.length > 0
209 # This callback will be called with the selected marker as argument
210 cb = (marker) ->
211 marker.element.focus()
212 utils.simulateClick marker.element, { metaKey: true, ctrlKey: true }
213
214 vim.enterHintsMode markers, cb
215
216 # Move current tab to the left
217 command_cJ = (vim) ->
218 if gBrowser = utils.getRootWindow(vim.window)?.gBrowser
219 if tab = gBrowser.selectedTab
220 index = gBrowser.tabContainer.selectedIndex
221 total = gBrowser.tabContainer.itemCount
222
223 # `total` is added to deal with negative offset
224 gBrowser.moveTabTo tab, (total + index - 1) % total
225
226 # Move current tab to the right
227 command_cK = (vim) ->
228 if gBrowser = utils.getRootWindow(vim.window)?.gBrowser
229 if tab = gBrowser.selectedTab
230 index = gBrowser.tabContainer.selectedIndex
231 total = gBrowser.tabContainer.itemCount
232
233 gBrowser.moveTabTo tab, (index + 1) % total
234
235 # Display the Help Dialog
236 command_help = (vim) ->
237 help.injectHelp vim.window.document, commandsHelp
238
239 # Switch into find mode
240 command_find = (vim) ->
241 find.injectFind vim.window.document, (findStr, direction) ->
242 # Reset region and find string if new find stirng has arrived
243 if vim.findStr != findStr
244 [vim.findStr, vim.findRng] = [findStr, null]
245 # Perform forward find and store found region
246 return vim.findRng = find.find vim.window, vim.findStr, vim.findRng, find.DIRECTION_FORWARDS
247
248 # Switch into find mode with highlighting
249 command_find_hl = (vim) ->
250 find.injectFind vim.window.document, (findStr) ->
251 # Reset region and find string if new find stirng has arrived
252 return find.highlight vim.window, findStr
253
254 # Search for the last pattern
255 command_n = (vim) ->
256 if vim.findStr.length > 0
257 vim.findRng = find.find vim.window, vim.findStr, vim.findRng, find.DIRECTION_FORWARDS, true
258
259 # Search for the last pattern backwards
260 command_N = (vim) ->
261 if vim.findStr.length > 0
262 vim.findRng = find.find vim.window, vim.findStr, vim.findRng, find.DIRECTION_BACKWARDS, true
263
264 # Close the Help dialog and cancel the pending hint marker action
265 command_Esc = (vim) ->
266 # Blur active element if it's editable. Other elements
267 # aren't blurred - we don't want to interfere with
268 # the browser too much
269 activeElement = vim.window.document.activeElement
270 if utils.isElementEditable activeElement
271 activeElement.blur()
272
273 #Remove Find input
274 find.removeFind vim.window.document
275
276 # Remove hints
277 hints.removeHints vim.window.document
278
279 # Hide help dialog
280 help.removeHelp vim.window.document
281
282 # Finally enter normal mode
283 vim.enterNormalMode()
284
285 if not getPref('leave_dt_on_esc')
286 if chromeWindow = utils.getRootWindow vim.window
287 chromeWindow.DeveloperToolbar.hide()
288
289 commandGroups =
290 'urls':
291 'o': [ command_o, _('help_command_o') ]
292 'p': [ command_p, _('help_command_p') ]
293 'P': [ command_P, _('help_command_P') ]
294 'y,f': [ command_yf, _('help_command_yf') ]
295 'v,f': [ command_vf, _('help_command_vf') ]
296 'y,y': [ command_yy, _('help_command_yy') ]
297 'r': [ command_r, _('help_command_r') ]
298 'R': [ command_R, _('help_command_R') ]
299 'a,r': [ command_ar, _('help_command_ar') ]
300 'a,R': [ command_aR, _('help_command_aR') ]
301 'nav':
302 'g,g': [ command_gg , _('help_command_gg') ]
303 'G': [ command_G, _('help_command_G') ]
304 'j|c-e': [ command_j_ce, _('help_command_j_ce') ]
305 'k|c-y': [ command_k_cy, _('help_command_k_cy') ]
306 'h': [ command_h, _('help_command_h') ]
307 'l': [ command_l , _('help_command_l') ]
308 # Can't use c-u/c-d because c-u is widely used for viewing sources
309 'd': [ command_d, _('help_command_d') ]
310 'u': [ command_u, _('help_command_u') ]
311 'c-f': [ command_cf, _('help_command_cf') ]
312 'c-b': [ command_cb, _('help_command_cb') ]
313 'tabs':
314 't': [ command_t, _('help_command_t') ]
315 'J|g,T': [ command_J_gT, _('help_command_J_gT') ]
316 'K|g,t': [ command_K_gt, _('help_command_K_gt') ]
317 'c-J': [ command_cJ, _('help_command_cJ') ]
318 'c-K': [ command_cK, _('help_command_cK') ]
319 'g,h': [ command_gh, _('help_command_gh') ]
320 "g,H|g,\^": [ command_gH_g0, _('help_command_gH_g0') ]
321 'g,L|g,$': [ command_gL_g$, _('help_command_gL_g$') ]
322 'x': [ command_x, _('help_command_x') ]
323 'X': [ command_X, _('help_command_X') ]
324 'browse':
325 'f': [ command_f, _('help_command_f') ]
326 'F': [ command_F, _('help_command_F') ]
327 'H': [ command_H, _('help_command_H') ]
328 'L': [ command_L, _('help_command_L') ]
329 'misc':
330 # `.` is added to find command mapping to hack around Russian keyboard layout
331 '\.|/': [ command_find, _('help_command_find') ]
332 'a,\.|a,/': [ command_find_hl,_('help_command_find_hl') ]
333 'n': [ command_n, _('help_command_n') ]
334 'N': [ command_N, _('help_command_N') ]
335 # `>` is added to help command mapping to hack around Russian keyboard layout
336 # See key-utils.coffee for more info
337 '?|>': [ command_help, _('help_command_help') ]
338 'Esc': [ command_Esc, _('help_command_Esc') ]
339 ':': [ command_dev, _('help_command_dev') ]
340
341 # Merge groups and split command pipes into individual commands
342 commands = do (commandGroups) ->
343 newCommands = {}
344 for group, commandsList of commandGroups
345 for keys, command of commandsList
346 for key in keys.split '|'
347 newCommands[key] = command[0]
348
349 return newCommands
350
351 # Extract the help text from the commands preserving groups formation
352 commandsHelp = do (commandGroups) ->
353 helpStrings = {}
354 for group, commandsList of commandGroups
355 helpGroup = {}
356 for keys, command of commandsList
357 helpGroup[keys] = command[1]
358
359 helpStrings[group] = helpGroup
360 return helpStrings
361
362 # Called in hints mode. Will process the char, update and hide/show markers
363 hintCharHandler = (vim, keyStr, charCode) ->
364 if keyStr and charCode > 0
365 # Get char and escape it to avoid problems with String.search
366 key = regexpEscape keyStr
367
368 # First do a pre match - count how many markers will match with the new character entered
369 if vim.markers.reduce ((v, marker) -> v or marker.willMatch key), false
370 for marker in vim.markers
371 marker.matchHintChar key
372
373 if marker.isMatched()
374 vim.cb marker
375 hints.removeHints vim.window.document
376 vim.enterNormalMode()
377 break
378
379 exports.hintCharHandler = hintCharHandler
380 exports.commands = commands
381 exports.commandsHelp = commandsHelp
Imprint / Impressum