From 62e7c92cae0cb29bbdf194c56454dc842d5ea852 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Thu, 6 Dec 2012 06:37:56 +0200 Subject: [PATCH 01/16] Closes #35. Replaced innerHtml with Ci.nsIParserUtils --- extension/packages/help.coffee | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/extension/packages/help.coffee b/extension/packages/help.coffee index 2f7da4f..cf2337a 100644 --- a/extension/packages/help.coffee +++ b/extension/packages/help.coffee @@ -10,7 +10,7 @@ showHelp = (document, commandsHelp) -> div.id = CONTAINER_ID div.className = 'VimFxReset' - div.innerHTML = helpDialogHtml(commandsHelp) + div.appendChild parseHTML(document, helpDialogHtml(commandsHelp)) body.appendChild div @@ -21,6 +21,11 @@ showHelp = (document, commandsHelp) -> hideHelp(document) button.addEventListener 'click', clickHandler, false +parseHTML = (doc, html) -> + parser = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils) + flags = parser.SanitizerAllowStyle + return parser.parseFragment(html, flags, false, null, doc.documentElement) + hideHelp = (document) -> if div = document.getElementById CONTAINER_ID div.parentNode.removeChild div -- 2.39.3 From cabea425ae0b4f044a192e6e778b0b0ffc6f9397 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Thu, 6 Dec 2012 07:13:00 +0200 Subject: [PATCH 02/16] Closes #34. Closes #18. Prefs will now be stored under extensions.VimFx. Added a routing to transfer preferences from extension.VimFx. to extensions.VimFx. un upgrade to version greater than 0.3.3 The toolbar button won't reappear after being removed from the toolbar --- extension/bootstrap.coffee | 9 ++++++--- extension/options.xul | 8 ++++---- extension/packages/prefs.coffee | 24 +++++++++++++++++++++++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/extension/bootstrap.coffee b/extension/bootstrap.coffee index 2016dfb..73126a6 100644 --- a/extension/bootstrap.coffee +++ b/extension/bootstrap.coffee @@ -54,18 +54,21 @@ do (global = this) -> { loadCss } = require 'utils' { addEventListeners } = require 'events' { getPref - , installPrefObserver } = require 'prefs' + , installPrefObserver + , transferPrefs } = require 'prefs' { setButtonInstallPosition , addToolbarButton } = require 'button' # Firefox will call this method on startup/enabling global.startup = (data, reason) -> - - if reason = ADDON_INSTALL + if reason == ADDON_INSTALL # Position the toolbar button right before the default Bookmarks button # If Bookmarks button is hidden - then VimFx button will be appended to the toolbar setButtonInstallPosition 'nav-bar', 'bookmarks-menu-button-container' + else if reason == ADDON_UPGRADE + if data["version"] > "0.3.3" + transferPrefs "extension.VimFx.", "extensions.VimFx." loadCss 'style' watchWindows addEventListeners, 'navigator:browser' diff --git a/extension/options.xul b/extension/options.xul index 0e69d26..c04ea45 100644 --- a/extension/options.xul +++ b/extension/options.xul @@ -3,13 +3,13 @@ - - - - + diff --git a/extension/packages/prefs.coffee b/extension/packages/prefs.coffee index 23a961e..b39c200 100644 --- a/extension/packages/prefs.coffee +++ b/extension/packages/prefs.coffee @@ -1,6 +1,6 @@ { classes: Cc, interfaces: Ci } = Components -PREF_BRANCH = "extension.VimFx."; +PREF_BRANCH = "extensions.VimFx."; # Default values for the preference # All used preferences should be mentioned here becuase @@ -72,6 +72,28 @@ getPref = (key) -> return PREFS[key] # Set preference value setPref = (key, value) -> setFFPref key, value +# Transfer all setting values from one branch to another +transferPrefs = (from, to) -> + fromBranch = Services.prefs.getBranch from + toBranch = Services.prefs.getBranch to + + count = {} + vals = fromBranch.getChildList("", count) + + for i in [0...count.value] + name = vals[i] + switch fromBranch.getPrefType name + when fromBranch.PREF_STRING + toBranch.setCharPref name, fromBranch.getCharPref name + when fromBranch.PREF_INT + toBranch.setIntPref name, fromBranch.getIntPref name + when fromBranch.PREF_BOOL + toBranch.setBoolPref name, fromBranch.getBoolPref name + + fromBranch.deleteBranch("") + + exports.getPref = getPref exports.setPref = setPref exports.installPrefObserver = installPrefObserver +exports.transferPrefs = transferPrefs -- 2.39.3 From 26443a6b2656e65caecde5eab62427515da5d2dd Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Thu, 6 Dec 2012 08:02:48 +0200 Subject: [PATCH 03/16] Closes #32. Added *mail.google.com* to the default black list --- extension/packages/prefs.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/packages/prefs.coffee b/extension/packages/prefs.coffee index b39c200..1d5ce6b 100644 --- a/extension/packages/prefs.coffee +++ b/extension/packages/prefs.coffee @@ -11,7 +11,7 @@ PREFS = disabled: false scroll_step: 60 scroll_time: 100 - black_list: '' + black_list: '*mail.google.com*' # Get Firefox preference value of type specified in `PREFS` getFFPref = do -> -- 2.39.3 From d67b2871be4f2b2ff8fb6f260c3f284d78cad3fc Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Thu, 6 Dec 2012 08:23:36 +0200 Subject: [PATCH 04/16] Closes #29. Marker hints are now sorter with respect to the underlying element area. Elements with larger are get shorter hints --- extension/packages/marker.coffee | 38 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/extension/packages/marker.coffee b/extension/packages/marker.coffee index db536c9..fa647cb 100644 --- a/extension/packages/marker.coffee +++ b/extension/packages/marker.coffee @@ -106,17 +106,31 @@ class Marker Marker.createMarkers = (document) -> hintChars = getPref('hint_chars').toLowerCase() - elementsSet = getMarkableElements(document) + set = getMarkableElements(document) markers = []; j = 0 - for i in [0...elementsSet.snapshotLength] by 1 - element = elementsSet.snapshotItem(i) - if rect = getElementRect element - hint = indexToHint(j++, hintChars) - marker = new Marker(element) - marker.setPosition rect - marker.setHint hint - markers.push(marker) + + elements = [] + for i in [0...set.snapshotLength] by 1 + e = set.snapshotItem(i) + if rect = getElementRect e + elements.push [e, rect] + + elements.sort ([e1, r1], [e2, r2]) -> + if r1.area > r2.area + return -1 + else if r1.area < r2.area + return 1 + else + return 0 + + for [element, rect] in elements + console.log element.text, rect.height * rect.width, rect.area + hint = indexToHint(j++, hintChars) + marker = new Marker(element) + marker.setPosition rect + marker.setHint hint + markers.push(marker) return markers @@ -188,9 +202,10 @@ getElementRect = (element) -> clientLeft = docElem.clientLeft || body.clientLeft || 0; scrollTop = window.pageYOffset || docElem.scrollTop; scrollLeft = window.pageXOffset || docElem.scrollLeft; - + + clientRect = element.getBoundingClientRect() rects = [rect for rect in element.getClientRects()] - rects.push element.getBoundingClientRect() + rects.push clientRect for rect in rects if isRectOk rect, window @@ -199,6 +214,7 @@ getElementRect = (element) -> left: rect.left + scrollLeft - clientLeft width: rect.width height: rect.height + area: clientRect.width * clientRect.height } # If the element has 0 dimentions then check what's inside. -- 2.39.3 From da284b1adf7efcc541b16ac34f55bf9e0444a366 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Thu, 6 Dec 2012 11:46:31 +0200 Subject: [PATCH 05/16] Closes 33. Now the container divs are appended directly to document.documentElement (html) This allows to avoid various edge cases (ex: body { position: relative; } --- extension/packages/help.coffee | 12 ++++++------ extension/packages/hints.coffee | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/extension/packages/help.coffee b/extension/packages/help.coffee index cf2337a..52839e6 100644 --- a/extension/packages/help.coffee +++ b/extension/packages/help.coffee @@ -2,8 +2,12 @@ utils = require 'utils' CONTAINER_ID = 'VimFxHelpDialogContainer' +hideHelp = (document) -> + if div = document.getElementById CONTAINER_ID + div.parentNode.removeChild div + showHelp = (document, commandsHelp) -> - if body = document.body + if document.documentElement if div = document.getElementById CONTAINER_ID div.parentNode.removeChild div div = document.createElement 'div' @@ -12,7 +16,7 @@ showHelp = (document, commandsHelp) -> div.appendChild parseHTML(document, helpDialogHtml(commandsHelp)) - body.appendChild div + document.documentElement.appendChild div if button = document.getElementById('VimFxClose') clickHandler = (event) -> @@ -26,10 +30,6 @@ parseHTML = (doc, html) -> flags = parser.SanitizerAllowStyle return parser.parseFragment(html, flags, false, null, doc.documentElement) -hideHelp = (document) -> - if div = document.getElementById CONTAINER_ID - div.parentNode.removeChild div - td = (text, klass='') -> """#{ text }""" diff --git a/extension/packages/hints.coffee b/extension/packages/hints.coffee index 5cabd6b..7e4eb08 100644 --- a/extension/packages/hints.coffee +++ b/extension/packages/hints.coffee @@ -16,7 +16,7 @@ createHintsContainer = (document) -> injectHints = (document) -> removeHints document - if document instanceof HTMLDocument + if document instanceof HTMLDocument and document.documentElement markers = Marker.createMarkers document container = createHintsContainer document @@ -27,13 +27,13 @@ injectHints = (document) -> container.appendChild fragment - document.body.appendChild container + document.documentElement.appendChild container return markers removeHints = (document, markers) -> if container = getHintsContainer document - document.body.removeChild container + document.documentElement.removeChild container handleHintChar = (markers, char) -> -- 2.39.3 From ad6e9b15526f005518cd768e1475fe5c5dd668c9 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Sun, 9 Dec 2012 13:12:35 +0200 Subject: [PATCH 06/16] Closes #12. Implemented find with / and n/N --- extension/bootstrap.coffee | 5 + extension/locale/en/vimfx.properties | 11 +- extension/locale/ru/vimfx.properties | 10 +- extension/packages/button.coffee | 4 +- extension/packages/commands.coffee | 152 ++++++++++++++++++--------- extension/packages/events.coffee | 10 +- extension/packages/find.coffee | 63 +++++++++++ extension/packages/help.coffee | 17 ++- extension/packages/hints.coffee | 13 ++- extension/packages/key-utils.coffee | 10 +- extension/packages/marker.coffee | 17 +-- extension/packages/utils.coffee | 22 ++++ extension/packages/vim.coffee | 107 +++++++++++-------- extension/resources/style.css | 16 +++ 14 files changed, 320 insertions(+), 137 deletions(-) create mode 100644 extension/packages/find.coffee diff --git a/extension/bootstrap.coffee b/extension/bootstrap.coffee index 73126a6..e90e1ff 100644 --- a/extension/bootstrap.coffee +++ b/extension/bootstrap.coffee @@ -80,3 +80,8 @@ do (global = this) -> # Don't bother to clean up if the browser is shutting down if reason != APP_SHUTDOWN unload() + + global.install = (data, reason) -> + + global.uninstall = (data, reason) -> + diff --git a/extension/locale/en/vimfx.properties b/extension/locale/en/vimfx.properties index b24b3f1..6bbdbfc 100644 --- a/extension/locale/en/vimfx.properties +++ b/extension/locale/en/vimfx.properties @@ -11,7 +11,9 @@ help_command_P =Open new tab and navigate to the address in the clipboard help_command_yf =Copy link url to the clipboard help_command_yy =Copy current page link to the clipboard help_command_r =Reload current page -help_command_R =Reload current page and all the assets (js, css, etc.) +help_command_R =Reload current page and all assets (js, css, img) +help_command_ar =Reload pages in all tabs +help_command_aR =Reload pages in all tabs including assets (js, css, img) help_section_nav =Navigating the page help_command_gg =Scroll to the Top of the page @@ -22,8 +24,8 @@ help_command_h =Scroll Left help_command_l =Scroll Right help_command_d =Scroll half a Page Down help_command_u =Scroll half a Page Up -help_command_cf =Scroll a full Page Down -help_command_cb =Scroll a full Page Up +help_command_cf =Scroll full Page Down +help_command_cb =Scroll full Page Up help_section_tabs =Working with Tabs help_command_t =Open New Blank tab @@ -46,6 +48,9 @@ help_command_L =Go Forward in history help_section_misc =Misc help_command_help =Show Help Dialog help_command_Esc =Close this dialog and cancel hint markers +help_command_find =Enter Find mode +help_command_n =Go ot the next Find match +help_command_N =Go ot the previous Find match help=Help help_version=Version diff --git a/extension/locale/ru/vimfx.properties b/extension/locale/ru/vimfx.properties index 0d75b35..7fa2f4c 100644 --- a/extension/locale/ru/vimfx.properties +++ b/extension/locale/ru/vimfx.properties @@ -10,8 +10,10 @@ help_command_p =Перейти по адресу в буфере обмен help_command_P =Открыть новую вкладку и перейти по адресу в буфере обмена help_command_yf =Скопировать в буфер обмена адрес ссылки на сранице при помощи маркеров help_command_yy =Скопировать в буфер обмена адрес текцщей сраницы -help_command_r =Перезагрузить текущую страницу (возможно из кэша) -help_command_R =Перезагрузить текущую страницу и все ресурсы (js, css, и т.д.) +help_command_r =Перезагрузить текущую страницу +help_command_R =Перезагрузить текущую страницу и все ресурсы (js, css, img) +help_command_ar =Перезагрузить страницы во всех вкладках +help_command_aR =Перезагрузить страницы и ресурамы (js, css, img) во всех вкладках help_section_nav =Страница help_command_gg =Прокрутить к верху страницы @@ -46,12 +48,14 @@ help_command_L =Следующая страница help_section_misc =Разное help_command_help =Показать справку help_command_Esc =Закрыть справку или отменить действие с маркерами +help_command_find =Режим поиска +help_command_n =Перейти к следующему результату поиска +help_command_N =Перейти к предыдущему результату поиска help=Справка help_version=Версия help_enjoying=Расширение понравилось? help_feedback=Оставьте отзыв! - help_found_bug=Нашли ошибку? help_report_bug=Сообщите нам! diff --git a/extension/packages/button.coffee b/extension/packages/button.coffee index 1bb44fb..56e1728 100644 --- a/extension/packages/button.coffee +++ b/extension/packages/button.coffee @@ -1,7 +1,7 @@ { getPref , setPref } = require 'prefs' -{ showHelp } = require 'help' +{ injectHelp } = require 'help' { commandsHelp } = require 'commands' KEYSET_ID = 'vimfx-keyset' @@ -123,7 +123,7 @@ createMenupopup = (window) -> onHelpCommand = (event) -> if tabWindow = window.gBrowser.selectedTab.linkedBrowser.contentWindow - showHelp tabWindow.document, commandsHelp + injectHelp tabWindow.document, commandsHelp event.stopPropagation() diff --git a/extension/packages/commands.coffee b/extension/packages/commands.coffee index 62d87a4..df92599 100644 --- a/extension/packages/commands.coffee +++ b/extension/packages/commands.coffee @@ -1,16 +1,11 @@ { classes: Cc, interfaces: Ci, utils: Cu } = Components utils = require 'utils' -{ getPref } = require 'prefs' - -{ handleHintChar -, injectHints -, removeHints -} = require 'hints' +hints = require 'hints' +help = require 'help' +find = require 'find' -{ showHelp -, hideHelp -} = require 'help' +{ getPref } = require 'prefs' # Navigate to the address that is currently stored in the system clipboard command_p = (vim) -> @@ -34,14 +29,14 @@ command_t = (vim) -> # Copy current URL to the clipboard command_yf = (vim) -> - vim.markers = injectHints vim.window.document - if vim.markers.length > 0 + markers = hints.injectHints vim.window.document + if markers.length > 0 # This callback will be called with the selected marker as argument - vim.cb = (marker) -> + cb = (marker) -> if url = marker.element.href utils.writeToClipboard vim.window, url - vim.enterHintsMode() + vim.enterHintsMode(markers, cb) # Copy current URL to the clipboard command_yy = (vim) -> @@ -108,11 +103,13 @@ command_u = (vim) -> # Scroll down full a page command_cf = (vim) -> - vim.window.scrollByPages(1) + step = (vim.window.innerHeight - (getPref 'scroll_step')) + utils.smoothScroll vim.window, 0, step, getPref 'scroll_time' # Scroll up full a page command_cb = (vim) -> - vim.window.scrollByPages(-1) + step = - (vim.window.innerHeight - (getPref 'scroll_step')) + utils.smoothScroll vim.window, 0, step, getPref 'scroll_time' # Activate previous tab command_J_gT = (vim) -> @@ -158,25 +155,25 @@ command_X = (vim) -> # Follow links with hint markers command_f = (vim) -> if document = vim.window.document - vim.markers = injectHints document - if vim.markers.length > 0 + markers = hints.injectHints document + if markers.length > 0 # This callback will be called with the selected marker as argument - vim.cb = (marker) -> + cb = (marker) -> marker.element.focus() utils.simulateClick marker.element - vim.enterHintsMode() + vim.enterHintsMode markers, cb # Follow links in a new Tab with hint markers command_F = (vim) -> - vim.markers = injectHints vim.window.document - if vim.markers.length > 0 + markers = hints.injectHints vim.window.document + if markers.length > 0 # This callback will be called with the selected marker as argument - vim.cb = (marker) -> + cb = (marker) -> marker.element.focus() utils.simulateClick marker.element, { metaKey: true, ctrlKey: true } - vim.enterHintsMode() + vim.enterHintsMode markers, cb # Move current tab to the left command_cJ = (vim) -> @@ -199,7 +196,22 @@ command_cK = (vim) -> # Display the Help Dialog command_help = (vim) -> - showHelp vim.window.document, commandsHelp + help.injectHelp vim.window.document, commandsHelp + +# Switch into find mode +command_find = (vim) -> + vim.enterFindMode() + vim.findStr = "" + + find.injectFind vim.window.document + +# Search for the last pattern +command_n = (vim) -> + find.find vim.window, vim.findStr, false + +# Search for the last pattern backwards +command_N = (vim) -> + find.find vim.window, vim.findStr, true # Close the Help dialog and cancel the pending hint marker action command_Esc = (vim) -> @@ -210,10 +222,15 @@ command_Esc = (vim) -> if utils.isElementEditable activeElement activeElement.blur() + #Remove Find input + find.removeFind vim.window.document + # Remove hints - removeHints vim.window.document + hints.removeHints vim.window.document + # Hide help dialog - hideHelp vim.window.document + help.removeHelp vim.window.document + # Finally enter normal mode vim.enterNormalMode() @@ -234,21 +251,18 @@ commandGroups = 'k|c-y': [ command_k_cy, _('help_command_k_cy') ] 'h': [ command_h, _('help_command_h') ] 'l': [ command_l , _('help_command_l') ] - - # Can't use c-u/c-d because it's generally used for viewing sources + # Can't use c-u/c-d because it's widely used for viewing sources 'd': [ command_d, _('help_command_d') ] 'u': [ command_u, _('help_command_u') ] - - # Can't use c-f because it's generally used for viewing sources - #'c-f': [ command_cf, _('help_command_cf') ] - #'c-b': [ command_cb, _('help_command_cb') ] + 'c-f': [ command_cf, _('help_command_cf') ] + 'c-b': [ command_cb, _('help_command_cb') ] 'tabs': 't': [ command_t, _('help_command_t') ] 'J|g,T': [ command_J_gT, _('help_command_J_gT') ] 'K|g,t': [ command_K_gt, _('help_command_K_gt') ] 'c-J': [ command_cJ, _('help_command_cJ') ] 'c-K': [ command_cK, _('help_command_cK') ] - 'g,H|g,0': [ command_gH_g0, _('help_command_gH_g0') ] + "g,H|g,\^": [ command_gH_g0, _('help_command_gH_g0') ] 'g,L|g,$': [ command_gL_g$, _('help_command_gL_g$') ] 'x': [ command_x, _('help_command_x') ] 'X': [ command_X, _('help_command_X') ] @@ -258,6 +272,9 @@ commandGroups = 'H': [ command_H, _('help_command_H') ] 'L': [ command_L, _('help_command_L') ] 'misc': + '/': [ command_find, _('help_command_find') ] + 'n': [ command_n, _('help_command_n') ] + 'N': [ command_N, _('help_command_N') ] # `>` is added to help command mapping to hack around russian keyboard layout # See key-utils.coffee for more info '?|>': [ command_help, _('help_command_help') ] @@ -275,32 +292,71 @@ commands = do (commandGroups) -> # Extract the help text from the commands preserving groups formation commandsHelp = do (commandGroups) -> - help = {} + helpStrings = {} for group, commandsList of commandGroups helpGroup = {} for keys, command of commandsList key = keys.replace(/,/g, '').replace('|', ', ') helpGroup[key] = command[1] - help[group] = helpGroup - return help + helpStrings[group] = helpGroup + return helpStrings # Called in hints mode. Will process the char, update and hide/show markers -hintCharHandler = (vim, char) -> - # First count how many markers will match with the new character entered - preMatch = vim.markers.reduce ((v, marker) -> v + marker.willMatch char), 0 +hintCharHandler = (vim, keyStr, charCode) -> + if charCode > 0 + key = if keyStr == 'Backspace' then keyStr else String.fromCharCode(charCode) + + # Get char and escape it to avoid problems with String.search + key = utils.regexpEscape key + + # First do a pre match - count how many markers will match with the new character entered + if vim.markers.reduce ((v, marker) -> v + marker.willMatch key), 0 + for marker in vim.markers + marker.matchHintChar key + + if marker.isMatched() + vim.cb marker + hints.removeHints vim.window.document + vim.enterNormalMode() + break + +# Called in find mode. Will process charCode, update find, or close the +findCharHandler = (vim, keyStr, charCode) -> + backwards = false + + toNormalMode = -> + find.removeFind vim.window.document + vim.enterNormalMode() + + if keyStr.match(/.*Return/) + return toNormalMode() + else if keyStr == 'Backspace' + # Delete last available character from the query string + if vim.findStr.length > 0 + vim.findStr = vim.findStr.substr(0, vim.findStr.length - 1) + # Leave Find Mode the query string is already empty + else + return toNormalMode() + else if charCode > 0 + vim.findStr += String.fromCharCode(charCode) + else + return + + # Update the interface string + find.setFindStr vim.window.document, vim.findStr + + # Clear selection to avoid jumping between matching search results + vim.window.getSelection().removeAllRanges() + + # Search only if the query string isn't emply. + # Otherwise it will pop up Find dialog + if vim.findStr.length > 0 + find.find vim.window, vim.findStr, backwards - # If prematch is greater than 0, then proceed with matching, else ignore the new char - if preMatch > 0 - for marker in vim.markers - marker.matchHintChar char - if marker.isMatched() - vim.cb marker - removeHints vim.window.document - vim.enterNormalMode() - break exports.hintCharHandler = hintCharHandler +exports.findCharHandler = findCharHandler exports.commands = commands exports.commandsHelp = commandsHelp diff --git a/extension/packages/events.coffee b/extension/packages/events.coffee index f61c22c..ea011d5 100644 --- a/extension/packages/events.coffee +++ b/extension/packages/events.coffee @@ -43,10 +43,9 @@ windowsListener = if vim.blacklisted return - # Push new keyStr on the stack and we don't really want to - # suppress the Esc key, but we want to handle it - if vim.pushKey(keyStr) and keyStr != 'Esc' - suppressEvent event + if vim.handleKeyDown(event, keyStr) + if keyStr != 'Esc' + suppressEvent event catch err console.log err, 'keydown' @@ -62,7 +61,8 @@ windowsListener = # No action on blacklisted locations if vim.blacklisted return - else if vim.execKeys() + + if vim.handleKeyPress event suppressEvent event catch err console.log err, 'keypress' diff --git a/extension/packages/find.coffee b/extension/packages/find.coffee new file mode 100644 index 0000000..918c885 --- /dev/null +++ b/extension/packages/find.coffee @@ -0,0 +1,63 @@ +utils = require 'utils' + +CONTAINER_ID = 'VimFxFindContainer' + +# Create and inserts into DOM find controls and handlers +injectFind = (document) -> + # Clean up just in case... + removeFind document + + container = createFindContainer(document) + + document.documentElement.appendChild container + +# Removes find controls from DOM +removeFind = (document) -> + if div = document.getElementById CONTAINER_ID + document.documentElement.removeChild div + +setFindStr = (document, findStr) -> + document = document + + span = document.getElementById "VimFxFindSpan" + span.textContent = "/#{ findStr }" + +createFindContainer = (document) -> + return utils.parseHTML document, """ +
+ / +
+ """ + +find = (window, findStr, backwards=false) -> + f = -> + smartCase = findStr.toLowerCase() != findStr + + return window.find \ + findStr, + smartCase, # Smart case sensitivity + backwards, # To avoid getting last search result in the beginning + true, # aWrapAround - Doesn't currently work as expected + false, # aWholeWord - Not implemented according to MDN + true, # aSearchInFrames - Hell yea, search in frames! + false # aShowDialog - No dialog please + + + success = false + + # Perform find only if query string isn't empty to avoid find dialog pop up + if findStr.length > 0 + # Wrap Around is broken... Therefore + if not success = f() + # If first search attemp has failed then + # reset current selection and try again + window.getSelection().removeAllRanges() + success = f() + + return success + + +exports.injectFind = injectFind +exports.removeFind = removeFind +exports.setFindStr = setFindStr +exports.find = find diff --git a/extension/packages/help.coffee b/extension/packages/help.coffee index 52839e6..c368e80 100644 --- a/extension/packages/help.coffee +++ b/extension/packages/help.coffee @@ -2,11 +2,11 @@ utils = require 'utils' CONTAINER_ID = 'VimFxHelpDialogContainer' -hideHelp = (document) -> +removeHelp = (document) -> if div = document.getElementById CONTAINER_ID div.parentNode.removeChild div -showHelp = (document, commandsHelp) -> +injectHelp = (document, commandsHelp) -> if document.documentElement if div = document.getElementById CONTAINER_ID div.parentNode.removeChild div @@ -14,7 +14,7 @@ showHelp = (document, commandsHelp) -> div.id = CONTAINER_ID div.className = 'VimFxReset' - div.appendChild parseHTML(document, helpDialogHtml(commandsHelp)) + div.appendChild utils.parseHTML document, helpDialogHtml(commandsHelp) document.documentElement.appendChild div @@ -22,14 +22,9 @@ showHelp = (document, commandsHelp) -> clickHandler = (event) -> event.stopPropagation() event.preventDefault() - hideHelp(document) + removeHelp(document) button.addEventListener 'click', clickHandler, false -parseHTML = (doc, html) -> - parser = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils) - flags = parser.SanitizerAllowStyle - return parser.parseFragment(html, flags, false, null, doc.documentElement) - td = (text, klass='') -> """#{ text }""" @@ -97,5 +92,5 @@ helpDialogHtml = (help) -> """ -exports.showHelp = showHelp -exports.hideHelp = hideHelp +exports.injectHelp = injectHelp +exports.removeHelp = removeHelp diff --git a/extension/packages/hints.coffee b/extension/packages/hints.coffee index 7e4eb08..deb9496 100644 --- a/extension/packages/hints.coffee +++ b/extension/packages/hints.coffee @@ -4,39 +4,38 @@ CONTAINER_ID = 'VimFxHintMarkerContainer' HTMLDocument = Ci.nsIDOMHTMLDocument { Marker } = require 'marker' -getHintsContainer = (document) -> - document.getElementById CONTAINER_ID - createHintsContainer = (document) -> container = document.createElement 'div' container.id = CONTAINER_ID container.className = 'VimFxReset' return container +# Creates and injects hint markers into the DOM injectHints = (document) -> + # First remove previous hints container removeHints document if document instanceof HTMLDocument and document.documentElement + # Find and create markers markers = Marker.createMarkers document container = createHintsContainer document + # For performance use Document Fragment fragment = document.createDocumentFragment() for marker in markers fragment.appendChild marker.markerElement container.appendChild fragment - document.documentElement.appendChild container return markers +# Remove previously injected hints from the DOM removeHints = (document, markers) -> - if container = getHintsContainer document + if container = document.getElementById CONTAINER_ID document.documentElement.removeChild container -handleHintChar = (markers, char) -> exports.injectHints = injectHints exports.removeHints = removeHints -exports.handleHintChar = handleHintChar diff --git a/extension/packages/key-utils.coffee b/extension/packages/key-utils.coffee index 64ff112..d516843 100644 --- a/extension/packages/key-utils.coffee +++ b/extension/packages/key-utils.coffee @@ -19,11 +19,11 @@ keyCharFromCode = (keyCode, shiftKey=false) -> return charWithShift options = [ - [ KE.DOM_VK_RETURN, undefined, 'Return', undefined ], - [ KE.DOM_VK_ESCAPE, undefined, 'Esc', undefined ], - [ KE.DOM_VK_BACK_SPACE, undefined, 'Backspace', undefined ], - [ KE.DOM_VK_SPACE, undefined, 'Space', undefined ], - [ KE.DOM_VK_TAB, undefined, 'Tab', undefined ], + [ KE.DOM_VK_ESCAPE, KE.DOM_VK_ESCAPE, 'Esc', 'Shift-Esc' ], + [ KE.DOM_VK_BACK_SPACE, KE.DOM_VK_BACK_SPACE, 'Backspace', 'Shift-Backspace' ], + [ KE.DOM_VK_SPACE, KE.DOM_VK_SPACE, 'Space', 'Shift-Space' ], + [ KE.DOM_VK_TAB, KE.DOM_VK_TAB, 'Tab', 'Shift-Tab' ], + [ KE.DOM_VK_RETURN, KE.DOM_VK_RETURN, 'Return', 'Shift-Return' ], [ KE.DOM_VK_1, KE.DOM_VK_EXCLAMATION, '1', '!' ], [ KE.DOM_VK_2, KE.DOM_VK_AT, '2', '@' ], diff --git a/extension/packages/marker.coffee b/extension/packages/marker.coffee index fa647cb..201f912 100644 --- a/extension/packages/marker.coffee +++ b/extension/packages/marker.coffee @@ -77,14 +77,14 @@ class Marker matchHintChar: (char) -> # Handle backspace key by removing a previously entered hint char # and resetting its class - if char == 'backspace' + if char == 'Backspace' if @enteredHintChars.length > 0 @enteredHintChars = @enteredHintChars.slice(0, -1) @markerElement.children[@enteredHintChars.length]?.className = 'VimFxReset' # Otherwise append hint char and change hint class else @markerElement.children[@enteredHintChars.length]?.className = 'VimFxReset VimFxCharMatch' - @enteredHintChars += char + @enteredHintChars += char.toLowerCase() # If entered hint chars no longer partially match the hint chars # then hide the marker. Othersie show it back @@ -92,7 +92,7 @@ class Marker # Checks if the marker will be matched if the next character entered is `char` willMatch: (char) -> - char == 'backspace' or @hintChars.search(@enteredHintChars + char) == 0 + char == 'Backspace' or @hintChars.search(@enteredHintChars + char.toLowerCase()) == 0 # Checks if enterd hint chars completely match the hint chars isMatched: -> @@ -108,7 +108,6 @@ Marker.createMarkers = (document) -> set = getMarkableElements(document) markers = []; - j = 0 elements = [] for i in [0...set.snapshotLength] by 1 @@ -117,16 +116,18 @@ Marker.createMarkers = (document) -> elements.push [e, rect] elements.sort ([e1, r1], [e2, r2]) -> - if r1.area > r2.area + if r1.area < r2.area return -1 - else if r1.area < r2.area + else if r1.area > r2.area return 1 else return 0 + # start from the end because the list is sorted in ascending order + j = elements.length for [element, rect] in elements - console.log element.text, rect.height * rect.width, rect.area - hint = indexToHint(j++, hintChars) + # Get a hint for an element + hint = indexToHint(--j, hintChars) marker = new Marker(element) marker.setPosition rect marker.setHint hint diff --git a/extension/packages/utils.coffee b/extension/packages/utils.coffee index 376cc28..1eabc12 100644 --- a/extension/packages/utils.coffee +++ b/extension/packages/utils.coffee @@ -110,6 +110,18 @@ simulateClick = (element, modifiers) -> # but Webkit will. Dispatching a click on an input box does not seem to focus it; we do that separately element.dispatchEvent(mouseEvent) +focusSelection = (document) -> + selection = document.getSelection() + console.expand selection + for i in [0...selection.rangeCount] + console.log "range count", selection.rangeCount, i, selection.getRangeAt(i).startContainer + if element = selection.getRangeAt(i).startContainer?.parentElement + if isElementEditable element + range.startContainer.focus() + return true + + return false + # Write a string into system clipboard writeToClipboard = (window, text) -> str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); @@ -204,6 +216,13 @@ smoothScroll = (window, dx, dy, msecs) -> l -= 1 window.setTimeout fn, l * delta, x, y +parseHTML = (document, html) -> + parser = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils) + flags = parser.SanitizerAllowStyle + return parser.parseFragment(html, flags, false, null, document.documentElement) + +regexpEscape = (s) -> return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + exports.Bucket = Bucket exports.getCurrentTabWindow = getCurrentTabWindow exports.getEventWindow = getEventWindow @@ -213,6 +232,7 @@ exports.getEventTabBrowser = getEventTabBrowser exports.getWindowId = getWindowId exports.getRootWindow = getRootWindow exports.isElementEditable = isElementEditable +exports.focusSelection = focusSelection exports.getSessionStore = getSessionStore exports.loadCss = loadCss @@ -224,3 +244,5 @@ exports.writeToClipboard = writeToClipboard exports.timeIt = timeIt exports.isBlacklisted = isBlacklisted exports.getVersion = getVersion +exports.parseHTML = parseHTML +exports.regexpEscape = regexpEscape diff --git a/extension/packages/vim.coffee b/extension/packages/vim.coffee index 580a9a4..f37f34b 100644 --- a/extension/packages/vim.coffee +++ b/extension/packages/vim.coffee @@ -1,13 +1,16 @@ -{ getWindowId, Bucket } = require 'utils' +utils = require 'utils' -{ commands, - hintCharHandler } = require 'commands' +{ commands +, hintCharHandler +, findCharHandler +} = require 'commands' { getPref } = require 'prefs' MODE_NORMAL = 1 MODE_HINTS = 2 +MODE_FIND = 3 class Vim constructor: (@window) -> @@ -15,62 +18,76 @@ class Vim @keys = [] @markers = undefined @cb = undefined + @findStr = "" - pushKey: (keyStr) -> - if _maybeCommand(@mode, @keys, keyStr) + enterFindMode: -> + @mode = MODE_FIND + + enterHintsMode: (@markers, @cb) -> + @mode = MODE_HINTS + + enterNormalMode: -> + @mode = MODE_NORMAL + @markers = @cb = undefined + + pushKey: (keyStr, keyCode) -> + if _maybeCommand(@mode, @keys, keyStr, keyCode) @keys.push keyStr return true return false - execKeys: -> - if command = _getCommand(@mode, @keys) + execKeys: (charCode) -> + if command = _getCommand @mode, @keys, charCode lastKey = @keys[@keys.length - 1] command @ @keys = [] return lastKey != 'Esc' - enterHintsMode: () -> - @mode = MODE_HINTS - - enterNormalMode: () -> - @markers = @cb = undefined - - @mode = MODE_NORMAL - -_getCommand = (mode, keys) -> - lastKey = keys[keys.length - 1] - - if mode == MODE_NORMAL or lastKey == 'Esc' - sequence = keys.join(',') - if command = commands[sequence] - return command - else if keys.length > 0 - return _getCommand mode, keys.slice(1) - - else if mode == MODE_HINTS and keys.length > 0 - # `lastKey` should be one hint chars or `Backspace` - hintChars = getPref('hint_chars').toLowerCase() + 'backspace' - if hintChars.search(lastKey.toLowerCase()) > -1 - return (vim) => - return hintCharHandler(vim, lastKey.toLowerCase()) + handleKeyDown: (keyboardEvent, keyStr) -> + if @mode == MODE_NORMAL || keyStr == 'Esc' + result = maybeCommand @keys.concat([keyStr]) + else if !keyboardEvent.ctrlKey and !keyboardEvent.metaKey + if @mode == MODE_HINTS + hintChars = getPref('hint_chars').toLowerCase() + result = hintChars.search(utils.regexpEscape(keyStr)) > -1 + else if @mode == MODE_FIND + result = true + + if result then @keys.push keyStr + + return result + + handleKeyPress: (keyboardEvent) -> + lastKeyStr = if @keys.length > 0 then @keys[@keys.length - 1] else undefined + if @mode == MODE_NORMAL or lastKeyStr == 'Esc' + if command = findCommand @keys + command @ + @keys.length = 0 + return lastKeyStr != 'Esc' + else if !keyboardEvent.ctrlKey and !keyboardEvent.metaKey + @keys.length = 0 + if @mode == MODE_HINTS + hintCharHandler @, lastKeyStr, keyboardEvent.charCode + return true + else if @mode == MODE_FIND + findCharHandler @, lastKeyStr, keyboardEvent.charCode + return true + +findCommand = (keys) -> + for i in [0...keys.length] + if com = commands[keys.slice(i).join(',')] + return com return undefined -_maybeCommand = (mode, keys, keyStr) -> - if mode == MODE_NORMAL || keyStr == 'Esc' - sequence = keys.concat([keyStr]).join(',') - for commandSequence in Object.keys(commands) - if commandSequence.indexOf(sequence) == 0 - return true - - if keys.length > 0 - return _maybeCommand mode, keys.slice(1), keyStr +maybeCommand = (keys) -> + for i in [0...keys.length] + sequence = keys.slice(i).join(',') + for seq, com of commands + if seq.indexOf(sequence) == 0 + return true - else if mode == MODE_HINTS - hintChars = getPref('hint_chars').toLowerCase() - return (hintChars.search keyStr != -1) - - return false + return false exports.Vim = Vim diff --git a/extension/resources/style.css b/extension/resources/style.css index 4e74924..937a698 100644 --- a/extension/resources/style.css +++ b/extension/resources/style.css @@ -39,6 +39,22 @@ float: clear !important; } +/* Find */ + +span#VimFxFindSpan { + position: fixed !important; + bottom: 0 !important; + right: 0 !important; + font-size: 13px !important; + min-width: 200px !important; + background-color: white !important; + border: solid 1px #bd6b00 !important; + border-radius: 3px !important; + padding: 2px 4px 2px 4px !important; +} + +/* Markers */ + div.VimFxHintMarker { position: absolute !important; display: block !important; -- 2.39.3 From dbdd866b2970f6d89ed0b4c3bbd292cbc39840ff Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Sun, 9 Dec 2012 13:29:30 +0200 Subject: [PATCH 07/16] Closes #37. Added a preference that will enable bluring from any element that has input focus in the browser on Esc keydown --- extension/locale/en/options.dtd | 5 ++++- extension/options.xul | 2 ++ extension/packages/events.coffee | 11 ++++++++++- extension/packages/prefs.coffee | 1 + 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/extension/locale/en/options.dtd b/extension/locale/en/options.dtd index 3187fa4..f129035 100644 --- a/extension/locale/en/options.dtd +++ b/extension/locale/en/options.dtd @@ -6,7 +6,10 @@ Wildcards allowed: *, !"> - + + + + diff --git a/extension/options.xul b/extension/options.xul index c04ea45..4633d25 100644 --- a/extension/options.xul +++ b/extension/options.xul @@ -7,6 +7,8 @@ title="&pref.hint_chars.title;" desc="&pref.hint_chars.desc;" /> + diff --git a/extension/packages/events.coffee b/extension/packages/events.coffee index ea011d5..527b063 100644 --- a/extension/packages/events.coffee +++ b/extension/packages/events.coffee @@ -3,7 +3,7 @@ keyUtils = require 'key-utils' { getCommand } = require 'commands' { Vim } = require 'vim' { getPref } = require 'prefs' -{ setWindowBlacklisted } = require 'button' +{ setWindowBlacklisted } = require 'button' { interfaces: Ci } = Components @@ -61,9 +61,18 @@ windowsListener = # No action on blacklisted locations if vim.blacklisted return + + # Blur from any active element on Esc. Calling before `handleKeyPress` + # because `vim.keys` will be reset afterwards` + blur_on_esc = vim.keys[vim.keys.length - 1] == 'Esc' and getPref 'blur_on_esc' if vim.handleKeyPress event suppressEvent event + + # Calling after the command has been executed + if blur_on_esc + event.originalTarget?.ownerDocument?.activeElement?.blur() + catch err console.log err, 'keypress' diff --git a/extension/packages/prefs.coffee b/extension/packages/prefs.coffee index 1d5ce6b..208556d 100644 --- a/extension/packages/prefs.coffee +++ b/extension/packages/prefs.coffee @@ -12,6 +12,7 @@ PREFS = scroll_step: 60 scroll_time: 100 black_list: '*mail.google.com*' + blur_on_esc: true # Get Firefox preference value of type specified in `PREFS` getFFPref = do -> -- 2.39.3 From c47a026e0116b6b1bd74fc16bc0a98a66bb687a8 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Sun, 9 Dec 2012 14:37:50 +0200 Subject: [PATCH 08/16] Housekeeping --- .gitignore | 1 + extension/bootstrap.coffee | 23 ++++++++++--------- extension/includes/chrome.coffee | 7 +++--- extension/locale/ru/options.dtd | 3 +++ extension/packages/button.coffee | 5 ++-- extension/packages/utils.coffee | 13 ----------- .../window-utils.coffee | 4 ++++ 7 files changed, 27 insertions(+), 29 deletions(-) rename extension/{includes => packages}/window-utils.coffee (95%) diff --git a/.gitignore b/.gitignore index 6a621f1..65fa42a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules *.js .DS_Store builds +*.xpi diff --git a/extension/bootstrap.coffee b/extension/bootstrap.coffee index e90e1ff..3307886 100644 --- a/extension/bootstrap.coffee +++ b/extension/bootstrap.coffee @@ -1,6 +1,6 @@ "use strict" -{ utils: Cu } = Components +{ utils: Cu, classes: Cc, interfaces: Ci } = Components Cu.import "resource://gre/modules/Services.jsm" Cu.import "resource://gre/modules/AddonManager.jsm" @@ -10,13 +10,14 @@ do (global = this) -> baseURI = Services.io.newURI __SCRIPT_URI_SPEC__, null, null getResourceURI = (path) -> Services.io.newURI path, null, baseURI + loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader); + include = (src, scope = {}) -> try - uri = getResourceURI "packages/#{ src }.js" - Services.scriptloader.loadSubScript uri.spec, scope - catch error uri = getResourceURI src - Services.scriptloader.loadSubScript uri.spec, scope + loader.loadSubScript uri.spec, scope + catch error + dump "Failed to load #{ src }: #{ error }\n" return scope @@ -31,7 +32,7 @@ do (global = this) -> include: include exports: {} - include src, scope + include "packages/#{ src }.js", scope return modules[src] = scope.exports; @@ -44,13 +45,12 @@ do (global = this) -> 'chrome', 'console', 'unload', - 'window-utils', ] # Init localization `underscore` method - { l10n } = require 'l10n' - global._ = l10n "vimfx.properties" + global._ = require('l10n').l10n "vimfx.properties" + # Requires for startup/install { loadCss } = require 'utils' { addEventListeners } = require 'events' { getPref @@ -58,6 +58,7 @@ do (global = this) -> , transferPrefs } = require 'prefs' { setButtonInstallPosition , addToolbarButton } = require 'button' + wu = require 'window-utils' # Firefox will call this method on startup/enabling global.startup = (data, reason) -> @@ -71,8 +72,8 @@ do (global = this) -> transferPrefs "extension.VimFx.", "extensions.VimFx." loadCss 'style' - watchWindows addEventListeners, 'navigator:browser' - watchWindows addToolbarButton, 'navigator:browser' + wu.watchWindows addEventListeners, 'navigator:browser' + wu.watchWindows addToolbarButton, 'navigator:browser' installPrefObserver() # Firefox will call this method on shutdown/disabling diff --git a/extension/includes/chrome.coffee b/extension/includes/chrome.coffee index 7aea969..bf2c742 100644 --- a/extension/includes/chrome.coffee +++ b/extension/includes/chrome.coffee @@ -1,3 +1,4 @@ -{ classes: Cc -, interfaces: Ci -, utils: Cu } = Components +{ utils: Cu +, classes: Cc +, interfaces: Ci +} = Components diff --git a/extension/locale/ru/options.dtd b/extension/locale/ru/options.dtd index f3b258b..54ab897 100644 --- a/extension/locale/ru/options.dtd +++ b/extension/locale/ru/options.dtd @@ -8,6 +8,9 @@ + + + diff --git a/extension/packages/button.coffee b/extension/packages/button.coffee index 56e1728..ecea725 100644 --- a/extension/packages/button.coffee +++ b/extension/packages/button.coffee @@ -149,9 +149,10 @@ createButton = (window) -> setPref('disabled', not getPref 'disabled') updateToolbarButton button + event.preventDefault() event.stopPropagation() - button.addEventListener 'command', onButtonCommand, false + button.addEventListener 'command', onButtonCommand, true menupopup = createMenupopup window button.appendChild menupopup @@ -161,7 +162,7 @@ createButton = (window) -> vimkey.setAttribute "key", "V" vimkey.setAttribute "modifiers", "shift,alt" vimkey.setAttribute "oncommand", "void(0);" - vimkey.addEventListener "command", onButtonCommand, false + vimkey.addEventListener "command", onButtonCommand, true keyset = doc.createElement 'keyset' keyset.setAttribute 'id', KEYSET_ID diff --git a/extension/packages/utils.coffee b/extension/packages/utils.coffee index 1eabc12..ffb69d8 100644 --- a/extension/packages/utils.coffee +++ b/extension/packages/utils.coffee @@ -110,18 +110,6 @@ simulateClick = (element, modifiers) -> # but Webkit will. Dispatching a click on an input box does not seem to focus it; we do that separately element.dispatchEvent(mouseEvent) -focusSelection = (document) -> - selection = document.getSelection() - console.expand selection - for i in [0...selection.rangeCount] - console.log "range count", selection.rangeCount, i, selection.getRangeAt(i).startContainer - if element = selection.getRangeAt(i).startContainer?.parentElement - if isElementEditable element - range.startContainer.focus() - return true - - return false - # Write a string into system clipboard writeToClipboard = (window, text) -> str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString); @@ -232,7 +220,6 @@ exports.getEventTabBrowser = getEventTabBrowser exports.getWindowId = getWindowId exports.getRootWindow = getRootWindow exports.isElementEditable = isElementEditable -exports.focusSelection = focusSelection exports.getSessionStore = getSessionStore exports.loadCss = loadCss diff --git a/extension/includes/window-utils.coffee b/extension/packages/window-utils.coffee similarity index 95% rename from extension/includes/window-utils.coffee rename to extension/packages/window-utils.coffee index 309d02e..e36a4b3 100644 --- a/extension/includes/window-utils.coffee +++ b/extension/packages/window-utils.coffee @@ -61,3 +61,7 @@ watchWindows = (callback, winType) -> # Make sure to stop watching for windows if we're unloading unload -> Services.ww.unregisterNotification(windowWatcher) + +exports.runOnLoad = runOnLoad +exports.runOnWindows = runOnWindows +exports.watchWindows = watchWindows -- 2.39.3 From 9bdc73751115d1eca4725fe59655a2c85d2824a7 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Sun, 9 Dec 2012 14:48:14 +0200 Subject: [PATCH 09/16] Bumped version and updated README.md --- README.md | 23 +++++++++++++++++++++-- extension/install.rdf | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c37881e..f84b19a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ *Extension AMO page*: https://addons.mozilla.org/en-US/firefox/addon/vimfx/ +*Contribute your localization! See `locale` folder* + [VimFx](https://addons.mozilla.org/en-US/firefox/addon/vimfx/) is a [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/fx/#desktop) extension which introduces Vim-style keyboard shortcuts for browsing and navigation, @@ -47,6 +49,8 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` yy Copy current page link to the clipboard r Reload current page R Reload current page and all the assets (js, css, etc.) + ar Reload pages in all tabs + aR Reload pages in all tabs including assets (js, css, img) ### Navigating @@ -58,6 +62,8 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` l Scroll Right d Scroll half a Page Down u Scroll half a Page Up + c-f Scroll full Page Down + c-b Scroll full Page Up ### Tabs @@ -80,6 +86,9 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` ### Misc + / Enter Find mode + n Go ot the next Find match + N Go ot the previous Find match ? Show Help Dialog Esc Close this dialog and cancel hint markers @@ -98,8 +107,8 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` - document.designMode='on' is now honored. Will also provide hint markers for iframes on the page. - Bug fixed where it would completely reset the toolbar while installing the toolbar button. - Bug fixed where it's not possible to change the text in the blaclisting textbox -- Changed u/d to scroll half a page, added ^f/^b to scroll full page -- Added tab movement commands: ^J and ^K. +- Changed u/d to scroll half a page, added c-f/c-b to scroll full page +- Added tab movement commands: c-J and c-K. - Invisible markers bug fixed. - Global hotkey to disable the commands (equal to the toolbar button click): Alt-Shift V - ^u and ^d are removed from the command list. ^u is commonly used to show the page source code @@ -118,3 +127,13 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` 0.3.2, 0.3.2, 0.3.3 (20-21 Nov 2012) - Hotfixes for the build script to include localization related files and folders + +0.4 (9 Dec 2012) + +- Implemented find with `/` and `n/N` +- Added `ar` and `aR` commands to reload pages in all open tabs. +- Added a preference that enables bluring from any element that has input focus in the browser on Esc keydown (on by default) +- Fixed bug where markers and help dialog would blow up some of the pages. +- Marker hints are now sorted with respect to the underlying element area. Elements with larger area get shorter hints +- Added *mail.google.com* to the default black list +- Various bug fixed and improvements. diff --git a/extension/install.rdf b/extension/install.rdf index 0acb43f..a3c8fa6 100644 --- a/extension/install.rdf +++ b/extension/install.rdf @@ -9,7 +9,7 @@ VimFx@akhodakivskiy.github.com http://www.github.com/akhodakivskiy/VimFx - 0.3.3 + 0.4 2 true 2 -- 2.39.3 From 6e94d948068dd4eae940c47632eda61b7685b515 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Wed, 12 Dec 2012 09:03:49 +0200 Subject: [PATCH 10/16] small fix for non-english keyboard layouts --- extension/packages/commands.coffee | 4 +--- extension/packages/events.coffee | 7 +++++-- extension/packages/vim.coffee | 11 +++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/extension/packages/commands.coffee b/extension/packages/commands.coffee index df92599..0c95bdc 100644 --- a/extension/packages/commands.coffee +++ b/extension/packages/commands.coffee @@ -305,10 +305,8 @@ commandsHelp = do (commandGroups) -> # Called in hints mode. Will process the char, update and hide/show markers hintCharHandler = (vim, keyStr, charCode) -> if charCode > 0 - key = if keyStr == 'Backspace' then keyStr else String.fromCharCode(charCode) - # Get char and escape it to avoid problems with String.search - key = utils.regexpEscape key + key = utils.regexpEscape keyStr # First do a pre match - count how many markers will match with the new character entered if vim.markers.reduce ((v, marker) -> v + marker.willMatch key), 0 diff --git a/extension/packages/events.coffee b/extension/packages/events.coffee index 527b063..028deb8 100644 --- a/extension/packages/events.coffee +++ b/extension/packages/events.coffee @@ -62,12 +62,15 @@ windowsListener = if vim.blacklisted return + lastKeyStr = vim.keys[vim.keys.length - 1] + # Blur from any active element on Esc. Calling before `handleKeyPress` # because `vim.keys` will be reset afterwards` - blur_on_esc = vim.keys[vim.keys.length - 1] == 'Esc' and getPref 'blur_on_esc' + blur_on_esc = lastKeyStr == 'Esc' and getPref 'blur_on_esc' if vim.handleKeyPress event - suppressEvent event + if lastKeyStr != 'Esc' + suppressEvent event # Calling after the command has been executed if blur_on_esc diff --git a/extension/packages/vim.coffee b/extension/packages/vim.coffee index f37f34b..b08e58e 100644 --- a/extension/packages/vim.coffee +++ b/extension/packages/vim.coffee @@ -63,16 +63,19 @@ class Vim if @mode == MODE_NORMAL or lastKeyStr == 'Esc' if command = findCommand @keys command @ - @keys.length = 0 - return lastKeyStr != 'Esc' + result = lastKeyStr != 'Esc' else if !keyboardEvent.ctrlKey and !keyboardEvent.metaKey @keys.length = 0 if @mode == MODE_HINTS hintCharHandler @, lastKeyStr, keyboardEvent.charCode - return true + result = true else if @mode == MODE_FIND findCharHandler @, lastKeyStr, keyboardEvent.charCode - return true + result = true + + if result then @keys.length = 0 + + return result findCommand = (keys) -> for i in [0...keys.length] -- 2.39.3 From 0a82425482fa9911917147e0914b712e9f5d43da Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Wed, 12 Dec 2012 13:14:32 +0200 Subject: [PATCH 11/16] Closes #38. Now there is an indication that find yielded no results --- extension/packages/commands.coffee | 17 +++++++++----- extension/packages/find.coffee | 36 ++++++++++++++++++++++++++---- extension/resources/style.css | 5 ++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/extension/packages/commands.coffee b/extension/packages/commands.coffee index 0c95bdc..a94dbed 100644 --- a/extension/packages/commands.coffee +++ b/extension/packages/commands.coffee @@ -207,11 +207,15 @@ command_find = (vim) -> # Search for the last pattern command_n = (vim) -> - find.find vim.window, vim.findStr, false + if vim.findStr.length > 0 + if not find.find vim.window, vim.findStr, false + find.flashFind vim.window.document, "#{ vim.findStr } (Not Found)" # Search for the last pattern backwards command_N = (vim) -> - find.find vim.window, vim.findStr, true + if vim.findStr.length > 0 + if not find.find vim.window, vim.findStr, true + find.flashFind vim.window.document, "#{ vim.findStr } (Not Found)" # Close the Help dialog and cancel the pending hint marker action command_Esc = (vim) -> @@ -327,7 +331,7 @@ findCharHandler = (vim, keyStr, charCode) -> find.removeFind vim.window.document vim.enterNormalMode() - if keyStr.match(/.*Return/) + if keyStr and keyStr.match(/.*Return/) return toNormalMode() else if keyStr == 'Backspace' # Delete last available character from the query string @@ -342,15 +346,16 @@ findCharHandler = (vim, keyStr, charCode) -> return # Update the interface string - find.setFindStr vim.window.document, vim.findStr # Clear selection to avoid jumping between matching search results vim.window.getSelection().removeAllRanges() # Search only if the query string isn't emply. # Otherwise it will pop up Find dialog - if vim.findStr.length > 0 - find.find vim.window, vim.findStr, backwards + if find.find vim.window, vim.findStr, backwards + find.setFindStr vim.window.document, vim.findStr + else + find.setFindStr vim.window.document, "#{ vim.findStr } (Not Found)" diff --git a/extension/packages/find.coffee b/extension/packages/find.coffee index 918c885..8835dee 100644 --- a/extension/packages/find.coffee +++ b/extension/packages/find.coffee @@ -16,11 +16,17 @@ removeFind = (document) -> if div = document.getElementById CONTAINER_ID document.documentElement.removeChild div -setFindStr = (document, findStr) -> - document = document +flashFind = (document, findStr) -> + window = document.defaultView + + injectFind document + setFindStr document, findStr - span = document.getElementById "VimFxFindSpan" - span.textContent = "/#{ findStr }" + window.setTimeout (-> removeFind document), 1000 + +setFindStr = (document, findStr) -> + if span = document.getElementById "VimFxFindSpan" + span.textContent = "/#{ findStr }" createFindContainer = (document) -> return utils.parseHTML document, """ @@ -47,6 +53,9 @@ find = (window, findStr, backwards=false) -> # Perform find only if query string isn't empty to avoid find dialog pop up if findStr.length > 0 + # This will change the ::selection css rule + addClass window.document.body, "VimFxFindModeBody" + # Wrap Around is broken... Therefore if not success = f() # If first search attemp has failed then @@ -54,10 +63,29 @@ find = (window, findStr, backwards=false) -> window.getSelection().removeAllRanges() success = f() + # For now let's rely on the fact that Fiefox doesn't update the selection + # if the css fule that governs it is chnaged + window.setTimeout (-> removeClass window.document.body, "VimFxFindModeBody"), 1000 + return success +# Adds a class the the `element.className` trying to keep the whole class string +# will formed (without extra spaces at the tails) +addClass = (element, klass) -> + if element.className?.search klass == -1 + if element.className + element.className += " #{ klass }" + else + element.className = klass + +# Remove a class from the `element.className` +removeClass = (element, klass) -> + name = element.className.replace new RegExp("\\s*#{ klass }"), "" + element.className = name or null + exports.injectFind = injectFind exports.removeFind = removeFind +exports.flashFind = flashFind exports.setFindStr = setFindStr exports.find = find diff --git a/extension/resources/style.css b/extension/resources/style.css index 937a698..994df69 100644 --- a/extension/resources/style.css +++ b/extension/resources/style.css @@ -41,6 +41,9 @@ /* Find */ +body.VimFxFindModeBody ::-moz-selection { background-color: #2CD25E !important; } +body.VimFxFindModeBody ::selection { background-color: #2CD25E !important; } + span#VimFxFindSpan { position: fixed !important; bottom: 0 !important; @@ -48,7 +51,7 @@ span#VimFxFindSpan { font-size: 13px !important; min-width: 200px !important; background-color: white !important; - border: solid 1px #bd6b00 !important; + border: solid 2px #bd6b00 !important; border-radius: 3px !important; padding: 2px 4px 2px 4px !important; } -- 2.39.3 From 6b872f200d799c97079e3f9b534e5cc0ab495590 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Wed, 12 Dec 2012 13:20:03 +0200 Subject: [PATCH 12/16] bumped version and updated change log --- README.md | 5 +++++ extension/install.rdf | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f84b19a..addac9c 100644 --- a/README.md +++ b/README.md @@ -137,3 +137,8 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` - Marker hints are now sorted with respect to the underlying element area. Elements with larger area get shorter hints - Added *mail.google.com* to the default black list - Various bug fixed and improvements. + +0.4.1 (13 Dec 2012) + +- Small tweaks of the find feature. +- Bugfix for keyboard handling on non-english keyboard layouts diff --git a/extension/install.rdf b/extension/install.rdf index a3c8fa6..56e7089 100644 --- a/extension/install.rdf +++ b/extension/install.rdf @@ -9,7 +9,7 @@ VimFx@akhodakivskiy.github.com http://www.github.com/akhodakivskiy/VimFx - 0.4 + 0.4.1 2 true 2 -- 2.39.3 From dec744548a094418774d34450ae979588abe6de6 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Fri, 14 Dec 2012 16:51:15 +0200 Subject: [PATCH 13/16] Key handling bug fixing --- extension/includes/console.coffee | 13 +++++++++++++ extension/packages/commands.coffee | 8 ++++---- extension/packages/events.coffee | 22 ++++++++++++++++++---- extension/packages/utils.coffee | 2 +- extension/packages/vim.coffee | 19 ++----------------- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/extension/includes/console.coffee b/extension/includes/console.coffee index a561992..c750235 100644 --- a/extension/includes/console.coffee +++ b/extension/includes/console.coffee @@ -22,10 +22,23 @@ console = do -> else return arg + stacktrace = -> + st2 = (f) -> + if f + name = f.toString().split('(')[0] + args = Array.map(f.arguments, stringify).join(", ") + return st2(f.caller) + .concat(["#{ name } ( #{ args } )"]) + else + [] + return st2(arguments.callee.caller); + + return { log: -> message 'log', arguments info: -> message 'info', arguments error: -> message 'error', arguments warning: -> message 'warning', arguments expand: -> message 'expand', Array.map(arguments, expand) + stacktrace: -> message 'stacktrace', stacktrace() } diff --git a/extension/packages/commands.coffee b/extension/packages/commands.coffee index a94dbed..046da11 100644 --- a/extension/packages/commands.coffee +++ b/extension/packages/commands.coffee @@ -255,7 +255,7 @@ commandGroups = 'k|c-y': [ command_k_cy, _('help_command_k_cy') ] 'h': [ command_h, _('help_command_h') ] 'l': [ command_l , _('help_command_l') ] - # Can't use c-u/c-d because it's widely used for viewing sources + # Can't use c-u/c-d because c-u is widely used for viewing sources 'd': [ command_d, _('help_command_d') ] 'u': [ command_u, _('help_command_u') ] 'c-f': [ command_cf, _('help_command_cf') ] @@ -283,7 +283,7 @@ commandGroups = # See key-utils.coffee for more info '?|>': [ command_help, _('help_command_help') ] 'Esc': [ command_Esc, _('help_command_Esc') ] - + # Merge groups and split command pipes into individual commands commands = do (commandGroups) -> newCommands = {} @@ -308,12 +308,12 @@ commandsHelp = do (commandGroups) -> # Called in hints mode. Will process the char, update and hide/show markers hintCharHandler = (vim, keyStr, charCode) -> - if charCode > 0 + if keyStr and charCode > 0 # Get char and escape it to avoid problems with String.search key = utils.regexpEscape keyStr # First do a pre match - count how many markers will match with the new character entered - if vim.markers.reduce ((v, marker) -> v + marker.willMatch key), 0 + if vim.markers.reduce ((v, marker) -> v or marker.willMatch key), false for marker in vim.markers marker.matchHintChar key diff --git a/extension/packages/events.coffee b/extension/packages/events.coffee index 028deb8..38524c0 100644 --- a/extension/packages/events.coffee +++ b/extension/packages/events.coffee @@ -13,6 +13,10 @@ suppressEvent = (event) -> event.preventDefault() event.stopPropagation() +# ************************* +# NB! All this shit needs to be redone!! +# ************************* + # The following listeners are installed on every top level Chrome window windowsListener = 'keydown': (event) -> @@ -21,7 +25,7 @@ windowsListener = return try - isEditable = utils.isElementEditable event.originalTarget + isEditable = utils.isElementEditable event.originalTarget { ctrlKey: ctrl, metaKey: meta, altKey: alt, shiftKey: shift } = event @@ -48,12 +52,15 @@ windowsListener = suppressEvent event catch err console.log err, 'keydown' + console.stacktrace() 'keypress': (event) -> if getPref 'disabled' return try + isEditable = utils.isElementEditable event.originalTarget + # Try to execute keys that were accumulated so far. # Suppress event if there is a matching command. if window = utils.getCurrentTabWindow event @@ -68,9 +75,15 @@ windowsListener = # because `vim.keys` will be reset afterwards` blur_on_esc = lastKeyStr == 'Esc' and getPref 'blur_on_esc' - if vim.handleKeyPress event - if lastKeyStr != 'Esc' - suppressEvent event + # Process event if there is no editable element in focus + # Or last key was Esc key + if not isEditable or lastKeyStr == 'Esc' + result = vim.handleKeyPress event + + # If there was some processing done then suppress the eveng + # unless it's the Esc key + if result or lastKeyStr == 'Esc' + suppressEvent event # Calling after the command has been executed if blur_on_esc @@ -78,6 +91,7 @@ windowsListener = catch err console.log err, 'keypress' + console.stacktrace() # When the top level window closes we should release all Vims that were # associated with tabs in this window diff --git a/extension/packages/utils.coffee b/extension/packages/utils.coffee index ffb69d8..1186e87 100644 --- a/extension/packages/utils.coffee +++ b/extension/packages/utils.coffee @@ -209,7 +209,7 @@ parseHTML = (document, html) -> flags = parser.SanitizerAllowStyle return parser.parseFragment(html, flags, false, null, document.documentElement) -regexpEscape = (s) -> return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') +regexpEscape = (s) -> return s and s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') exports.Bucket = Bucket exports.getCurrentTabWindow = getCurrentTabWindow diff --git a/extension/packages/vim.coffee b/extension/packages/vim.coffee index b08e58e..084cc50 100644 --- a/extension/packages/vim.coffee +++ b/extension/packages/vim.coffee @@ -30,20 +30,6 @@ class Vim @mode = MODE_NORMAL @markers = @cb = undefined - pushKey: (keyStr, keyCode) -> - if _maybeCommand(@mode, @keys, keyStr, keyCode) - @keys.push keyStr - return true - - return false - - execKeys: (charCode) -> - if command = _getCommand @mode, @keys, charCode - lastKey = @keys[@keys.length - 1] - command @ - @keys = [] - return lastKey != 'Esc' - handleKeyDown: (keyboardEvent, keyStr) -> if @mode == MODE_NORMAL || keyStr == 'Esc' result = maybeCommand @keys.concat([keyStr]) @@ -63,7 +49,8 @@ class Vim if @mode == MODE_NORMAL or lastKeyStr == 'Esc' if command = findCommand @keys command @ - result = lastKeyStr != 'Esc' + @keys.length = 0 + result = true else if !keyboardEvent.ctrlKey and !keyboardEvent.metaKey @keys.length = 0 if @mode == MODE_HINTS @@ -73,8 +60,6 @@ class Vim findCharHandler @, lastKeyStr, keyboardEvent.charCode result = true - if result then @keys.length = 0 - return result findCommand = (keys) -> -- 2.39.3 From 7faddc15236dff1bc464fe4542cc52801b38010f Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Fri, 14 Dec 2012 16:52:26 +0200 Subject: [PATCH 14/16] Version bump, README.md update --- README.md | 2 +- extension/install.rdf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index addac9c..9f0da7d 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Global shortcut to enable/disable VimFx: `Shift-Alt-v` - Added *mail.google.com* to the default black list - Various bug fixed and improvements. -0.4.1 (13 Dec 2012) +0.4.1, 0.4.2 (12-14 Dec 2012) - Small tweaks of the find feature. - Bugfix for keyboard handling on non-english keyboard layouts diff --git a/extension/install.rdf b/extension/install.rdf index 56e7089..28cfc00 100644 --- a/extension/install.rdf +++ b/extension/install.rdf @@ -9,7 +9,7 @@ VimFx@akhodakivskiy.github.com http://www.github.com/akhodakivskiy/VimFx - 0.4.1 + 0.4.2 2 true 2 -- 2.39.3 From d3aa23a59ff3fb730d8255a8017475ebdace42fa Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Mon, 24 Dec 2012 23:26:51 +0200 Subject: [PATCH 15/16] Closes #39. Checkboxes are added to the Help Dialog allowing users to disable certain commands --- extension/bootstrap.coffee | 2 - extension/packages/commands.coffee | 19 +++--- extension/packages/help.coffee | 102 +++++++++++++++++------------ extension/packages/prefs.coffee | 78 ++++++++++------------ extension/packages/vim.coffee | 12 ++-- extension/resources/style.css | 2 +- 6 files changed, 115 insertions(+), 100 deletions(-) diff --git a/extension/bootstrap.coffee b/extension/bootstrap.coffee index 3307886..77b7bb7 100644 --- a/extension/bootstrap.coffee +++ b/extension/bootstrap.coffee @@ -54,7 +54,6 @@ do (global = this) -> { loadCss } = require 'utils' { addEventListeners } = require 'events' { getPref - , installPrefObserver , transferPrefs } = require 'prefs' { setButtonInstallPosition , addToolbarButton } = require 'button' @@ -74,7 +73,6 @@ do (global = this) -> loadCss 'style' wu.watchWindows addEventListeners, 'navigator:browser' wu.watchWindows addToolbarButton, 'navigator:browser' - installPrefObserver() # Firefox will call this method on shutdown/disabling global.shutdown = (data, reason) -> diff --git a/extension/packages/commands.coffee b/extension/packages/commands.coffee index 046da11..8baee76 100644 --- a/extension/packages/commands.coffee +++ b/extension/packages/commands.coffee @@ -5,7 +5,7 @@ hints = require 'hints' help = require 'help' find = require 'find' -{ getPref } = require 'prefs' +{ getPref, setPref } = require 'prefs' # Navigate to the address that is currently stored in the system clipboard command_p = (vim) -> @@ -276,10 +276,11 @@ commandGroups = 'H': [ command_H, _('help_command_H') ] 'L': [ command_L, _('help_command_L') ] 'misc': - '/': [ command_find, _('help_command_find') ] + # `.` is added to find command mapping to hack around Russian keyboard layout + '\.|/': [ command_find, _('help_command_find') ] 'n': [ command_n, _('help_command_n') ] 'N': [ command_N, _('help_command_N') ] - # `>` is added to help command mapping to hack around russian keyboard layout + # `>` is added to help command mapping to hack around Russian keyboard layout # See key-utils.coffee for more info '?|>': [ command_help, _('help_command_help') ] 'Esc': [ command_Esc, _('help_command_Esc') ] @@ -300,8 +301,7 @@ commandsHelp = do (commandGroups) -> for group, commandsList of commandGroups helpGroup = {} for keys, command of commandsList - key = keys.replace(/,/g, '').replace('|', ', ') - helpGroup[key] = command[1] + helpGroup[keys] = command[1] helpStrings[group] = helpGroup return helpStrings @@ -358,8 +358,7 @@ findCharHandler = (vim, keyStr, charCode) -> find.setFindStr vim.window.document, "#{ vim.findStr } (Not Found)" - -exports.hintCharHandler = hintCharHandler -exports.findCharHandler = findCharHandler -exports.commands = commands -exports.commandsHelp = commandsHelp +exports.hintCharHandler = hintCharHandler +exports.findCharHandler = findCharHandler +exports.commands = commands +exports.commandsHelp = commandsHelp diff --git a/extension/packages/help.coffee b/extension/packages/help.coffee index c368e80..1c946ea 100644 --- a/extension/packages/help.coffee +++ b/extension/packages/help.coffee @@ -1,4 +1,5 @@ -utils = require 'utils' +utils = require 'utils' +prefs = require 'prefs' CONTAINER_ID = 'VimFxHelpDialogContainer' @@ -18,6 +19,8 @@ injectHelp = (document, commandsHelp) -> document.documentElement.appendChild div + installCheckboxHandlers document + if button = document.getElementById('VimFxClose') clickHandler = (event) -> event.stopPropagation() @@ -25,12 +28,31 @@ injectHelp = (document, commandsHelp) -> removeHelp(document) button.addEventListener 'click', clickHandler, false +installCheckboxHandlers = (document) -> + cbs = document.getElementsByClassName "VimFxKeyCheckbox" + for cb in cbs + cb.addEventListener "change", (event)-> + key = event.target.getAttribute "data-key" + + # Checkbox if checked => command is in use + if event.target.checked + prefs.enableCommand key + else + prefs.disableCommand key + td = (text, klass='') -> """#{ text }""" tr = (key, text) -> - key = """#{ key } """ - """#{ td(key, 'VimFxSequence') }#{ td(text) }""" + disabled = prefs.isCommandDisabled key + checked = if disabled then null else "checked" + key = """ + #{ key.replace(/,/g, '').replace('|', ', ') } + + + """ + + return """#{ td(key, 'VimFxSequence') }#{ td(text) }""" table = (commands) -> """ @@ -47,50 +69,48 @@ section = (title, commands) -> helpDialogHtml = (help) -> return """ - -
-
-
- VimFx - #{ _('help') } +
+
+
+ VimFx + #{ _('help') } +
+ #{ _('help_version') } #{ utils.getVersion() } + +
- #{ _('help_version') } #{ utils.getVersion() } - -
-
-
-
- #{ section(_('help_section_urls'), help['urls']) } - #{ section(_('help_section_nav'), help['nav']) } -
-
- #{ section(_('help_section_tabs'), help['tabs']) } - #{ section(_('help_section_browse'), help['browse']) } - #{ section(_('help_section_misc'), help['misc']) } +
+
+ #{ section(_('help_section_urls'), help['urls']) } + #{ section(_('help_section_nav'), help['nav']) } +
+
+ #{ section(_('help_section_tabs'), help['tabs']) } + #{ section(_('help_section_browse'), help['browse']) } + #{ section(_('help_section_misc'), help['misc']) } +
+
-
-
-
-
-

- #{ _('help_found_bug') } - - #{ _('help_report_bug') } - -

-

- #{ _('help_enjoying') } - - #{ _('help_feedback') } - -

+
+
+

+ #{ _('help_found_bug') } + + #{ _('help_report_bug') } + +

+

+ #{ _('help_enjoying') } + + #{ _('help_feedback') } + +

+
-
- -""" + """ exports.injectHelp = injectHelp exports.removeHelp = removeHelp diff --git a/extension/packages/prefs.coffee b/extension/packages/prefs.coffee index 208556d..d8db215 100644 --- a/extension/packages/prefs.coffee +++ b/extension/packages/prefs.coffee @@ -5,7 +5,7 @@ PREF_BRANCH = "extensions.VimFx."; # Default values for the preference # All used preferences should be mentioned here becuase # preference type is derived from here -PREFS = +DEFAULT_PREF_VALUES = addon_id: 'VimFx@akhodakivskiy.github.com' hint_chars: 'asdfgercvhjkl;uinm' disabled: false @@ -14,27 +14,27 @@ PREFS = black_list: '*mail.google.com*' blur_on_esc: true -# Get Firefox preference value of type specified in `PREFS` -getFFPref = do -> +getPref = do -> branch = Services.prefs.getBranch PREF_BRANCH - return (key) -> - value = PREFS[key] + return (key, defaultValue=undefined) -> + type = branch.getPrefType(key) - # Return default value if the preference value hasn't been set yet - if branch.getPrefType(key) == branch.PREF_INVALID - return value; - - switch typeof value - when 'boolean' + switch type + when branch.PREF_BOOL return branch.getBoolPref key - when 'number' + when branch.PREF_INT return branch.getIntPref key - else + when branch.PREF_STRING return branch.getCharPref key + else + if defaultValue != undefined + return defaultValue + else + return DEFAULT_PREF_VALUES[key]; # Assign and save Firefox preference value -setFFPref = do -> +setPref = do -> branch = Services.prefs.getBranch PREF_BRANCH return (key, value) -> @@ -43,35 +43,11 @@ setFFPref = do -> branch.setBoolPref(key, value) when 'number' branch.setIntPref(key, value) + when 'string' + branch.setCharPref(key, value); else - branch.setCharPref(key, String(value)); - -# Set default values and update previously stored values for the preferences -do -> - branch = Services.prefs.getBranch PREF_BRANCH - for key in Object.keys(PREFS) - if branch.getPrefType(key) == branch.PREF_INVALID - setFFPref key, PREFS[key] - else - PREFS[key] = getFFPref key + branch.clearUserPref(key); -# Monitor preference changes and update values in local cache - PREFS -installPrefObserver = -> - branch = Services.prefs.getBranch(PREF_BRANCH) - - observer = - observe: (subject, topic, data) -> - if topic == 'nsPref:changed' and data in Object.keys(PREFS) - PREFS[data] = getFFPref data - - branch.addObserver "", observer, false - unload -> branch.removeObserver "", observer - -# Get preference value from local cache - PREFS -getPref = (key) -> return PREFS[key] - -# Set preference value -setPref = (key, value) -> setFFPref key, value # Transfer all setting values from one branch to another transferPrefs = (from, to) -> @@ -93,8 +69,26 @@ transferPrefs = (from, to) -> fromBranch.deleteBranch("") +# Checks if given command is disabled in the preferences +isCommandDisabled = (key) -> + return getPref("disabled_commands", "").indexOf(key) > -1 + +# Adds command to the disabled list +disableCommand = (key) -> + dc = getPref("disabled_commands", "").split("||") + dc.push key + setPref "disabled_commands", dc.join("||") + +# Enables command +enableCommand = (key) -> + dc = getPref("disabled_commands", "").split("||") + while (index = dc.indexOf(key)) > -1 + dc.splice(index, 1) + setPref "disabled_commands", dc.join("||") exports.getPref = getPref exports.setPref = setPref -exports.installPrefObserver = installPrefObserver exports.transferPrefs = transferPrefs +exports.isCommandDisabled = isCommandDisabled +exports.disableCommand = disableCommand +exports.enableCommand = enableCommand diff --git a/extension/packages/vim.coffee b/extension/packages/vim.coffee index 084cc50..55f73f0 100644 --- a/extension/packages/vim.coffee +++ b/extension/packages/vim.coffee @@ -5,7 +5,9 @@ utils = require 'utils' , findCharHandler } = require 'commands' -{ getPref } = require 'prefs' +{ getPref +, isCommandDisabled +} = require 'prefs' MODE_NORMAL = 1 @@ -64,8 +66,10 @@ class Vim findCommand = (keys) -> for i in [0...keys.length] - if com = commands[keys.slice(i).join(',')] - return com + seq = keys.slice(i).join(',') + if com = commands[seq] + if not isCommandDisabled(seq) + return com return undefined @@ -74,7 +78,7 @@ maybeCommand = (keys) -> sequence = keys.slice(i).join(',') for seq, com of commands if seq.indexOf(sequence) == 0 - return true + return not isCommandDisabled(seq) return false diff --git a/extension/resources/style.css b/extension/resources/style.css index 994df69..78b8a23 100644 --- a/extension/resources/style.css +++ b/extension/resources/style.css @@ -95,7 +95,7 @@ div#VimFxHelpDialog { position:fixed !important; border-radius:3px !important; padding:15px 30px !important; - width:600px !important; + width:700px !important; left:50% !important; /* This needs to be 1/2 width to horizontally center the help dialog */ margin-left:-330px !important; -- 2.39.3 From 1acb7d2b0b53b2ae8eebab674bda0a832ae27144 Mon Sep 17 00:00:00 2001 From: Anton Khodakivskiy Date: Tue, 25 Dec 2012 11:04:37 +0200 Subject: [PATCH 16/16] Closes #40. Toolbar button is back online. Small tweaks to the new feature that allows to disable individual hotkeys --- extension/packages/button.coffee | 8 ++++---- extension/packages/prefs.coffee | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extension/packages/button.coffee b/extension/packages/button.coffee index ecea725..7f7ed95 100644 --- a/extension/packages/button.coffee +++ b/extension/packages/button.coffee @@ -4,6 +4,8 @@ { injectHelp } = require 'help' { commandsHelp } = require 'commands' +utils = require 'utils' + KEYSET_ID = 'vimfx-keyset' BUTTON_ID = 'vimfx-toolbar-button' KEY_ID = 'vimfx-key' @@ -149,10 +151,9 @@ createButton = (window) -> setPref('disabled', not getPref 'disabled') updateToolbarButton button - event.preventDefault() event.stopPropagation() - button.addEventListener 'command', onButtonCommand, true + button.addEventListener 'command', onButtonCommand, false menupopup = createMenupopup window button.appendChild menupopup @@ -162,7 +163,7 @@ createButton = (window) -> vimkey.setAttribute "key", "V" vimkey.setAttribute "modifiers", "shift,alt" vimkey.setAttribute "oncommand", "void(0);" - vimkey.addEventListener "command", onButtonCommand, true + vimkey.addEventListener "command", onButtonCommand, false keyset = doc.createElement 'keyset' keyset.setAttribute 'id', KEYSET_ID @@ -170,7 +171,6 @@ createButton = (window) -> return [button, keyset] - addToolbarButton = (window) -> doc = window.document win = doc.querySelector 'window' diff --git a/extension/packages/prefs.coffee b/extension/packages/prefs.coffee index d8db215..4ae2a30 100644 --- a/extension/packages/prefs.coffee +++ b/extension/packages/prefs.coffee @@ -71,7 +71,7 @@ transferPrefs = (from, to) -> # Checks if given command is disabled in the preferences isCommandDisabled = (key) -> - return getPref("disabled_commands", "").indexOf(key) > -1 + return getPref("disabled_commands", "").split("||").indexOf(key) > -1 # Adds command to the disabled list disableCommand = (key) -> -- 2.39.3