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