aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2015-05-31 09:52:50 +0100
committerStephen Blott2015-05-31 09:52:50 +0100
commitbd07321766056cccd083aa69254abc8146bd5266 (patch)
tree59a9300cd4a0806f2f6072db406e00edf80674b4
parent8b0c610fb68573dbd839133fbc315521db6161f6 (diff)
parent5930a6e3510f2bd052771601581aa410728d68e3 (diff)
downloadvimium-bd07321766056cccd083aa69254abc8146bd5266.tar.bz2
Merge pull request #1697 from smblott-github/vomnibar-map-with-prepopulated-text
Direct keyboard access to custom-search engines via keyword flag
-rw-r--r--background_scripts/commands.coffee64
-rw-r--r--background_scripts/completion.coffee24
-rw-r--r--background_scripts/main.coffee14
-rw-r--r--content_scripts/vimium_frontend.coffee5
-rw-r--r--content_scripts/vomnibar.coffee34
-rw-r--r--lib/utils.coffee33
-rw-r--r--pages/vomnibar.coffee3
-rw-r--r--tests/dom_tests/vomnibar_test.coffee1
8 files changed, 101 insertions, 77 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index 5857665c..bf892c1a 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -24,21 +24,13 @@ Commands =
noRepeat: options.noRepeat
repeatLimit: options.repeatLimit
- mapKeyToCommand: (key, command) ->
+ mapKeyToCommand: ({ key, command, options }) ->
unless @availableCommands[command]
- console.log(command, "doesn't exist!")
+ console.log command, "doesn't exist!"
return
- commandDetails = @availableCommands[command]
-
- @keyToCommandRegistry[key] =
- command: command
- isBackgroundCommand: commandDetails.isBackgroundCommand
- passCountToFunction: commandDetails.passCountToFunction
- noRepeat: commandDetails.noRepeat
- repeatLimit: commandDetails.repeatLimit
-
- unmapKey: (key) -> delete @keyToCommandRegistry[key]
+ options ?= []
+ @keyToCommandRegistry[key] = extend { command, options }, @availableCommands[command]
# Lower-case the appropriate portions of named keys.
#
@@ -54,37 +46,29 @@ Commands =
"<" + (if optionalPrefix then optionalPrefix else "") + keyName.toLowerCase() + ">")
parseCustomKeyMappings: (customKeyMappings) ->
- lines = customKeyMappings.split("\n")
-
- for line in lines
- continue if (line[0] == "\"" || line[0] == "#")
- splitLine = line.replace(/\s+$/, "").split(/\s+/)
-
- lineCommand = splitLine[0]
-
- if (lineCommand == "map")
- continue if (splitLine.length != 3)
- key = @normalizeKey(splitLine[1])
- vimiumCommand = splitLine[2]
-
- continue unless @availableCommands[vimiumCommand]
-
- console.log("Mapping", key, "to", vimiumCommand)
- @mapKeyToCommand(key, vimiumCommand)
- else if (lineCommand == "unmap")
- continue if (splitLine.length != 2)
-
- key = @normalizeKey(splitLine[1])
- console.log("Unmapping", key)
- @unmapKey(key)
- else if (lineCommand == "unmapAll")
- @keyToCommandRegistry = {}
+ for line in customKeyMappings.split "\n"
+ unless line[0] == "\"" or line[0] == "#"
+ tokens = line.replace(/\s+$/, "").split /\s+/
+ switch tokens[0]
+ when "map"
+ [ _, key, command, options... ] = tokens
+ if command? and @availableCommands[command]
+ key = @normalizeKey key
+ console.log "Mapping", key, "to", command
+ @mapKeyToCommand { key, command, options }
+
+ when "unmap"
+ if tokens.length == 2
+ key = @normalizeKey tokens[1]
+ console.log "Unmapping", key
+ delete @keyToCommandRegistry[key]
+
+ when "unmapAll"
+ @keyToCommandRegistry = {}
clearKeyMappingsAndSetDefaults: ->
@keyToCommandRegistry = {}
-
- for key of defaultKeyMappings
- @mapKeyToCommand(key, defaultKeyMappings[key])
+ @mapKeyToCommand { key, command } for key, command of defaultKeyMappings
# An ordered listing of all available commands, grouped by type. This is the order they will
# be shown in the help page.
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index bae73b8d..c83066a6 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -413,7 +413,6 @@ class TabCompleter
class SearchEngineCompleter
@debug: false
- searchEngines: null
previousSuggestions: null
cancel: ->
@@ -422,7 +421,7 @@ class SearchEngineCompleter
# This looks up the custom search engine and, if one is found, notes it and removes its keyword from the
# query terms.
preprocessRequest: (request) ->
- @searchEngines.use (engines) =>
+ SearchEngines.use (engines) =>
{ queryTerms, query } = request
extend request, searchEngines: engines, keywords: key for own key of engines
keyword = queryTerms[0]
@@ -436,26 +435,7 @@ class SearchEngineCompleter
refresh: (port) ->
@previousSuggestions = {}
- # Parse the search-engine configuration.
- @searchEngines = new AsyncDataFetcher (callback) ->
- engines = {}
- for line in Settings.get("searchEngines").split "\n"
- line = line.trim()
- continue if /^[#"]/.test line
- tokens = line.split /\s+/
- continue unless 2 <= tokens.length
- keyword = tokens[0].split(":")[0]
- url = tokens[1]
- description = tokens[2..].join(" ") || "search (#{keyword})"
- continue unless Utils.hasFullUrlPrefix url
- engines[keyword] =
- keyword: keyword
- searchUrl: url
- description: description
- searchUrlPrefix: url.split("%s")[0]
-
- callback engines
-
+ SearchEngines.refreshAndUse Settings.get("searchEngines"), (engines) ->
# Let the front-end vomnibar know the search-engine keywords. It needs to know them so that, when the
# query goes from "w" to "w ", the vomnibar can synchronously launch the next filter() request (which
# avoids an ugly delay/flicker).
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index edcdf3b2..99a5672b 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -558,13 +558,13 @@ checkKeyQueue = (keysToCheck, tabId, frameId) ->
if runCommand
if not registryEntry.isBackgroundCommand
- chrome.tabs.sendMessage(tabId,
- name: "executePageCommand",
- command: registryEntry.command,
- frameId: frameId,
- count: count,
- passCountToFunction: registryEntry.passCountToFunction,
- completionKeys: generateCompletionKeys(""))
+ chrome.tabs.sendMessage tabId,
+ name: "executePageCommand"
+ command: registryEntry.command
+ frameId: frameId
+ count: count
+ completionKeys: generateCompletionKeys ""
+ registryEntry: registryEntry
refreshedCompletionKeys = true
else
if registryEntry.passCountToFunction
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index b7acf433..c8c83029 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -62,6 +62,7 @@ settings =
helpDialog_showAdvancedCommands: null
smoothScroll: null
grabBackFocus: null
+ searchEngines: null
init: ->
@port = chrome.runtime.connect name: "settings"
@@ -307,14 +308,14 @@ executePageCommand = (request) ->
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.
- Utils.invokeCommandString request.command, [ request.frameId ]
+ Utils.invokeCommandString request.command, [ request.frameId, request.registryEntry ]
refreshCompletionKeys request
return
# All other commands are handled in their frame (but only if Vimium is enabled).
return unless frameId == request.frameId and isEnabledForUrl
- if (request.passCountToFunction)
+ if request.registryEntry.passCountToFunction
Utils.invokeCommandString(request.command, [request.count])
else
Utils.invokeCommandString(request.command) for i in [0...request.count]
diff --git a/content_scripts/vomnibar.coffee b/content_scripts/vomnibar.coffee
index 2529c077..4bd8e8fd 100644
--- a/content_scripts/vomnibar.coffee
+++ b/content_scripts/vomnibar.coffee
@@ -4,14 +4,36 @@
Vomnibar =
vomnibarUI: null
+ # Parse any additional options from the command's registry entry. Currently, this only includes a flag of
+ # the form "keyword=X", for direct activation of a custom search engine.
+ parseRegistryEntry: (registryEntry = { options: [] }, callback = null) ->
+ options = {}
+ searchEngines = settings.get("searchEngines") ? ""
+ SearchEngines.refreshAndUse searchEngines, (engines) ->
+ for option in registryEntry.options
+ [ key, value ] = option.split "="
+ switch key
+ when "keyword"
+ if value? and engines[value]?
+ options.keyword = value
+ else
+ console.log "Vimium configuration error: no such custom search engine: #{option}."
+ else
+ console.log "Vimium configuration error: unused flag: #{option}."
+
+ callback? options
+
# sourceFrameId here (and below) is the ID of the frame from which this request originates, which may be different
# from the current frame.
- activate: (sourceFrameId) -> @open sourceFrameId, {completer:"omni"}
- activateInNewTab: (sourceFrameId) -> @open sourceFrameId, {
- completer: "omni"
- selectFirst: false
- newTab: true
- }
+
+ activate: (sourceFrameId, registryEntry) ->
+ @parseRegistryEntry registryEntry, (options) =>
+ @open sourceFrameId, extend options, completer:"omni"
+
+ activateInNewTab: (sourceFrameId, registryEntry) ->
+ @parseRegistryEntry registryEntry, (options) =>
+ @open sourceFrameId, extend options, completer:"omni", newTab: true
+
activateTabSelection: (sourceFrameId) -> @open sourceFrameId, {
completer: "tabs"
selectFirst: true
diff --git a/lib/utils.coffee b/lib/utils.coffee
index 835b0359..93045f32 100644
--- a/lib/utils.coffee
+++ b/lib/utils.coffee
@@ -235,6 +235,38 @@ Utils =
# Like Nodejs's nextTick.
nextTick: (func) -> @setTimeout 0, func
+# Utility for parsing and using the custom search-engine configuration. We re-use the previous parse if the
+# search-engine configuration is unchanged.
+SearchEngines =
+ previousSearchEngines: null
+ searchEngines: null
+
+ refresh: (searchEngines) ->
+ unless @previousSearchEngines? and searchEngines == @previousSearchEngines
+ @previousSearchEngines = searchEngines
+ @searchEngines = new AsyncDataFetcher (callback) ->
+ engines = {}
+ for line in searchEngines.split "\n"
+ line = line.trim()
+ continue if /^[#"]/.test line
+ tokens = line.split /\s+/
+ continue unless 2 <= tokens.length
+ keyword = tokens[0].split(":")[0]
+ searchUrl = tokens[1]
+ description = tokens[2..].join(" ") || "search (#{keyword})"
+ continue unless Utils.hasFullUrlPrefix searchUrl
+ engines[keyword] = { keyword, searchUrl, description }
+
+ callback engines
+
+ # Use the parsed search-engine configuration, possibly asynchronously.
+ use: (callback) ->
+ @searchEngines.use callback
+
+ # Both set (refresh) the search-engine configuration and use it at the same time.
+ refreshAndUse: (searchEngines, callback) ->
+ @refresh searchEngines
+ @use callback
# This creates a new function out of an existing function, where the new function takes fewer arguments. This
# allows us to pass around functions instead of functions + a partial list of arguments.
@@ -332,6 +364,7 @@ class JobRunner
root = exports ? window
root.Utils = Utils
+root.SearchEngines = SearchEngines
root.SimpleCache = SimpleCache
root.AsyncDataFetcher = AsyncDataFetcher
root.JobRunner = JobRunner
diff --git a/pages/vomnibar.coffee b/pages/vomnibar.coffee
index 71f22900..d5659fdc 100644
--- a/pages/vomnibar.coffee
+++ b/pages/vomnibar.coffee
@@ -17,6 +17,7 @@ Vomnibar =
query: ""
newTab: false
selectFirst: false
+ keyword: null
extend options, userOptions
extend options, refreshInterval: if options.completer == "omni" then 150 else 0
@@ -28,6 +29,7 @@ Vomnibar =
@vomnibarUI.setRefreshInterval options.refreshInterval
@vomnibarUI.setForceNewTab options.newTab
@vomnibarUI.setQuery options.query
+ @vomnibarUI.setKeyword options.keyword
@vomnibarUI.update true
hide: -> @vomnibarUI?.hide()
@@ -40,6 +42,7 @@ class VomnibarUI
@initDom()
setQuery: (query) -> @input.value = query
+ setKeyword: (keyword) -> @customSearchMode = keyword
setInitialSelectionValue: (@initialSelectionValue) ->
setRefreshInterval: (@refreshInterval) ->
setForceNewTab: (@forceNewTab) ->
diff --git a/tests/dom_tests/vomnibar_test.coffee b/tests/dom_tests/vomnibar_test.coffee
index 380175f3..3eda6234 100644
--- a/tests/dom_tests/vomnibar_test.coffee
+++ b/tests/dom_tests/vomnibar_test.coffee
@@ -1,4 +1,5 @@
vomnibarFrame = null
+SearchEngines.refresh ""
context "Keep selection within bounds",