From c567d7d043b689d72eabbd671eab8ae8805dadc1 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 11:23:29 +0100 Subject: Fix marks (incl. global marks)... Fixes #1712: - Make global marks work. - Add mode indicator. - Don't fail for global marks on background page if mark is not set. - Give HUD warning for global marks if global mark is not set. (The diff is big but, which the exception of infrastructure refactoring, the main change is to not exit on , thereby fixing #1712). --- background_scripts/marks.coffee | 24 ++++++---- content_scripts/marks.coffee | 101 ++++++++++++++++++++++++---------------- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 15d41205..db9c4ae2 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -23,12 +23,18 @@ removeMarksForTab = (id) -> root.goto = (req, sender) -> mark = marks[req.markName] - chrome.tabs.update mark.tabId, selected: true - chrome.tabs.sendMessage mark.tabId, - name: "setScrollPosition" - scrollX: mark.scrollX - scrollY: mark.scrollY - chrome.tabs.sendMessage mark.tabId, - name: "showHUDforDuration", - text: "Jumped to global mark '#{req.markName}'" - duration: 1000 + if mark? + chrome.tabs.update mark.tabId, selected: true + chrome.tabs.sendMessage mark.tabId, + name: "setScrollPosition" + scrollX: mark.scrollX + scrollY: mark.scrollY + chrome.tabs.sendMessage mark.tabId, + name: "showHUDforDuration", + text: "Jumped to global mark '#{req.markName}'." + duration: 1000 + else + chrome.tabs.sendMessage sender.tab.id, + name: "showHUDforDuration", + text: "Global mark not set: '#{req.markName}'." + duration: 1000 diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 316ab951..f3dfd465 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -1,45 +1,64 @@ -root = window.Marks = {} -root.activateCreateMode = -> - handlerStack.push keydown: (e) -> - keyChar = KeyboardUtils.getKeyChar(event) - return unless keyChar isnt "" +exit = (mode, continuation = null) -> + mode.exit() + continuation?() + false - if /[A-Z]/.test keyChar - chrome.runtime.sendMessage { - handler: 'createMark', - markName: keyChar - scrollX: window.scrollX, - scrollY: window.scrollY - }, -> HUD.showForDuration "Created global mark '#{keyChar}'", 1000 - else if /[a-z]/.test keyChar - [baseLocation, sep, hash] = window.location.href.split '#' - localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] = JSON.stringify - scrollX: window.scrollX, - scrollY: window.scrollY - HUD.showForDuration "Created local mark '#{keyChar}'", 1000 +Marks = + activateCreateMode: -> + mode = new Mode + name: "create-mark" + indicator: "Create mark?" + keypress: -> false + keyup: -> false + keydown: (event) -> + keyChar = KeyboardUtils.getKeyChar(event) + if /[A-Z]/.test keyChar + exit mode, -> + chrome.runtime.sendMessage + handler: 'createMark' + markName: keyChar + scrollX: window.scrollX + scrollY: window.scrollY + , -> HUD.showForDuration "Created global mark '#{keyChar}'.", 1000 + else if /[a-z]/.test keyChar + [baseLocation, sep, hash] = window.location.href.split '#' + localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] = JSON.stringify + scrollX: window.scrollX, + scrollY: window.scrollY + exit mode, -> HUD.showForDuration "Created local mark '#{keyChar}'.", 1000 + else if event.shiftKey + false + else + exit mode - @remove() + activateGotoMode: -> + mode = new Mode + name: "goto-mark" + indicator: "Go to mark?" + keypress: -> false + keyup: -> false + keydown: (event) -> + keyChar = KeyboardUtils.getKeyChar(event) + if /[A-Z]/.test keyChar + exit mode, -> + chrome.runtime.sendMessage + handler: 'gotoMark' + markName: keyChar + else if /[a-z]/.test keyChar + [baseLocation, sep, hash] = window.location.href.split '#' + markString = localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] + exit mode, -> + if markString? + mark = JSON.parse markString + window.scrollTo mark.scrollX, mark.scrollY + HUD.showForDuration "Jumped to local mark '#{keyChar}'", 1000 + else + HUD.showForDuration "Local mark not set: '#{keyChar}'.", 1000 + else if event.shiftKey + false + else + exit mode - false - -root.activateGotoMode = -> - handlerStack.push keydown: (e) -> - keyChar = KeyboardUtils.getKeyChar(event) - return unless keyChar isnt "" - - if /[A-Z]/.test keyChar - chrome.runtime.sendMessage - handler: 'gotoMark' - markName: keyChar - else if /[a-z]/.test keyChar - [baseLocation, sep, hash] = window.location.href.split '#' - markString = localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] - if markString? - mark = JSON.parse markString - window.scrollTo mark.scrollX, mark.scrollY - HUD.showForDuration "Jumped to local mark '#{keyChar}'", 1000 - - @remove() - - false +root = exports ? window +root.Marks = Marks -- cgit v1.2.3 From d3e0974640f8138c26b010bd63e3d9caa2ffdfef Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 11:27:24 +0100 Subject: Note global-marks fix in "release notes". --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5abe3196..c19e0857 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ Release Notes ([here](https://github.com/philc/vimium/wiki/Search-Completion) and [here](https://github.com/philc/vimium/wiki/Tips-and-Tricks#repeat-recent-queries)). - A much improved interface for custom search engines. -- Bug fixes: bookmarklets accessed from the vomnibar. +- Bug fixes: bookmarklets accessed from the vomnibar, global marks. 1.51 (2015-05-02) -- cgit v1.2.3 From 03ef7f2a8525e8fbfc67b04d7a0ce47522449d03 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 11:42:25 +0100 Subject: Refactor to avoid having to cover all keyboard event cases. It's pretty common that we want to suppress all keyboard events, so let's support that in modes.coffee, thereby simplifying handlers elsewhere. --- content_scripts/marks.coffee | 15 ++++----------- content_scripts/mode.coffee | 9 +++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index f3dfd465..8ba45fd4 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -2,15 +2,13 @@ exit = (mode, continuation = null) -> mode.exit() continuation?() - false Marks = activateCreateMode: -> mode = new Mode name: "create-mark" indicator: "Create mark?" - keypress: -> false - keyup: -> false + suppressAllKeyboardEvents: true keydown: (event) -> keyChar = KeyboardUtils.getKeyChar(event) if /[A-Z]/.test keyChar @@ -27,17 +25,14 @@ Marks = scrollX: window.scrollX, scrollY: window.scrollY exit mode, -> HUD.showForDuration "Created local mark '#{keyChar}'.", 1000 - else if event.shiftKey - false - else + else if not event.shiftKey exit mode activateGotoMode: -> mode = new Mode name: "goto-mark" indicator: "Go to mark?" - keypress: -> false - keyup: -> false + suppressAllKeyboardEvents: true keydown: (event) -> keyChar = KeyboardUtils.getKeyChar(event) if /[A-Z]/.test keyChar @@ -55,9 +50,7 @@ Marks = HUD.showForDuration "Jumped to local mark '#{keyChar}'", 1000 else HUD.showForDuration "Local mark not set: '#{keyChar}'.", 1000 - else if event.shiftKey - false - else + else if not event.shiftKey exit mode root = exports ? window diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index f631b4cd..b2019ef9 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -47,6 +47,15 @@ class Mode @id = "#{@name}-#{@count}" @log "activate:", @id + # If options.suppressAllKeyboardEvents is truthy, then all keyboard events are suppressed. This avoids + # the need for modes which block all keyboard events to 1) provide handlers for all keyboard events, + # and 2) worry about their return value. + if options.suppressAllKeyboardEvents + for type in [ "keydown", "keypress", "keyup" ] + do (type) -> + handler = options[type] + options[type] = (event) -> handler? event; false + @push keydown: @options.keydown || null keypress: @options.keypress || null -- cgit v1.2.3 From e79fe062bc84b1530ec266a12f9323aa53cb89e4 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 12:02:47 +0100 Subject: Fix tests for #1713... ... which is weird, because the tests are passing here. Let's see what Travis makes of this. --- content_scripts/mode.coffee | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index b2019ef9..cbcc15f7 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -50,11 +50,11 @@ class Mode # If options.suppressAllKeyboardEvents is truthy, then all keyboard events are suppressed. This avoids # the need for modes which block all keyboard events to 1) provide handlers for all keyboard events, # and 2) worry about their return value. - if options.suppressAllKeyboardEvents + if @options.suppressAllKeyboardEvents for type in [ "keydown", "keypress", "keyup" ] - do (type) -> - handler = options[type] - options[type] = (event) -> handler? event; false + do (type) => + handler = @options[type] + @options[type] = (event) -> handler? event; false @push keydown: @options.keydown || null -- cgit v1.2.3 From 291e7fd67de9e1c4bd0bc5048ab7344424f19b30 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 15:27:45 +0100 Subject: Re-implement Marks, incl `` binding. --- background_scripts/commands.coffee | 2 +- content_scripts/marks.coffee | 94 +++++++++++++++++++++------------- content_scripts/mode.coffee | 2 +- content_scripts/vimium_frontend.coffee | 17 ++++-- 4 files changed, 72 insertions(+), 43 deletions(-) diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index 64ec36be..b9ab274c 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -30,7 +30,7 @@ Commands = return options ?= [] - @keyToCommandRegistry[key] = extend { command, options }, @availableCommands[command] + @keyToCommandRegistry[key] = extend { command, options, key }, @availableCommands[command] # Lower-case the appropriate portions of named keys. # diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 8ba45fd4..fab509a7 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -1,57 +1,77 @@ -exit = (mode, continuation = null) -> - mode.exit() - continuation?() - Marks = + mode: null + previousPosition: null + + exit: (continuation = null) -> + @mode?.exit() + @mode = null + continuation?() + + # This returns the key which is used for storing mark locations in localStorage. + getLocationKey: (keyChar) -> + "vimiumMark|#{window.location.href.split('#')[0]}|#{keyChar}" + + showMessage: (message, keyChar) -> + HUD.showForDuration "#{message} \"#{keyChar}\".", 1000 + activateCreateMode: -> - mode = new Mode + @mode = new Mode name: "create-mark" - indicator: "Create mark?" + indicator: "Create mark..." suppressAllKeyboardEvents: true - keydown: (event) -> - keyChar = KeyboardUtils.getKeyChar(event) - if /[A-Z]/.test keyChar - exit mode, -> + keypress: (event) => + keyChar = String.fromCharCode event.charCode + # If is depressed, then it's a global mark, otherwise it's a local mark. This is consistent + # vim's [A-Z] for global marks, [a-z] for local marks. However, it also admits other non-Latin + # characters. + if event.shiftKey + @exit => chrome.runtime.sendMessage handler: 'createMark' markName: keyChar scrollX: window.scrollX scrollY: window.scrollY - , -> HUD.showForDuration "Created global mark '#{keyChar}'.", 1000 - else if /[a-z]/.test keyChar - [baseLocation, sep, hash] = window.location.href.split '#' - localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] = JSON.stringify - scrollX: window.scrollX, - scrollY: window.scrollY - exit mode, -> HUD.showForDuration "Created local mark '#{keyChar}'.", 1000 - else if not event.shiftKey - exit mode - - activateGotoMode: -> - mode = new Mode + , => @showMessage "Created global mark", keyChar + else + @exit => @markPosition keyChar + + markPosition: (keyChar = null) -> + markString = JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY + if keyChar? + localStorage[@getLocationKey keyChar] = markString + @showMessage "Created local mark", keyChar + else + @previousPosition = markString + + activateGotoMode: (registryEntry) -> + # We pick off the last character of the key sequence used to launch this command. Usually this is just "`". + # We then use that character, so together usually the sequence "``", to jump back to the previous + # position. The "previous position" is recorded below, and is registered via @markPosition() elsewhere + # for various other jump-like commands. + previousPositionKey = registryEntry.key[registryEntry.key.length-1..] + @mode = new Mode name: "goto-mark" - indicator: "Go to mark?" + indicator: "Go to mark..." suppressAllKeyboardEvents: true - keydown: (event) -> - keyChar = KeyboardUtils.getKeyChar(event) - if /[A-Z]/.test keyChar - exit mode, -> + keypress: (event) => + keyChar = String.fromCharCode event.charCode + if event.shiftKey + @exit -> chrome.runtime.sendMessage handler: 'gotoMark' markName: keyChar - else if /[a-z]/.test keyChar - [baseLocation, sep, hash] = window.location.href.split '#' - markString = localStorage["vimiumMark|#{baseLocation}|#{keyChar}"] - exit mode, -> + else + markString = + if keyChar == previousPositionKey then @previousPosition else localStorage[@getLocationKey keyChar] + @exit => if markString? - mark = JSON.parse markString - window.scrollTo mark.scrollX, mark.scrollY - HUD.showForDuration "Jumped to local mark '#{keyChar}'", 1000 + @markPosition() + position = JSON.parse markString + window.scrollTo position.scrollX, position.scrollY + @showMessage "Jumped to local mark", keyChar else - HUD.showForDuration "Local mark not set: '#{keyChar}'.", 1000 - else if not event.shiftKey - exit mode + @showMessage "Local mark not set", keyChar root = exports ? window root.Marks = Marks diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index cbcc15f7..22b6120f 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -54,7 +54,7 @@ class Mode for type in [ "keydown", "keypress", "keyup" ] do (type) => handler = @options[type] - @options[type] = (event) -> handler? event; false + @options[type] = (event) => handler? event; @stopBubblingAndFalse @push keydown: @options.keydown || null diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 7ad75514..9ff9b6db 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -241,9 +241,10 @@ unregisterFrame = -> tab_is_closing: DomUtils.isTopFrame() executePageCommand = (request) -> + commandType = request.command.split(".")[0] # Vomnibar commands are handled in the tab's main/top frame. They are handled even if Vimium is otherwise # disabled in the frame. - if request.command.split(".")[0] == "Vomnibar" + if commandType == "Vomnibar" if DomUtils.isTopFrame() # We pass the frameId from request. That's the frame which originated the request, so that's the frame # which should receive the focus when the vomnibar closes. @@ -254,7 +255,9 @@ executePageCommand = (request) -> # All other commands are handled in their frame (but only if Vimium is enabled). return unless frameId == request.frameId and isEnabledForUrl - if request.registryEntry.passCountToFunction + if commandType == "Marks" + Utils.invokeCommandString request.command, [request.registryEntry] + else if request.registryEntry.passCountToFunction Utils.invokeCommandString(request.command, [request.count]) else Utils.invokeCommandString(request.command) for i in [0...request.count] @@ -299,8 +302,12 @@ window.focusThisFrame = do -> setTimeout (-> highlightedFrameElement.remove()), 200 extend window, - scrollToBottom: -> Scroller.scrollTo "y", "max" - scrollToTop: -> Scroller.scrollTo "y", 0 + scrollToBottom: -> + Marks.markPosition() + Scroller.scrollTo "y", "max" + scrollToTop: -> + Marks.markPosition() + Scroller.scrollTo "y", 0 scrollToLeft: -> Scroller.scrollTo "x", 0 scrollToRight: -> Scroller.scrollTo "x", "max" scrollUp: -> Scroller.scrollBy "y", -1 * Settings.get("scrollStepSize") @@ -861,6 +868,7 @@ window.getFindModeQuery = (backwards) -> findModeQuery.parsedQuery findAndFocus = (backwards) -> + Marks.markPosition() query = getFindModeQuery backwards findModeQueryHasResults = @@ -1007,6 +1015,7 @@ findModeRestoreSelection = (range = findModeInitialRange) -> # Enters find mode. Returns the new find-mode instance. window.enterFindMode = (options = {}) -> + Marks.markPosition() # Save the selection, so performFindInPlace can restore it. findModeSaveSelection() findModeQuery = rawQuery: "" -- cgit v1.2.3 From 6fa88abbad70c19d5f9d69acff0e16844a2629b6 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 15:58:47 +0100 Subject: Note `` in README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c19e0857..18373f66 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,7 @@ Release Notes ([here](https://github.com/philc/vimium/wiki/Search-Completion) and [here](https://github.com/philc/vimium/wiki/Tips-and-Tricks#repeat-recent-queries)). - A much improved interface for custom search engines. +- Added "\`\`" to jump back to previous position after a jump. - Bug fixes: bookmarklets accessed from the vomnibar, global marks. 1.51 (2015-05-02) -- cgit v1.2.3 From 8dab334fa2fde9d4815ce0a12c0d2ab9dd44ff05 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 16:15:31 +0100 Subject: Also set previous position for before global mark movement. --- content_scripts/mode.coffee | 3 +-- content_scripts/vimium_frontend.coffee | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 22b6120f..86d3e011 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -52,8 +52,7 @@ class Mode # and 2) worry about their return value. if @options.suppressAllKeyboardEvents for type in [ "keydown", "keypress", "keyup" ] - do (type) => - handler = @options[type] + do (handler = @options[type]) => @options[type] = (event) => handler? event; @stopBubblingAndFalse @push diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 9ff9b6db..fec0dae2 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -266,7 +266,9 @@ executePageCommand = (request) -> setScrollPosition = (scrollX, scrollY) -> if (scrollX > 0 || scrollY > 0) - DomUtils.documentReady(-> window.scrollTo(scrollX, scrollY)) + DomUtils.documentReady -> + Marks.markPosition() + window.scrollTo scrollX, scrollY # # Called from the backend in order to change frame focus. -- cgit v1.2.3 From e005d3e5b7a06a949138109b2c57555f9a5db2b9 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:39:03 +0100 Subject: Refactor (to setPreviousPosition) to clarify Marks logic. --- content_scripts/marks.coffee | 25 +++++++++++++------------ content_scripts/vimium_frontend.coffee | 10 +++++----- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index fab509a7..9c6b1458 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -12,6 +12,12 @@ Marks = getLocationKey: (keyChar) -> "vimiumMark|#{window.location.href.split('#')[0]}|#{keyChar}" + getMarkString: -> + JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY + + setPreviousPosition: -> + @previousPosition = @getMarkString() + showMessage: (message, keyChar) -> HUD.showForDuration "#{message} \"#{keyChar}\".", 1000 @@ -34,21 +40,16 @@ Marks = scrollY: window.scrollY , => @showMessage "Created global mark", keyChar else - @exit => @markPosition keyChar - - markPosition: (keyChar = null) -> - markString = JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY - if keyChar? - localStorage[@getLocationKey keyChar] = markString - @showMessage "Created local mark", keyChar - else - @previousPosition = markString + @exit => + markString = JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY + localStorage[@getLocationKey keyChar] = @getMarkString() + @showMessage "Created local mark", keyChar activateGotoMode: (registryEntry) -> # We pick off the last character of the key sequence used to launch this command. Usually this is just "`". # We then use that character, so together usually the sequence "``", to jump back to the previous - # position. The "previous position" is recorded below, and is registered via @markPosition() elsewhere - # for various other jump-like commands. + # position. The "previous position" is recorded below, and is registered via @setPreviousPosition() + # elsewhere for various other jump-like commands. previousPositionKey = registryEntry.key[registryEntry.key.length-1..] @mode = new Mode name: "goto-mark" @@ -66,7 +67,7 @@ Marks = if keyChar == previousPositionKey then @previousPosition else localStorage[@getLocationKey keyChar] @exit => if markString? - @markPosition() + @setPreviousPosition() position = JSON.parse markString window.scrollTo position.scrollX, position.scrollY @showMessage "Jumped to local mark", keyChar diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index fec0dae2..f644ea35 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -267,7 +267,7 @@ executePageCommand = (request) -> setScrollPosition = (scrollX, scrollY) -> if (scrollX > 0 || scrollY > 0) DomUtils.documentReady -> - Marks.markPosition() + Marks.setPreviousPosition() window.scrollTo scrollX, scrollY # @@ -305,10 +305,10 @@ window.focusThisFrame = do -> extend window, scrollToBottom: -> - Marks.markPosition() + Marks.setPreviousPosition() Scroller.scrollTo "y", "max" scrollToTop: -> - Marks.markPosition() + Marks.setPreviousPosition() Scroller.scrollTo "y", 0 scrollToLeft: -> Scroller.scrollTo "x", 0 scrollToRight: -> Scroller.scrollTo "x", "max" @@ -870,7 +870,7 @@ window.getFindModeQuery = (backwards) -> findModeQuery.parsedQuery findAndFocus = (backwards) -> - Marks.markPosition() + Marks.setPreviousPosition() query = getFindModeQuery backwards findModeQueryHasResults = @@ -1017,7 +1017,7 @@ findModeRestoreSelection = (range = findModeInitialRange) -> # Enters find mode. Returns the new find-mode instance. window.enterFindMode = (options = {}) -> - Marks.markPosition() + Marks.setPreviousPosition() # Save the selection, so performFindInPlace can restore it. findModeSaveSelection() findModeQuery = rawQuery: "" -- cgit v1.2.3 From 474e986059cbf27ddbfb499f5b50b45bb41a3159 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:44:49 +0100 Subject: Add mark commands to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 18373f66..d55f7dff 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ Navigating the current page: yf copy a link url to the clipboard gf cycle forward to the next frame gF focus the main/top frame + ma, mA set local (global) mark "a" ("A") + `a, `A jump to local (global) mark "a" ("A") + `` jump back to position before previous jump -- before gg, G, n, N, / and `a Navigating to new pages: -- cgit v1.2.3 From 3d31289c1a246d230bc776c979d0d12c0a7f5e03 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:46:14 +0100 Subject: Add mark commands to README, fix spacing --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d55f7dff..26c4a986 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ Navigating the current page: yf copy a link url to the clipboard gf cycle forward to the next frame gF focus the main/top frame - ma, mA set local (global) mark "a" ("A") - `a, `A jump to local (global) mark "a" ("A") + ma, mA set local (global) mark "a" ("A") + `a, `A jump to local (global) mark "a" ("A") `` jump back to position before previous jump -- before gg, G, n, N, / and `a Navigating to new pages: -- cgit v1.2.3 From eb3d4c89e666f178ab0ecdd1e789cc3794ea71b5 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:48:06 +0100 Subject: Add mark commands to README, move to own section --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 26c4a986..31bb8c2a 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,6 @@ Navigating the current page: yf copy a link url to the clipboard gf cycle forward to the next frame gF focus the main/top frame - ma, mA set local (global) mark "a" ("A") - `a, `A jump to local (global) mark "a" ("A") - `` jump back to position before previous jump -- before gg, G, n, N, / and `a Navigating to new pages: @@ -82,6 +79,12 @@ Manipulating tabs: T search through your open tabs pin/unpin current tab +Using marks: + + ma, mA set local (global) mark "a" ("A") + `a, `A jump to local (global) mark "a" ("A") + `` jump back to position before previous jump -- before gg, G, n, N, / and `a + Additional advanced browsing commands: ]] Follow the link labeled 'next' or '>'. Helpful for browsing paginated sites. -- cgit v1.2.3 From 10df5755197d28f7a180160ecfec0e28f034ceeb Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:50:02 +0100 Subject: Add mark commands to README, wording --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 31bb8c2a..aa77e980 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,9 @@ Manipulating tabs: Using marks: - ma, mA set local (global) mark "a" ("A") - `a, `A jump to local (global) mark "a" ("A") - `` jump back to position before previous jump -- before gg, G, n, N, / and `a + ma, mA set local mark "a" (global mark "A") + `a, `A jump to local mark "a" (global mark "A") + `` jump back to the position before previous jump -- before gg, G, n, N, / and `a Additional advanced browsing commands: -- cgit v1.2.3 From 70892043f9e32b528f6debe829445585b2ec61e1 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:50:57 +0100 Subject: Add mark commands to README, wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa77e980..3bb9c6e7 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Using marks: ma, mA set local mark "a" (global mark "A") `a, `A jump to local mark "a" (global mark "A") - `` jump back to the position before previous jump -- before gg, G, n, N, / and `a + `` jump back to the position before the previous jump -- before gg, G, n, N, / or `a Additional advanced browsing commands: -- cgit v1.2.3 From 2251e082b776957f3c3d7476dfd6eefe31d023f1 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:51:49 +0100 Subject: Add mark commands to README, formatting --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bb9c6e7..ab6cb8b6 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,8 @@ Using marks: ma, mA set local mark "a" (global mark "A") `a, `A jump to local mark "a" (global mark "A") - `` jump back to the position before the previous jump -- before gg, G, n, N, / or `a + `` jump back to the position before the previous jump + -- that is, before the previous gg, G, n, N, / or `a Additional advanced browsing commands: -- cgit v1.2.3 From 6720f4c5a511e5e7b39e6a59e989353f7fb09792 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 18:57:39 +0100 Subject: Add mark commands to README, simple refactoring. --- content_scripts/marks.coffee | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 9c6b1458..73c019da 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -31,19 +31,17 @@ Marks = # If is depressed, then it's a global mark, otherwise it's a local mark. This is consistent # vim's [A-Z] for global marks, [a-z] for local marks. However, it also admits other non-Latin # characters. - if event.shiftKey - @exit => - chrome.runtime.sendMessage - handler: 'createMark' - markName: keyChar - scrollX: window.scrollX - scrollY: window.scrollY - , => @showMessage "Created global mark", keyChar - else - @exit => - markString = JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY - localStorage[@getLocationKey keyChar] = @getMarkString() - @showMessage "Created local mark", keyChar + @exit => + if event.shiftKey + chrome.runtime.sendMessage + handler: 'createMark' + markName: keyChar + scrollX: window.scrollX + scrollY: window.scrollY + , => @showMessage "Created global mark", keyChar + else + localStorage[@getLocationKey keyChar] = @getMarkString() + @showMessage "Created local mark", keyChar activateGotoMode: (registryEntry) -> # We pick off the last character of the key sequence used to launch this command. Usually this is just "`". -- cgit v1.2.3 From 457a976421107f9a67ac43090b0370366427bce1 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 19:13:17 +0100 Subject: Add mark commands to README, more simple refactoring. --- content_scripts/marks.coffee | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 73c019da..971feadf 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -54,16 +54,15 @@ Marks = indicator: "Go to mark..." suppressAllKeyboardEvents: true keypress: (event) => - keyChar = String.fromCharCode event.charCode - if event.shiftKey - @exit -> + @exit => + keyChar = String.fromCharCode event.charCode + if event.shiftKey chrome.runtime.sendMessage handler: 'gotoMark' markName: keyChar - else - markString = - if keyChar == previousPositionKey then @previousPosition else localStorage[@getLocationKey keyChar] - @exit => + else + markString = + if keyChar == previousPositionKey then @previousPosition else localStorage[@getLocationKey keyChar] if markString? @setPreviousPosition() position = JSON.parse markString -- cgit v1.2.3 From 1c4daf625949451178a349e93811b04a00472835 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 19:15:54 +0100 Subject: Modes, better comments. --- content_scripts/mode.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 86d3e011..9105fabb 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -48,8 +48,8 @@ class Mode @log "activate:", @id # If options.suppressAllKeyboardEvents is truthy, then all keyboard events are suppressed. This avoids - # the need for modes which block all keyboard events to 1) provide handlers for all keyboard events, - # and 2) worry about their return value. + # the need for modes which block all keyboard events 1) to provide handlers for all keyboard events, + # and 2) to worry about their return values. if @options.suppressAllKeyboardEvents for type in [ "keydown", "keypress", "keyup" ] do (handler = @options[type]) => -- cgit v1.2.3 From 23e415e60ceb25ddd30c65e2569d00a70f102681 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:09:57 +0100 Subject: Make layout consistent in README commands. --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ab6cb8b6..02e3827d 100644 --- a/README.md +++ b/README.md @@ -68,16 +68,16 @@ Navigating your history: Manipulating tabs: - J, gT go one tab left - K, gt go one tab right - g0 go to the first tab - g$ go to the last tab - t create tab - yt duplicate current tab - x close current tab - X restore closed tab (i.e. unwind the 'x' command) - T search through your open tabs - pin/unpin current tab + J, gT go one tab left + K, gt go one tab right + g0 go to the first tab + g$ go to the last tab + t create tab + yt duplicate current tab + x close current tab + X restore closed tab (i.e. unwind the 'x' command) + T search through your open tabs + pin/unpin current tab Using marks: -- cgit v1.2.3 From 42ca5182bbedff43405055bafdf46062e92cb4aa Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:14:16 +0100 Subject: README layout; avoid horizontal scroll bars. --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 02e3827d..ceeb3d24 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,13 @@ Navigating to new pages: Using find: - / enter find mode -- type your search query and hit enter to search or esc to cancel - See here for advanced usage (regular expressions): https://github.com/philc/vimium/wiki/Find-Mode + / enter find mode + -- type your search query and hit enter to search, or ESC to cancel n cycle forward to the next find match N cycle backward to the previous find match +For advanced usage, see [regular expressions](https://github.com/philc/vimium/wiki/Find-Mode) on the wiki. + Navigating your history: H go back in history @@ -84,7 +86,7 @@ Using marks: ma, mA set local mark "a" (global mark "A") `a, `A jump to local mark "a" (global mark "A") `` jump back to the position before the previous jump - -- that is, before the previous gg, G, n, N, / or `a + -- that is, before the previous gg, G, n, N, / or `a Additional advanced browsing commands: -- cgit v1.2.3 From a946fe96b53d65fbbd01992d4a12c4404a611f49 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:18:33 +0100 Subject: README; improve consistency of Esc usage. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ceeb3d24..4fce4053 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Navigating the current page: F open a link in a new tab r reload gs view source - i enter insert mode -- all commands will be ignored until you hit esc to exit + i enter insert mode -- all commands will be ignored until you hit Esc to exit yy copy the current url to the clipboard yf copy a link url to the clipboard gf cycle forward to the next frame @@ -57,7 +57,7 @@ Navigating to new pages: Using find: / enter find mode - -- type your search query and hit enter to search, or ESC to cancel + -- type your search query and hit enter to search, or Esc to cancel n cycle forward to the next find match N cycle backward to the previous find match @@ -90,8 +90,8 @@ Using marks: Additional advanced browsing commands: - ]] Follow the link labeled 'next' or '>'. Helpful for browsing paginated sites. - [[ Follow the link labeled 'previous' or '<'. Helpful for browsing paginated sites. + ]], [[ Follow the link labeled 'next' or '>' ('previous' or '<') + - helpful for browsing paginated sites open multiple links in a new tab gi focus the first (or n-th) text input box on the page gu go up one level in the URL hierarchy @@ -101,7 +101,7 @@ Additional advanced browsing commands: v enter visual mode; use p/P to paste-and-go, use y to yank V enter visual line mode -Vimium supports command repetition so, for example, hitting `5t` will open 5 tabs in rapid succession. `` (or +Vimium supports command repetition so, for example, hitting `5t` will open 5 tabs in rapid succession. `` (or ``) will clear any partial commands in the queue and will also exit insert and find modes. There are some advanced commands which aren't documented here; refer to the help dialog (type `?`) for a full @@ -383,7 +383,7 @@ does not support command repetition. - Bug fixes related to entering insert mode when the page first loads, and when focusing Flash embeds. - Added command listing to the Options page for easy reference. - `J` & `K` have reversed for tab switching: `J` goes left and `K` goes right. -- `` is now equivalent to ESC, to match the behavior of VIM. +- `` is now equivalent to `Esc`, to match the behavior of VIM. - `` and `` are now mapped to scroll down and up respectively. - The characters used for link hints are now configurable under Advanced Options. @@ -393,7 +393,7 @@ does not support command repetition. - Command `yy` to yank (copy) the current tab's url to the clipboard. - Better Linux support. - Fix for `Shift+F` link hints. -- `ESC` now clears the keyQueue. So, for example, hitting `g`, `ESC`, `g` will no longer scroll the page. +- `Esc` now clears the keyQueue. So, for example, hitting `g`, `Esc`, `g` will no longer scroll the page. 1.1 (2010-01-03) -- cgit v1.2.3 From 08446b6dc8d799e4c528050004312bd90c1bc351 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:23:24 +0100 Subject: README; correct inacurate informatiom. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 4fce4053..5c86223c 100644 --- a/README.md +++ b/README.md @@ -110,8 +110,7 @@ list. Custom Key Mappings ------------------- -You may remap or unmap any of the default key bindings in the "Key mappings" section under "Advanced Options" -on the options page. +You may remap or unmap any of the default key bindings in the "Custom key mappings" on the options page. Enter one of the following key mapping commands per line: -- cgit v1.2.3 From 6a5449ae02da9a9eb483380ed24401a1b5bd50cc Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:24:49 +0100 Subject: README; correct (syntactically) inacurate informatiom. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c86223c..47f09548 100644 --- a/README.md +++ b/README.md @@ -127,10 +127,11 @@ Examples: - `unmap ` removes any mapping for ctrl+d and restores Chrome's default behavior. - `unmap r` removes any mapping for the r key. -Available Vimium commands can be found via the "Show Available Commands" link near the key mapping box. The -command name appears to the right of the description in parenthesis. +Available Vimium commands can be found via the "Show available commands" link +near the key mapping box one the options page. The command name appears to the +right of the description in parenthesis. -You can add comments to your key mappings by starting a line with `"` or `#`. +You can add comments to key mappings by starting a line with `"` or `#`. The following special keys are available for mapping: -- cgit v1.2.3 From 304705a74b7de1f232c3186058ec4c31490f3c7f Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 3 Jun 2015 20:25:32 +0100 Subject: README; correct typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47f09548..c083c385 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Examples: - `unmap r` removes any mapping for the r key. Available Vimium commands can be found via the "Show available commands" link -near the key mapping box one the options page. The command name appears to the +near the key mapping box on the options page. The command name appears to the right of the description in parenthesis. You can add comments to key mappings by starting a line with `"` or `#`. -- cgit v1.2.3 From 8b8cc319cc02521a11e766e0d059a6fa53e5f4ae Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 07:11:03 +0100 Subject: README; tweak release notes. --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c083c385..0d3750d3 100644 --- a/README.md +++ b/README.md @@ -159,8 +159,10 @@ Release Notes ([here](https://github.com/philc/vimium/wiki/Search-Completion) and [here](https://github.com/philc/vimium/wiki/Tips-and-Tricks#repeat-recent-queries)). - A much improved interface for custom search engines. -- Added "\`\`" to jump back to previous position after a jump. -- Bug fixes: bookmarklets accessed from the vomnibar, global marks. +- Added \`\` to jump back to the previous position after selected jump-like movements. +- Bug fixes, including: + - Bookmarklets accessed from the vomnibar. + - Global marks on non-Windows platforms. 1.51 (2015-05-02) -- cgit v1.2.3 From 931d246e59389bd3070aa03bde4fada9f2ef9700 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 11:40:55 +0100 Subject: Global marks; move marks to chrome.storage. --- background_scripts/marks.coffee | 84 ++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index db9c4ae2..5336e8da 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -1,40 +1,56 @@ -root = window.Marks = {} -marks = {} +Marks = + marks: {} -root.create = (req, sender) -> - marks[req.markName] = - tabId: sender.tab.id - scrollX: req.scrollX - scrollY: req.scrollY + # This returns the key which is used for storing mark locations in chrome.storage.local. + getLocationKey: (markName) -> "vimiumGlobalMark|#{markName}" -chrome.tabs.onUpdated.addListener (tabId, changeInfo, tab) -> - if changeInfo.url? - removeMarksForTab tabId + create: (req, sender) -> + chrome.storage.local.get "vimiumSecret", (items) => + item = {} + item[@getLocationKey req.markName] = + vimiumSecret: items.vimiumSecret + tabId: sender.tab.id + url: sender.tab.url + scrollX: req.scrollX + scrollY: req.scrollY + console.log item + chrome.storage.local.set item -chrome.tabs.onRemoved.addListener (tabId, removeInfo) -> - # XXX(jez): what about restored tabs? - removeMarksForTab tabId + goto: (req, sender) -> + key = @getLocationKey req.markName + chrome.storage.local.get [ "vimiumSecret", key ], (items) => + markInfo = items[key] + if not markInfo + # The mark is not defined. + chrome.tabs.sendMessage sender.tab.id, + name: "showHUDforDuration", + text: "Global mark not set: '#{req.markName}'." + duration: 1000 + else if markInfo.vimiumSecret != items.vimiumSecret + # This is a different Vimium instantiation, so markInfo.tabId is definitely out of date. + @focusOrLaunch markInfo + else + # Check whether markInfo.tabId still exists. + { tabId, url, scrollX, scrollY } = markInfo + chrome.tabs.get tabId, (tab) => + if chrome.runtime.lastError or not tab + # The tab no longer exists. + @focusOrLaunch markInfo + else + # The original tab still exists. + chrome.tabs.update tabId, { selected: true }, -> + chrome.tabs.sendMessage tabId, + { name: "setScrollPosition", scrollX: scrollX, scrollY: scrollY }, -> + chrome.tabs.sendMessage tabId, + name: "showHUDforDuration", + text: "Jumped to global mark '#{req.markName}'." + duration: 1000 -removeMarksForTab = (id) -> - for markName, mark of marks - if mark.tabId is id - delete marks[markName] + # The tab we're trying to find no longer exists. Either find another tab with a matching URL and use it, or + # create a new tab. + focusOrLaunch: (info) -> + console.log info -root.goto = (req, sender) -> - mark = marks[req.markName] - if mark? - chrome.tabs.update mark.tabId, selected: true - chrome.tabs.sendMessage mark.tabId, - name: "setScrollPosition" - scrollX: mark.scrollX - scrollY: mark.scrollY - chrome.tabs.sendMessage mark.tabId, - name: "showHUDforDuration", - text: "Jumped to global mark '#{req.markName}'." - duration: 1000 - else - chrome.tabs.sendMessage sender.tab.id, - name: "showHUDforDuration", - text: "Global mark not set: '#{req.markName}'." - duration: 1000 +root = exports ? window +root.Marks = Marks -- cgit v1.2.3 From 278b03bd14ddad188000e87ec1f60f925f94697b Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 11:58:13 +0100 Subject: Global marks; find another (existing) tab if tabId has been removed. --- background_scripts/marks.coffee | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 5336e8da..05c8e579 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -14,7 +14,7 @@ Marks = url: sender.tab.url scrollX: req.scrollX scrollY: req.scrollY - console.log item + markName: req.markName chrome.storage.local.set item goto: (req, sender) -> @@ -32,25 +32,35 @@ Marks = @focusOrLaunch markInfo else # Check whether markInfo.tabId still exists. - { tabId, url, scrollX, scrollY } = markInfo - chrome.tabs.get tabId, (tab) => + chrome.tabs.get markInfo.tabId, (tab) => if chrome.runtime.lastError or not tab - # The tab no longer exists. + # The original tab no longer exists. @focusOrLaunch markInfo else # The original tab still exists. - chrome.tabs.update tabId, { selected: true }, -> - chrome.tabs.sendMessage tabId, - { name: "setScrollPosition", scrollX: scrollX, scrollY: scrollY }, -> - chrome.tabs.sendMessage tabId, - name: "showHUDforDuration", - text: "Jumped to global mark '#{req.markName}'." - duration: 1000 + @gotoPositionInTab markInfo + + gotoPositionInTab: ({ tabId, scrollX, scrollY, markName }) -> + chrome.tabs.update tabId, { selected: true }, -> + chrome.tabs.sendMessage tabId, + { name: "setScrollPosition", scrollX: scrollX, scrollY: scrollY }, -> + chrome.tabs.sendMessage tabId, + name: "showHUDforDuration", + text: "Jumped to global mark '#{markName}'." + duration: 1000 # The tab we're trying to find no longer exists. Either find another tab with a matching URL and use it, or # create a new tab. - focusOrLaunch: (info) -> - console.log info + focusOrLaunch: (markInfo) -> + chrome.windows.getAll { populate: true }, (windows) => + baseUrl = @getBaseUrl markInfo.url + for window in windows + for tab in window.tabs + if baseUrl == @getBaseUrl tab.url + # We have a matching tab. We'll use it. + return @gotoPositionInTab extend markInfo, tabId: tab.id + + getBaseUrl: (url) -> url.split("#")[0] root = exports ? window root.Marks = Marks -- cgit v1.2.3 From cb3d18a8068063050dd25f0db03777b564f1a548 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 12:16:06 +0100 Subject: Global marks; create a new tab, if necessary. --- background_scripts/main.coffee | 3 ++- background_scripts/marks.coffee | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 980f8e18..cbb70c6c 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -35,7 +35,8 @@ namedKeyRegex = /^(<(?:[amc]-.|(?:[amc]-)?[a-z0-9]{2,5})>)(.*)$/ # Event handlers selectionChangedHandlers = [] -tabLoadedHandlers = {} # tabId -> function() +# Note. tabLoadedHandlers handlers is exported for use also by "marks.coffee". +root.tabLoadedHandlers = {} # tabId -> function() # A secret, available only within the current instantiation of Vimium. The secret is big, likely unguessable # in practice, but less than 2^31. diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 05c8e579..94633c36 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -59,6 +59,11 @@ Marks = if baseUrl == @getBaseUrl tab.url # We have a matching tab. We'll use it. return @gotoPositionInTab extend markInfo, tabId: tab.id + # There is no existing matching tab, we'll have to create one. + chrome.tabs.create { url: @getBaseUrl(markInfo.url) }, (tab) => + # Note. tabLoadedHandlers is defined in "main.coffee". This handler will be called when the tab has + # is loaded, its DOM is ready and it registers with the background page. + tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id getBaseUrl: (url) -> url.split("#")[0] -- cgit v1.2.3 From 8e93f5bc28709b307f233f2326093ca47e0e4aba Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 12:35:31 +0100 Subject: Global marks; better comments and minor refactoring. --- background_scripts/marks.coffee | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 94633c36..c6c76dbb 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -1,17 +1,21 @@ Marks = - marks: {} - # This returns the key which is used for storing mark locations in chrome.storage.local. getLocationKey: (markName) -> "vimiumGlobalMark|#{markName}" + # Get the part of a URL we use for matching here (that is, everything up to the first anchor). + getBaseUrl: (url) -> url.split("#")[0] + + # Create a global mark. We record vimiumSecret with the mark so that we can tell later, when the mark is + # used, whether this is the original Vimium instantiation or a subsequent instantiation. This affects + # whether or not tabId can be considered valid. create: (req, sender) -> chrome.storage.local.get "vimiumSecret", (items) => item = {} item[@getLocationKey req.markName] = vimiumSecret: items.vimiumSecret tabId: sender.tab.id - url: sender.tab.url + url: @getBaseUrl sender.tab.url scrollX: req.scrollX scrollY: req.scrollY markName: req.markName @@ -31,14 +35,15 @@ Marks = # This is a different Vimium instantiation, so markInfo.tabId is definitely out of date. @focusOrLaunch markInfo else - # Check whether markInfo.tabId still exists. + # Check whether markInfo.tabId still exists. According to here (https://developer.chrome.com/extensions/tabs), + # tab Ids are unqiue within a Chrome session. So, if we find a match, we can use. chrome.tabs.get markInfo.tabId, (tab) => - if chrome.runtime.lastError or not tab - # The original tab no longer exists. - @focusOrLaunch markInfo - else + if not chrome.runtime.lastError and tab?.url and markInfo.url == @getBaseUrl tab.url # The original tab still exists. @gotoPositionInTab markInfo + else + # The original tab no longer exists. + @focusOrLaunch markInfo gotoPositionInTab: ({ tabId, scrollX, scrollY, markName }) -> chrome.tabs.update tabId, { selected: true }, -> @@ -49,23 +54,21 @@ Marks = text: "Jumped to global mark '#{markName}'." duration: 1000 - # The tab we're trying to find no longer exists. Either find another tab with a matching URL and use it, or - # create a new tab. + # The tab we're trying to find no longer exists. We either find another tab with a matching URL and use it, + # or we create a new tab. focusOrLaunch: (markInfo) -> chrome.windows.getAll { populate: true }, (windows) => - baseUrl = @getBaseUrl markInfo.url for window in windows for tab in window.tabs - if baseUrl == @getBaseUrl tab.url - # We have a matching tab. We'll use it. - return @gotoPositionInTab extend markInfo, tabId: tab.id + if markInfo.url == @getBaseUrl tab.url + # We have a matching tab: use it. + @gotoPositionInTab extend markInfo, tabId: tab.id + return # There is no existing matching tab, we'll have to create one. chrome.tabs.create { url: @getBaseUrl(markInfo.url) }, (tab) => - # Note. tabLoadedHandlers is defined in "main.coffee". This handler will be called when the tab has + # Note. tabLoadedHandlers is defined in "main.coffee". The handler below will be called when the tab # is loaded, its DOM is ready and it registers with the background page. tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id - getBaseUrl: (url) -> url.split("#")[0] - root = exports ? window root.Marks = Marks -- cgit v1.2.3 From e1e273ad35940c0aad44d20a4ff1ad15bd8bea3a Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 12:36:53 +0100 Subject: Global marks; add note to release notes in README. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0d3750d3..06e42567 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ Release Notes [here](https://github.com/philc/vimium/wiki/Tips-and-Tricks#repeat-recent-queries)). - A much improved interface for custom search engines. - Added \`\` to jump back to the previous position after selected jump-like movements. +- Global marks are now persistent (across tab closes and browser sessions) and synced. - Bug fixes, including: - Bookmarklets accessed from the vomnibar. - Global marks on non-Windows platforms. -- cgit v1.2.3 From a0b56c86461f9d40a839bc0a5cafb12e6a0e32ba Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 12:40:19 +0100 Subject: Global marks; move marks to chrome.storage.sync. --- background_scripts/marks.coffee | 50 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index c6c76dbb..ab39883b 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -1,6 +1,6 @@ Marks = - # This returns the key which is used for storing mark locations in chrome.storage.local. + # This returns the key which is used for storing mark locations in chrome.storage.sync. getLocationKey: (markName) -> "vimiumGlobalMark|#{markName}" # Get the part of a URL we use for matching here (that is, everything up to the first anchor). @@ -19,31 +19,33 @@ Marks = scrollX: req.scrollX scrollY: req.scrollY markName: req.markName - chrome.storage.local.set item + chrome.storage.sync.set item goto: (req, sender) -> - key = @getLocationKey req.markName - chrome.storage.local.get [ "vimiumSecret", key ], (items) => - markInfo = items[key] - if not markInfo - # The mark is not defined. - chrome.tabs.sendMessage sender.tab.id, - name: "showHUDforDuration", - text: "Global mark not set: '#{req.markName}'." - duration: 1000 - else if markInfo.vimiumSecret != items.vimiumSecret - # This is a different Vimium instantiation, so markInfo.tabId is definitely out of date. - @focusOrLaunch markInfo - else - # Check whether markInfo.tabId still exists. According to here (https://developer.chrome.com/extensions/tabs), - # tab Ids are unqiue within a Chrome session. So, if we find a match, we can use. - chrome.tabs.get markInfo.tabId, (tab) => - if not chrome.runtime.lastError and tab?.url and markInfo.url == @getBaseUrl tab.url - # The original tab still exists. - @gotoPositionInTab markInfo - else - # The original tab no longer exists. - @focusOrLaunch markInfo + chrome.storage.local.get "vimiumSecret", (items) => + vimiumSecret = items.vimiumSecret + key = @getLocationKey req.markName + chrome.storage.sync.get key, (items) => + markInfo = items[key] + if not markInfo + # The mark is not defined. + chrome.tabs.sendMessage sender.tab.id, + name: "showHUDforDuration", + text: "Global mark not set: '#{req.markName}'." + duration: 1000 + else if markInfo.vimiumSecret != items.vimiumSecret + # This is a different Vimium instantiation, so markInfo.tabId is definitely out of date. + @focusOrLaunch markInfo + else + # Check whether markInfo.tabId still exists. According to here (https://developer.chrome.com/extensions/tabs), + # tab Ids are unqiue within a Chrome session. So, if we find a match, we can use. + chrome.tabs.get markInfo.tabId, (tab) => + if not chrome.runtime.lastError and tab?.url and markInfo.url == @getBaseUrl tab.url + # The original tab still exists. + @gotoPositionInTab markInfo + else + # The original tab no longer exists. + @focusOrLaunch markInfo gotoPositionInTab: ({ tabId, scrollX, scrollY, markName }) -> chrome.tabs.update tabId, { selected: true }, -> -- cgit v1.2.3 From bd7671f6289eb35d5c2d4c2dca43d0a3c7a75c13 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 12:45:39 +0100 Subject: Global marks; better comments and fix typo. --- background_scripts/marks.coffee | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index ab39883b..f599cfe3 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -7,20 +7,23 @@ Marks = getBaseUrl: (url) -> url.split("#")[0] # Create a global mark. We record vimiumSecret with the mark so that we can tell later, when the mark is - # used, whether this is the original Vimium instantiation or a subsequent instantiation. This affects - # whether or not tabId can be considered valid. + # used, whether this is the original Vimium session or a subsequent session. This affects whether or not + # tabId can be considered valid. create: (req, sender) -> chrome.storage.local.get "vimiumSecret", (items) => item = {} item[@getLocationKey req.markName] = vimiumSecret: items.vimiumSecret - tabId: sender.tab.id + markName: req.markName url: @getBaseUrl sender.tab.url + tabId: sender.tab.id scrollX: req.scrollX scrollY: req.scrollY - markName: req.markName chrome.storage.sync.set item + # Goto a global mark. We try to find the original tab. If we can't find that, then we try to find another + # tab with the original URL, and use that. And if we can't find such an existing tab, then we create a new + # one. Whichever of those we do, we then set the scroll position to the original scroll position. goto: (req, sender) -> chrome.storage.local.get "vimiumSecret", (items) => vimiumSecret = items.vimiumSecret @@ -33,12 +36,12 @@ Marks = name: "showHUDforDuration", text: "Global mark not set: '#{req.markName}'." duration: 1000 - else if markInfo.vimiumSecret != items.vimiumSecret + else if markInfo.vimiumSecret != vimiumSecret # This is a different Vimium instantiation, so markInfo.tabId is definitely out of date. @focusOrLaunch markInfo else # Check whether markInfo.tabId still exists. According to here (https://developer.chrome.com/extensions/tabs), - # tab Ids are unqiue within a Chrome session. So, if we find a match, we can use. + # tab Ids are unqiue within a Chrome session. So, if we find a match, we can use it. chrome.tabs.get markInfo.tabId, (tab) => if not chrome.runtime.lastError and tab?.url and markInfo.url == @getBaseUrl tab.url # The original tab still exists. @@ -47,6 +50,7 @@ Marks = # The original tab no longer exists. @focusOrLaunch markInfo + # Focus an existing tab and scroll to the given position within it. gotoPositionInTab: ({ tabId, scrollX, scrollY, markName }) -> chrome.tabs.update tabId, { selected: true }, -> chrome.tabs.sendMessage tabId, @@ -67,7 +71,7 @@ Marks = @gotoPositionInTab extend markInfo, tabId: tab.id return # There is no existing matching tab, we'll have to create one. - chrome.tabs.create { url: @getBaseUrl(markInfo.url) }, (tab) => + chrome.tabs.create { url: @getBaseUrl markInfo.url }, (tab) => # Note. tabLoadedHandlers is defined in "main.coffee". The handler below will be called when the tab # is loaded, its DOM is ready and it registers with the background page. tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id -- cgit v1.2.3 From b356e50677e1ae7ba68e27b1b70e59744e129627 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 13:37:40 +0100 Subject: Exit marks modes on escape. --- content_scripts/marks.coffee | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 971feadf..fc30849a 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -25,6 +25,7 @@ Marks = @mode = new Mode name: "create-mark" indicator: "Create mark..." + exitOnEscape: true suppressAllKeyboardEvents: true keypress: (event) => keyChar = String.fromCharCode event.charCode @@ -52,6 +53,7 @@ Marks = @mode = new Mode name: "goto-mark" indicator: "Go to mark..." + exitOnEscape: true suppressAllKeyboardEvents: true keypress: (event) => @exit => -- cgit v1.2.3 From 5901968be865588c2444055f8e63916a22c01156 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 13:44:46 +0100 Subject: Global marks; use chrome.tabs.query. (As suggested by @mrmr1993 in #1716.) --- background_scripts/marks.coffee | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index f599cfe3..6692dc6f 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -63,18 +63,16 @@ Marks = # The tab we're trying to find no longer exists. We either find another tab with a matching URL and use it, # or we create a new tab. focusOrLaunch: (markInfo) -> - chrome.windows.getAll { populate: true }, (windows) => - for window in windows - for tab in window.tabs - if markInfo.url == @getBaseUrl tab.url - # We have a matching tab: use it. - @gotoPositionInTab extend markInfo, tabId: tab.id - return - # There is no existing matching tab, we'll have to create one. - chrome.tabs.create { url: @getBaseUrl markInfo.url }, (tab) => - # Note. tabLoadedHandlers is defined in "main.coffee". The handler below will be called when the tab - # is loaded, its DOM is ready and it registers with the background page. - tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id + chrome.tabs.query { url: markInfo.url }, (tabs) => + if 0 < tabs.length + # We have a matching tab: use it. + @gotoPositionInTab extend markInfo, tabId: tabs[0].id + else + # There is no existing matching tab, we'll have to create one. + chrome.tabs.create { url: @getBaseUrl markInfo.url }, (tab) => + # Note. tabLoadedHandlers is defined in "main.coffee". The handler below will be called when the tab + # is loaded, its DOM is ready and it registers with the background page. + tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id root = exports ? window root.Marks = Marks -- cgit v1.2.3 From fea6e507761e6870d9c240d0718cb96711891a3a Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 14:57:24 +0100 Subject: Global marks; prefer to re-use a tab in the current window. --- background_scripts/marks.coffee | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 6692dc6f..45697ac4 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -65,8 +65,9 @@ Marks = focusOrLaunch: (markInfo) -> chrome.tabs.query { url: markInfo.url }, (tabs) => if 0 < tabs.length - # We have a matching tab: use it. - @gotoPositionInTab extend markInfo, tabId: tabs[0].id + # We have a matching tab: use it (prefering, if there are more than one, one in the current window). + @pickTabInWindow tabs, (tab) => + @gotoPositionInTab extend markInfo, tabId: tab.id else # There is no existing matching tab, we'll have to create one. chrome.tabs.create { url: @getBaseUrl markInfo.url }, (tab) => @@ -74,5 +75,12 @@ Marks = # is loaded, its DOM is ready and it registers with the background page. tabLoadedHandlers[tab.id] = => @gotoPositionInTab extend markInfo, tabId: tab.id + # Given a list of tabs, pick one in the current window, if possible, otherwise just pick any. + pickTabInWindow: (tabs, continuation) -> + chrome.windows.getCurrent ({ id }) -> + tabsInWindow = tabs.filter (tab) -> tab.windowId == id + continuation tabsInWindow[0] ? tabs[0] + + root = exports ? window root.Marks = Marks -- cgit v1.2.3 From bc4f3ecac81fd8f174b8c3ad92a0998ada8f7992 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 15:14:10 +0100 Subject: Global marks; focus and only scroll in the main frame. --- background_scripts/marks.coffee | 1 - content_scripts/vimium_frontend.coffee | 16 ++++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 45697ac4..3a5af130 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -81,6 +81,5 @@ Marks = tabsInWindow = tabs.filter (tab) -> tab.windowId == id continuation tabsInWindow[0] ? tabs[0] - root = exports ? window root.Marks = Marks diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index f644ea35..dc083e6c 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -147,7 +147,7 @@ initializePreDomReady = -> focusFrame: (request) -> if (frameId == request.frameId) then focusThisFrame request refreshCompletionKeys: refreshCompletionKeys getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY - setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY + setScrollPosition: setScrollPosition executePageCommand: executePageCommand currentKeyQueue: (request) -> keyQueue = request.keyQueue @@ -264,11 +264,15 @@ executePageCommand = (request) -> refreshCompletionKeys(request) -setScrollPosition = (scrollX, scrollY) -> - if (scrollX > 0 || scrollY > 0) - DomUtils.documentReady -> - Marks.setPreviousPosition() - window.scrollTo scrollX, scrollY +# Set the scroll position (but only in the main frame). Some pages (like Facebook) get confused if you set +# the scroll position in all frames. +setScrollPosition = ({ scrollX, scrollY }) -> + if DomUtils.isTopFrame() + if scrollX > 0 or scrollY > 0 + DomUtils.documentReady -> + window.focus() + Marks.setPreviousPosition() + window.scrollTo scrollX, scrollY # # Called from the backend in order to change frame focus. -- cgit v1.2.3 From 9600d258cbadd80568e37637974172e7755ca28c Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 16:07:57 +0100 Subject: Global marks; only handle messages in main frame. On sites with several frames (e.g. Facebook), if we allow all of the frames to handle the setScrollPosition and showHudForDuration messages, then the focus ends up in an arbitrary frame. And, on Facebook, say, Vimium ends up broken until the focus is returned to the main frame. So, we only handle these messages in the main frame. --- content_scripts/vimium_frontend.coffee | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index dc083e6c..033bb2b3 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -142,7 +142,7 @@ initializePreDomReady = -> window.removeEventListener "focus", onFocus requestHandlers = - showHUDforDuration: (request) -> HUD.showForDuration request.text, request.duration + showHUDforDuration: handleShowHUDforDuration toggleHelpDialog: (request) -> toggleHelpDialog(request.dialogHtml, request.frameId) focusFrame: (request) -> if (frameId == request.frameId) then focusThisFrame request refreshCompletionKeys: refreshCompletionKeys @@ -264,13 +264,16 @@ executePageCommand = (request) -> refreshCompletionKeys(request) -# Set the scroll position (but only in the main frame). Some pages (like Facebook) get confused if you set -# the scroll position in all frames. +handleShowHUDforDuration = ({ text, duration }) -> + if DomUtils.isTopFrame() + DomUtils.documentReady -> HUD.showForDuration text, duration + setScrollPosition = ({ scrollX, scrollY }) -> if DomUtils.isTopFrame() - if scrollX > 0 or scrollY > 0 - DomUtils.documentReady -> - window.focus() + DomUtils.documentReady -> + window.focus() + document.body.focus() + if 0 < scrollX or 0 < scrollY Marks.setPreviousPosition() window.scrollTo scrollX, scrollY -- cgit v1.2.3 From 2473475367411fdeb051a6752d0059e337ad09e3 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 16:23:54 +0100 Subject: Use only ' and ` for jumping to previous position. As suggested by @mrmr1993 in #1716. --- content_scripts/marks.coffee | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index fc30849a..5bb35f1f 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -1,7 +1,8 @@ Marks = + previousPositionRegisters: [ "`", "'" ] + localRegisters: {} mode: null - previousPosition: null exit: (continuation = null) -> @mode?.exit() @@ -16,7 +17,8 @@ Marks = JSON.stringify scrollX: window.scrollX, scrollY: window.scrollY setPreviousPosition: -> - @previousPosition = @getMarkString() + markString = @getMarkString() + @localRegisters[reg] = markString for reg in @previousPositionRegisters showMessage: (message, keyChar) -> HUD.showForDuration "#{message} \"#{keyChar}\".", 1000 @@ -45,11 +47,6 @@ Marks = @showMessage "Created local mark", keyChar activateGotoMode: (registryEntry) -> - # We pick off the last character of the key sequence used to launch this command. Usually this is just "`". - # We then use that character, so together usually the sequence "``", to jump back to the previous - # position. The "previous position" is recorded below, and is registered via @setPreviousPosition() - # elsewhere for various other jump-like commands. - previousPositionKey = registryEntry.key[registryEntry.key.length-1..] @mode = new Mode name: "goto-mark" indicator: "Go to mark..." @@ -63,8 +60,7 @@ Marks = handler: 'gotoMark' markName: keyChar else - markString = - if keyChar == previousPositionKey then @previousPosition else localStorage[@getLocationKey keyChar] + markString = @localRegisters[keyChar] ? localStorage[@getLocationKey keyChar] if markString? @setPreviousPosition() position = JSON.parse markString -- cgit v1.2.3 From 89c3ab075994de9b11952784eb5752da445df576 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 4 Jun 2015 16:36:00 +0100 Subject: Unwind passing key and registry entry for marks. As suggested by @mrmr1993 in #1716. --- background_scripts/commands.coffee | 2 +- content_scripts/vimium_frontend.coffee | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee index b9ab274c..64ec36be 100644 --- a/background_scripts/commands.coffee +++ b/background_scripts/commands.coffee @@ -30,7 +30,7 @@ Commands = return options ?= [] - @keyToCommandRegistry[key] = extend { command, options, key }, @availableCommands[command] + @keyToCommandRegistry[key] = extend { command, options }, @availableCommands[command] # Lower-case the appropriate portions of named keys. # diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 033bb2b3..3055ecea 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -255,9 +255,7 @@ executePageCommand = (request) -> # All other commands are handled in their frame (but only if Vimium is enabled). return unless frameId == request.frameId and isEnabledForUrl - if commandType == "Marks" - Utils.invokeCommandString request.command, [request.registryEntry] - else if request.registryEntry.passCountToFunction + if request.registryEntry.passCountToFunction Utils.invokeCommandString(request.command, [request.count]) else Utils.invokeCommandString(request.command) for i in [0...request.count] -- cgit v1.2.3 From 50980718d848ca324b6fca0568e2fa7203d51d52 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Fri, 5 Jun 2015 05:04:56 +0100 Subject: Fix event suppression for Marks keyboard events. --- content_scripts/mode.coffee | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 9105fabb..ffabc111 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -48,12 +48,11 @@ class Mode @log "activate:", @id # If options.suppressAllKeyboardEvents is truthy, then all keyboard events are suppressed. This avoids - # the need for modes which block all keyboard events 1) to provide handlers for all keyboard events, - # and 2) to worry about their return values. + # the need for modes which suppress all keyboard events 1) to provide handlers for all of those events, + # or 2) to worry about event suppression and event-handler return values. if @options.suppressAllKeyboardEvents for type in [ "keydown", "keypress", "keyup" ] - do (handler = @options[type]) => - @options[type] = (event) => handler? event; @stopBubblingAndFalse + @options[type] = @alwaysSuppressEvent @options[type] @push keydown: @options.keydown || null @@ -179,6 +178,13 @@ class Mode # case), because they do not need to be concerned with the value they yield. alwaysContinueBubbling: handlerStack.alwaysContinueBubbling + # Shorthand for an event handler which always suppresses event propagation. + alwaysSuppressEvent: (handler = null) -> + (event) => + handler? event + DomUtils.suppressPropagation event + @stopBubblingAndFalse + # Activate a new instance of this mode, together with all of its original options (except its main # keybaord-event handlers; these will be recreated). cloneMode: -> -- cgit v1.2.3 From a143d2c81a9faaf383a05b0dae2f232db85959a2 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Fri, 5 Jun 2015 06:35:26 +0100 Subject: Global marks; fix indentation. --- content_scripts/marks.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 5bb35f1f..3b5814da 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -36,15 +36,15 @@ Marks = # characters. @exit => if event.shiftKey - chrome.runtime.sendMessage - handler: 'createMark' - markName: keyChar - scrollX: window.scrollX - scrollY: window.scrollY - , => @showMessage "Created global mark", keyChar + chrome.runtime.sendMessage + handler: 'createMark' + markName: keyChar + scrollX: window.scrollX + scrollY: window.scrollY + , => @showMessage "Created global mark", keyChar else - localStorage[@getLocationKey keyChar] = @getMarkString() - @showMessage "Created local mark", keyChar + localStorage[@getLocationKey keyChar] = @getMarkString() + @showMessage "Created local mark", keyChar activateGotoMode: (registryEntry) -> @mode = new Mode -- cgit v1.2.3 From 8eda31fb236b9506d577a25908d4e5334d3289d5 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Fri, 5 Jun 2015 07:07:02 +0100 Subject: Global marks; global marks are always recorded for the top frame only. With global marks, we may later create a new tab when the mark is used. When doing so, we should always be using the URL and scroll position of the top frame within the tab. For example, if a global mark is created from within the Hangouts frame of Google's Inbox and the mark is later used, then we should create a new tab for Inbox's URL and scroll position, not for the Hangout's URL and scroll position. --- background_scripts/marks.coffee | 18 +++++++++++++++--- content_scripts/marks.coffee | 7 +++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/background_scripts/marks.coffee b/background_scripts/marks.coffee index 3a5af130..6e5f08ba 100644 --- a/background_scripts/marks.coffee +++ b/background_scripts/marks.coffee @@ -11,15 +11,27 @@ Marks = # tabId can be considered valid. create: (req, sender) -> chrome.storage.local.get "vimiumSecret", (items) => - item = {} - item[@getLocationKey req.markName] = + markInfo = vimiumSecret: items.vimiumSecret markName: req.markName url: @getBaseUrl sender.tab.url tabId: sender.tab.id scrollX: req.scrollX scrollY: req.scrollY - chrome.storage.sync.set item + + if markInfo.scrollX? and markInfo.scrollY? + @saveMark markInfo + else + # The front-end frame hasn't provided the scroll position (because it's not the top frame within its + # tab). We need to ask the top frame what its scroll position is. (With the frame Id set to 0, below, + # the request will only be handled by the top frame within the tab.) + chrome.tabs.sendMessage sender.tab.id, name: "getScrollPosition", frameId: 0, (response) => + @saveMark extend markInfo, scrollX: response.scrollX, scrollY: response.scrollY + + saveMark: (markInfo) -> + item = {} + item[@getLocationKey markInfo.markName] = markInfo + chrome.storage.sync.set item # Goto a global mark. We try to find the original tab. If we can't find that, then we try to find another # tab with the original URL, and use that. And if we can't find such an existing tab, then we create a new diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index 3b5814da..f569e1ea 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -36,11 +36,14 @@ Marks = # characters. @exit => if event.shiftKey + # We record the current scroll position, but only if this is the top frame within the tab. + # Otherwise, we'll fetch the scroll position of the top frame from the background page later. + [ scrollX, scrollY ] = [ window.scrollX, window.scrollY ] if DomUtils.isTopFrame() chrome.runtime.sendMessage handler: 'createMark' markName: keyChar - scrollX: window.scrollX - scrollY: window.scrollY + scrollX: scrollX + scrollY: scrollY , => @showMessage "Created global mark", keyChar else localStorage[@getLocationKey keyChar] = @getMarkString() -- cgit v1.2.3 From 83fc0e58f6139ff5a1ae37fc300ea647da079171 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Fri, 5 Jun 2015 07:14:50 +0100 Subject: Global marks; always treat ` and ' as local marks. On some keyboards (who knows?) "`" or "'" could be shift keys. In this case, with the previous implementation, these would be treated as global marks and `` would be unusable. This commit fixes that problem. --- content_scripts/marks.coffee | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/content_scripts/marks.coffee b/content_scripts/marks.coffee index f569e1ea..067d05a8 100644 --- a/content_scripts/marks.coffee +++ b/content_scripts/marks.coffee @@ -23,6 +23,12 @@ Marks = showMessage: (message, keyChar) -> HUD.showForDuration "#{message} \"#{keyChar}\".", 1000 + # If is depressed, then it's a global mark, otherwise it's a local mark. This is consistent + # vim's [A-Z] for global marks and [a-z] for local marks. However, it also admits other non-Latin + # characters. The exceptions are "`" and "'", which are always considered local marks. + isGlobalMark: (event, keyChar) -> + event.shiftKey and keyChar not in @previousPositionRegisters + activateCreateMode: -> @mode = new Mode name: "create-mark" @@ -31,11 +37,8 @@ Marks = suppressAllKeyboardEvents: true keypress: (event) => keyChar = String.fromCharCode event.charCode - # If is depressed, then it's a global mark, otherwise it's a local mark. This is consistent - # vim's [A-Z] for global marks, [a-z] for local marks. However, it also admits other non-Latin - # characters. @exit => - if event.shiftKey + if @isGlobalMark event, keyChar # We record the current scroll position, but only if this is the top frame within the tab. # Otherwise, we'll fetch the scroll position of the top frame from the background page later. [ scrollX, scrollY ] = [ window.scrollX, window.scrollY ] if DomUtils.isTopFrame() @@ -58,7 +61,7 @@ Marks = keypress: (event) => @exit => keyChar = String.fromCharCode event.charCode - if event.shiftKey + if @isGlobalMark event, keyChar chrome.runtime.sendMessage handler: 'gotoMark' markName: keyChar -- cgit v1.2.3