From 5e5a112c0be000a7d8e12a6abbb347d70007d6fb Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 10 Oct 2010 03:27:01 -0400 Subject: [PATCH 1/5] Fix some help formatting problems. --- common/content/help.xsl | 4 ++-- common/locale/en-US/cmdline.xml | 6 +++--- common/locale/en-US/map.xml | 6 +++--- common/locale/en-US/marks.xml | 6 +++--- common/locale/en-US/options.xml | 26 +++++++++++++------------- common/locale/en-US/pattern.xml | 4 ++-- common/locale/en-US/styling.xml | 9 ++++++--- common/locale/en-US/tabs.xml | 2 +- common/locale/en-US/various.xml | 9 ++++----- 9 files changed, 37 insertions(+), 35 deletions(-) diff --git a/common/content/help.xsl b/common/content/help.xsl index 727e21ed..908ae3ec 100644 --- a/common/content/help.xsl +++ b/common/content/help.xsl @@ -352,8 +352,8 @@
- - + + diff --git a/common/locale/en-US/cmdline.xml b/common/locale/en-US/cmdline.xml index 825f56b1..4e40f784 100644 --- a/common/locale/en-US/cmdline.xml +++ b/common/locale/en-US/cmdline.xml @@ -164,7 +164,7 @@ given in a single command line and will be executed consecutively. | can be included as an argument to a command by escaping it with a backslash. E.g. - :map \| :echo "bar" + :map \| :echo bar Several commands process the entire command line string literally. These commands will include any | as part of their @@ -239,7 +239,7 @@ optional quoting characters are available:

-
+
\
This is the most basic quoting character. When it is encountered @@ -261,7 +261,7 @@ included by preceding it with a backslash. Any other occurrence of a backslash starts an escape sequence as in JavaScript strings. Among the available escape sequences are: -
+
\n
A newline character.
\t
A tab character.
\0nn
Where each n is a digit between 0 and 7, represents an octal character code.
diff --git a/common/locale/en-US/map.xml b/common/locale/en-US/map.xml index a1c8a1b9..02aac3c1 100644 --- a/common/locale/en-US/map.xml +++ b/common/locale/en-US/map.xml @@ -48,7 +48,7 @@ common modes,

-
+
n
Normal mode: When browsing normally
v
Visual mode: When selecting text with the cursor keys
i
Insert mode: When interacting with text fields on a website
@@ -105,7 +105,7 @@ Any of the map commands may be given the following options:

-
+
-builtin
Execute this mapping as if there were no user-defined mappings (short name -b)
@@ -290,7 +290,7 @@ sequences are interpreted as described,

-
+
xc
Type the ‘X’ key followed by the ‘C’ key
diff --git a/common/locale/en-US/marks.xml b/common/locale/en-US/marks.xml index bf457cf3..04958499 100644 --- a/common/locale/en-US/marks.xml +++ b/common/locale/en-US/marks.xml @@ -45,7 +45,7 @@

The following options are available,

-
+
-keyword
A keyword which may be used to open the bookmark via @@ -124,7 +124,7 @@

The bookmarks may also be filtered via the following options,

-
+
-keyword
The bookmark's keyword (short name -k). @@ -273,7 +273,7 @@

The pages may also be filtered via the following options,

-
+
-max
The maximum number of items to list or open diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml index e3159e3a..d132dd66 100644 --- a/common/locale/en-US/options.xml +++ b/common/locale/en-US/options.xml @@ -25,8 +25,8 @@ achieve special effects. These options come in 8 forms:

-
-
boolean
Can only be on or off
+
+
boolean
Can only be on or off
number
A numeric value
string
A string value
@@ -44,7 +44,7 @@
stringmap
-
A comma-separated list of key-value pairs, e.g., key:val,foo:bar
+
A comma-separated list of key-value pairs, e.g., key:val,foo:bar
regexlist
@@ -430,7 +430,7 @@

Items which are completed at the :open prompts. Available items:

-
+
s
Search engines and keyword URLs
f
Local files
l
&dactyl.host; location bar entries (bookmarks and history sorted in an intelligent way)
@@ -598,7 +598,7 @@

Possible values:

-
+
0
Follow the first hint as soon as typed text uniquely identifies it.
1
Follow the selected hint on .
2
Follow the selected hint on only if it's been -selected.
@@ -630,7 +630,7 @@

Supported characters:

-
+
B
Bookmark bar
C
Always show the command-line outside of the status line
M
Always show messages outside of the status line
@@ -676,7 +676,7 @@ given, and the first successful value is used.

-
+
value
The hint is the value displayed in a text input, or the selected option for a drop-down.
label
The value of an explicit label for the input; this will not match most manually added labels that are found on sites.
name
The name of the input will be used; although the name is not designed for user consumption, it is frequently very similar to the label.
@@ -869,7 +869,7 @@

Possible values:

-
+
0
Never
1
Only if there are multiple windows
2
Always
@@ -1045,7 +1045,7 @@

Items available by default:

-
+
g
General info
f
Feeds
m
Meta tags
@@ -1073,7 +1073,7 @@

Possible values are:

-
+
tab
Open pop-ups in a new tab
window
Open pop-ups in a new window
resized
Open resized pop-ups in a new window
@@ -1185,7 +1185,7 @@ deleted. The value must be of the one of:

-
+
all
Everything
session
The current session
nm
Past n Minutes
@@ -1258,7 +1258,7 @@

Possible values are:

-
+
0
Don't show link destination
1
Show the link's destination in the status-line
2
Show the link's destination in the command-line
@@ -1276,7 +1276,7 @@

Possible values are:

-
+
0
Never show tab line
1
Show tab line only if more than one tab is open
2
Always show tab line
diff --git a/common/locale/en-US/pattern.xml b/common/locale/en-US/pattern.xml index f4448ecb..5d5cb129 100644 --- a/common/locale/en-US/pattern.xml +++ b/common/locale/en-US/pattern.xml @@ -55,7 +55,7 @@ appear is the one that takes effect.

-
+
\c
Perform case insensitive search (default if ignorecase is set).
\C
Perform case sensitive search
\l
Search only in links, as defined by hinttags. (default if linksearch is set).
@@ -66,7 +66,7 @@ Additionally, if the /Find Bar/ extension is installed, the following flags may be used,

-
+
\r
Process the entire pattern as a regular expression.
\R
Process the entire pattern as an ordinary string.
diff --git a/common/locale/en-US/styling.xml b/common/locale/en-US/styling.xml index 3c3d98f0..f5320164 100644 --- a/common/locale/en-US/styling.xml +++ b/common/locale/en-US/styling.xml @@ -197,27 +197,30 @@ :styleenable :stylee :styenable :stye + :styledisable -name=name -index=index filter css -

Enable any matching styles. Arguments are the same as for :delstyle.

+

Enable any matching styles. Arguments are the same as for :delstyle

:styledisable :styled :stydisable :styd + :styleenable -name=name -index=index filter css -

Disable any matching styles. Arguments are the same as for :delstyle.

+

Disable any matching styles. Arguments are the same as for :delstyle

:styletoggle :stylet :stytoggle :styt + :styletoggle -name=name -index=index filter css -

Toggle any matching styles. Arguments are the same as for :delstyle.

+

Toggle any matching styles. Arguments are the same as for :delstyle

diff --git a/common/locale/en-US/tabs.xml b/common/locale/en-US/tabs.xml index 99760426..9beab050 100644 --- a/common/locale/en-US/tabs.xml +++ b/common/locale/en-US/tabs.xml @@ -40,7 +40,7 @@

A buffer may be marked with one of the following indicators:

-
+
%
The current buffer
#
The alternate buffer for :e # and
diff --git a/common/locale/en-US/various.xml b/common/locale/en-US/various.xml index 31aceb41..bdcc3af2 100644 --- a/common/locale/en-US/various.xml +++ b/common/locale/en-US/various.xml @@ -122,16 +122,15 @@

- &dactyl.appName; fully supports &dactyl.host;'s private browsing mode. When in private browsing mode, no data other than Bookmarks and QuickMarks - are written to disk. Further, upon exiting private mode, all new data, - including command-line history, local and URL marks, and macros, - are purged. For more information, see private. + are written to disk. Further, upon exiting private mode, all newly + accumulated data, including command-line history, local and URL + marks, and macros, are purged from memory. For more information, see + private.

- In addition to private mode, &dactyl.appName; provides a comprehensive facility for clearing any potentially sensitive data generated by either &dactyl.appName; or &dactyl.host;. It directly integrates with From 7a2d80e6751ffe77e6ee9526f5635189fc1e06cf Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 10 Oct 2010 15:06:11 -0400 Subject: [PATCH 2/5] Some cherry-picked changes from my next mode-refactoring commit. --- common/content/hints.js | 11 +++++------ pentadactyl/NEWS | 10 +++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/common/content/hints.js b/common/content/hints.js index 8a17950a..7ded7bb8 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -347,8 +347,10 @@ const Hints = Module("hints", { let prefix = (elem.getAttributeNS(NS, "class") || "") + " "; if (active) elem.setAttributeNS(NS, "highlight", prefix + "HintActive"); - else + else if (active != null) elem.setAttributeNS(NS, "highlight", prefix + "HintElem"); + else + elem.removeAttributeNS(NS, "highlight"); }, /** @@ -429,7 +431,6 @@ const Hints = Module("hints", { */ _removeHints: function (timeout, slight) { for (let [,{ doc: doc, start: start, end: end }] in Iterator(this._docs)) { - util.dump(String(doc), start, end); for (let elem in util.evaluateXPath("//*[@dactyl:highlight='hints']", doc)) elem.parentNode.removeChild(elem); for (let i in util.range(start, end + 1)) @@ -489,12 +490,10 @@ const Hints = Module("hints", { let n = 5; (function next() { - this._setClass(elem, n % 2); - util.dump(n, String(this._top)); + let hinted = n || this._validHints.some(function (e) e === elem); + this._setClass(elem, n ? n % 2 : !hinted ? null : this._validHints[Math.max(0, this._hintNumber-1)] === elem); if (n--) this.timeout(next, 50); - else if (!this._validHints.some(function (h) h.elem == elem)) - elem.removeAttributeNS(NS, "highlight"); }).call(this); this.timeout(function () { diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS index 20987801..df7b5ff8 100644 --- a/pentadactyl/NEWS +++ b/pentadactyl/NEWS @@ -21,6 +21,13 @@ * Multiple Ex commands may now be separated by | * Command-line is now hidden by default. Added C and M to 'guioptions'. + * Hint mode improvements, including: + - Added g; continued extended hint mode, which allows + selecting multiple hints. Removed ;F + - Hints are now updated after scrolling and window resizing. + - Added ;S mode for creating search keywords. + - Added 'hintkeys' option. + - Added "transliterated" option to 'hintmatching'. * JavaScript completion improvements, including: - The prototype of the function whose arguments are currently being typed is displayed during completion. @@ -48,7 +55,6 @@ * IMPORTANT: 'guioptions' default value has changed. * IMPORTANT: 'mapleader' is now an option rather than a :let variable. - * Added g; continued extended hint mode and removed ;F * Added "bookmarks", "diverted", and "links" to 'activate' option * Added 'altwildmode' and command-line key binding. @@ -59,8 +65,6 @@ * Added -keyword, -tags, -title to :delbmarks. * Added "passwords" and "venkman" dialogs to :dialog. * Added :extupdate command - * Added 'hintkeys' option. - * Added "transliterated" option to 'hintmatching'. * Replaced 'focuscontent' with 'strictfocus'. * Changed 'urlseparator' default value to '|' * Added 'wildanchor' option. From e6672f47c3437398707a5f4257a431a919a67cfc Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 10 Oct 2010 23:05:59 -0400 Subject: [PATCH 3/5] Allow \ line continuations in Ex files. --- common/content/commands.js | 12 ++++++------ common/content/dactyl.js | 12 +----------- common/content/hints.js | 4 ++-- common/content/io.js | 32 +++++++++++++++++--------------- common/content/options.js | 11 +++++++++-- pentadactyl/NEWS | 9 ++++++--- 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/common/content/commands.js b/common/content/commands.js index bf9f8207..f1bcd8e4 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -791,7 +791,7 @@ const Commands = Module("commands", { str.replace(/\s*".*$/, ""); // 0 - count, 1 - cmd, 2 - special, 3 - args - let matches = str.match(/^([:\s]*(\d+|%)?([a-zA-Z]+|!)(!)?(\s*))(.*?)?$/); + let matches = str.match(/^([:\s]*(\d+|%)?([a-zA-Z]+|!)(!)?(\s*))((?:.|\n)*?)?$/); //var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/); if (!matches) return []; @@ -1103,21 +1103,21 @@ const Commands = Module("commands", { completion.ex(context); }, options: [ - { names: ["-bang"], description: "Command may be proceeded by a !" }, - { names: ["-count"], description: "Command may be preceeded by a count" }, + { names: ["-bang", "-b"], description: "Command may be proceeded by a !" }, + { names: ["-count", "-c"], description: "Command may be preceeded by a count" }, { - names: ["-description"], + names: ["-description", "-desc", "-d"], description: "A user-visible description of the command", type: CommandOption.STRING }, { // TODO: "E180: invalid complete value: " + arg - names: ["-complete"], + names: ["-complete", "-C"], description: "The argument completion function", completer: function (context) [[k, ""] for ([k, v] in Iterator(completeOptionMap))], type: CommandOption.STRING, validator: function (arg) arg in completeOptionMap || /custom,\w+/.test(arg), }, { - names: ["-nargs"], + names: ["-nargs", "-a"], description: "The allowed number of arguments", completer: [["0", "No arguments are allowed (default)"], ["1", "One argument is allowed"], diff --git a/common/content/dactyl.js b/common/content/dactyl.js index 65244f87..d0013a2c 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -2022,17 +2022,7 @@ const Dactyl = Module("dactyl", { // all gui options to their default values, if they have not been // set before by any RC file for (let option in values(options.needInit)) - // FIXME: - // 'encoding' option should not be set at this timing. - // Probably a wrong value is set into the option, - // if current page's encoding is not UTF-8. - try { - if (option.name != "encoding"); - option.value = option.value; - } - catch (e) { - dactyl.reportError(e); - } + option.initValue(); if (dactyl.commandLineOptions.postCommands) dactyl.commandLineOptions.postCommands.forEach(function (cmd) { diff --git a/common/content/hints.js b/common/content/hints.js index 7ded7bb8..255d4e95 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -83,7 +83,7 @@ const Hints = Module("hints", { this._hintNumber = 0; this._hintString = ""; statusline.updateInputBuffer(""); - commandline.command = ""; + commandline.widgets.command = ""; } this._pageHints = []; this._validHints = []; @@ -99,7 +99,7 @@ const Hints = Module("hints", { } if (this.__continue && this._validHints.length <= 1) { this._hintString = ""; - commandline.command = this._hintString; + commandline.widgets.command = this._hintString; this._showHints(); } this._updateStatusline(); diff --git a/common/content/io.js b/common/content/io.js index 305023ed..28c57fef 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -358,10 +358,7 @@ lookup: else if (/\.css$/.test(filename)) storage.styles.registerSheet(uri.spec, false, true); else { - let heredoc = ""; - let heredocEnd = null; // the string which ends the heredoc - let str = file.read(); - let lines = str.split(/\r\n|[\r\n]/); + let lines = file.read().split(/\r\n|[\r\n]/); this.readHeredoc = function (end) { let res = []; @@ -382,21 +379,26 @@ lookup: for (let [i, line] in iter) { if (this.sourcing.finished) break; + this.sourcing.line = i + 1; - // skip line comments and blank lines + + // Deal with editors from Silly OSs. line = line.replace(/\r$/, ""); - if (!/^\s*(".*)?$/.test(line)) - try { - dactyl.execute(line, { setFrom: file }); - } - catch (e) { - if (!silent) { - dactyl.echoerr("Error detected while processing " + file.path); - dactyl.echomsg("line\t" + this.sourcing.line + ":"); - dactyl.reportError(e, true); - } + // Process escaped new lines + for (; i < lines.length && /^\s*\\/.test(lines[i + 1]); i++) + line += "\n" + iter.next()[1].replace(/^\s*\\/, ""); + + try { + dactyl.execute(line, { setFrom: file }); + } + catch (e) { + if (!silent) { + dactyl.echoerr("Error detected while processing " + file.path); + dactyl.echomsg("line\t" + this.sourcing.line + ":"); + dactyl.reportError(e, true); } + } } } diff --git a/common/content/options.js b/common/content/options.js index 58ff5371..07914b99 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -71,6 +71,10 @@ const Option = Class("Option", { this.globalValue = this.parseValues(this.defaultValue); }, + initValue: function () { + dactyl.trapErrors(function () this.values = this.values, this); + }, + /** @property {value} The option's global value. @see #scope */ get globalValue() options.store.get(this.name, {}).value, set globalValue(val) { options.store.set(this.name, { value: val, time: Date.now() }); }, @@ -683,8 +687,11 @@ const Options = Module("options", { memoize(this._optionMap, name, function () Option(names, description, type, defaultValue, extraInfo)); for (let alias in values(names.slice(1))) memoize(this._optionMap, alias, closure); - if (extraInfo.setter) - memoize(this.needInit, this.needInit.length, closure); + if (extraInfo.setter && (!extraInfo.scope || extraInfo.scope & Option.SCOPE_GLOBAL)) + if (dactyl.initialized) + closure().initValue(); + else + memoize(this.needInit, this.needInit.length, closure); // quickly access options with options["wildmode"]: this.__defineGetter__(name, function () this._optionMap[name].values); diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS index df7b5ff8..ee5dc1bf 100644 --- a/pentadactyl/NEWS +++ b/pentadactyl/NEWS @@ -18,7 +18,12 @@ - Backtracks to the first successful match after pressing backspace. - Supports reverse incremental search. - * Multiple Ex commands may now be separated by | + * Ex command parsing improvements, including: + - Multiple Ex commands may now be separated by | + - Commands can continue over multiple lines in RC files by + prefixing the continues lines with a \ + - The \ character is no longer treated specially within single + quotes, i.e., 'fo\o''bar' ⇒ fo\o'bar * Command-line is now hidden by default. Added C and M to 'guioptions'. * Hint mode improvements, including: @@ -41,8 +46,6 @@ directory in 'runtimepath' rather than 'plugin/'. * IMPORTANT: 'loadplugins' is now a regexlist option rather than a boolean. - * IMPORTANT: Single quotes no longer treat \ specially. - I.e., 'fo\o''bar' ≡ fo\o'bar * IMPORTANT: 'cdpath' and 'runtimepath' no longer treat ",," specially. Use "." instead. * IMPORTANT: Option value quoting has changed. List options will From 5a670ebd7b0a3500667a91866f7862033b4c4540 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Mon, 11 Oct 2010 01:49:58 -0400 Subject: [PATCH 4/5] Stem my patholigical tendency to use iterators wherever possible (but not my pathological desire to clean up perfectly servicable code). --- common/content/io.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/common/content/io.js b/common/content/io.js index 28c57fef..5a274dc6 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -362,32 +362,24 @@ lookup: this.readHeredoc = function (end) { let res = []; - try { - io.sourcing.line++; - while (true) - let ([i, line] = iter.next()) { - if (line === end) - return res.join("\n"); - res.push(line); - } + io.sourcing.line++; + while (++i < lines.length) { + if (lines[i] === end) + return res.join("\n"); + res.push(lines[i]); } - catch (e if e instanceof StopIteration) {} dactyl.assert(false, "Unexpected end of file waiting for " + end); }; - let iter = Iterator(lines); - for (let [i, line] in iter) { - if (this.sourcing.finished) - break; + for (var i = 0; i < lines.length && !this.sourcing.finished; i++) { + // Deal with editors from Silly OSs. + let line = lines[i].replace(/\r$/, ""); this.sourcing.line = i + 1; - // Deal with editors from Silly OSs. - line = line.replace(/\r$/, ""); - // Process escaped new lines - for (; i < lines.length && /^\s*\\/.test(lines[i + 1]); i++) - line += "\n" + iter.next()[1].replace(/^\s*\\/, ""); + while (i < lines.length && /^\s*\\/.test(lines[i + 1])) + line += "\n" + lines[++i].replace(/^\s*\\/, ""); try { dactyl.execute(line, { setFrom: file }); From 4efc6a3972cc6d953059b5115b094141f82c6d88 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Mon, 11 Oct 2010 02:47:07 -0400 Subject: [PATCH 5/5] Allow things like :com! foo\n \ echo 1\n \ echo 2 --- common/content/autocommands.js | 2 +- common/content/commands.js | 76 ++++++++++++++++-- common/content/configbase.js | 2 +- common/content/dactyl.js | 2 +- common/content/io.js | 140 ++++++++++++--------------------- common/content/mappings.js | 4 +- 6 files changed, 127 insertions(+), 99 deletions(-) diff --git a/common/content/autocommands.js b/common/content/autocommands.js index d225c713..8aad6061 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -169,7 +169,7 @@ const AutoCommands = Module("autocommands", { cmd.toString = function toString() "-javascript " + cmd.source; } else { - cmd = function cmd(args) dactyl.execute(commands.replaceTokens(cmd.source, args), null, true, cmd.sourcing); + cmd = function cmd(args) commands.execute(cmd.source, args, false, null, cmd.sourcing); cmd.sourcing = io.sourcing && update({}, io.sourcing); cmd.toString = function toString() cmd.source; } diff --git a/common/content/commands.js b/common/content/commands.js index f1bcd8e4..bd37d271 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -412,6 +412,64 @@ const Commands = Module("commands", { return res.join(" "); }, + /** + * Executes an Ex command script. + * + * @param {string} string A string containing the commands to execute. + * @param {object} tokens An optional object containing tokens to be + * interpolated into the command string. + * @param {object} args Optional arguments object to be passed to + * command actions. + * @param {object} sourcing An object containing information about + * the file that is being or has been sourced to obtain the + * command string. + */ + execute: function (string, tokens, silent, args, sourcing) { + io.withSavedValues(["readHeredoc", "sourcing"], function () { + this.sourcing = update({}, sourcing); + + args = update({ setFrom: this.file }, args || {}); + + if (tokens) + string = commands.replaceTokens(string, tokens); + + let lines = string.split(/\r\n|[\r\n]/); + + this.readHeredoc = function (end) { + let res = []; + this.sourcing.line++; + while (++i < lines.length) { + if (lines[i] === end) + return res.join("\n"); + res.push(lines[i]); + } + dactyl.assert(false, "Unexpected end of file waiting for " + end); + }; + + for (var i = 0; i < lines.length && !this.sourcing.finished; i++) { + // Deal with editors from Silly OSs. + let line = lines[i].replace(/\r$/, ""); + + this.sourcing.line = sourcing.line + i; + + // Process escaped new lines + while (i < lines.length && /^\s*\\/.test(lines[i + 1])) + line += "\n" + lines[++i].replace(/^\s*\\/, ""); + + try { + dactyl.execute(line, args); + } + catch (e) { + if (!silent) { + dactyl.echoerr("Error detected while processing " + this.sourcing.file); + dactyl.echomsg("line\t" + this.sourcing.line + ":"); + dactyl.reportError(e, true); + } + } + } + }); + }, + /** * Returns the command with matching name. * @@ -595,9 +653,11 @@ const Commands = Module("commands", { outer: while (i < str.length || complete) { - // skip whitespace - while (/\s/.test(str[i]) && i < str.length) - i++; + var argStart = i; + let re = /^\s*/gy; + re.lastIndex = i; + i += re.exec(str)[0].length; + if (str[i] == "|") { args.string = str.slice(0, i); args.trailing = str.slice(i + 1); @@ -700,14 +760,20 @@ const Commands = Module("commands", { complete.highlight(i, sub.length, "SPELLCHECK"); } - if (args.length == literal) { + if (args.length === literal) { if (complete) args.completeArg = args.length; + + let re = /^(?:\s*(?=\n)|\s*)([^]*)/gy; + re.lastIndex = argStart || 0; + sub = re.exec(str)[1]; + // Hack. if (sub.substr(0, 2) === "<<" && hereDoc) let ([count, arg] = getNextArg(sub)) { sub = arg + sub.substr(count); } + args.literalArg = sub; args.push(sub); args.quote = null; @@ -997,7 +1063,7 @@ const Commands = Module("commands", { count: this.count && args.count }; - dactyl.execute(commands.replaceTokens(this.replacementText, tokens), null, true, this.sourcing); + commands.execute(this.replacementText, tokens, false, null, this.sourcing); } // TODO: offer completion.ex? diff --git a/common/content/configbase.js b/common/content/configbase.js index d316ac5b..c4f9f9ee 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -153,7 +153,7 @@ const ConfigBase = Class(ModuleBase, { Null color: blue; Number color: blue; Object color: maroon; - String color: green; + String color: green; white-space: pre; Key font-weight: bold; diff --git a/common/content/dactyl.js b/common/content/dactyl.js index d0013a2c..c9dec706 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -1994,7 +1994,7 @@ const Dactyl = Module("dactyl", { dactyl.execute(init); else { if (rcFile) { - io.source(rcFile.path, true); + io.source(rcFile.path, false); services.get("environment").set("MY_" + config.idName + "RC", rcFile.path); } else diff --git a/common/content/io.js b/common/content/io.js index 5a274dc6..763f0e05 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -319,99 +319,61 @@ lookup: source: function (filename, silent) { defineModule.loadLog.push("sourcing " + filename); let time = Date.now(); - this.withSavedValues(["readHeredoc", "sourcing"], function () { - try { - var file = io.File(filename); - this.sourcing = { - file: file.path, - line: 0 - }; + try { + var file = io.File(filename); - if (!file.exists() || !file.isReadable() || file.isDirectory()) { - if (!silent) - dactyl.echoerr("E484: Can't open file " + filename.quote()); - return; - } - - dactyl.echomsg("sourcing " + filename.quote(), 2); - - let uri = services.get("io").newFileURI(file); - - // handle pure JavaScript files specially - if (/\.js$/.test(filename)) { - try { - dactyl.loadScript(uri.spec, Script(file)); - dactyl.helpInitialized = false; - } - catch (e) { - if (e.fileName) - try { - e.fileName = e.fileName.replace(/^(chrome|resource):.*? -> /, ""); - if (e.fileName == uri.spec) - e.fileName = filename; - e.echoerr = <>{e.fileName}:{e.lineNumber}: {e} - } - catch (e) {} - throw e; - } - } - else if (/\.css$/.test(filename)) - storage.styles.registerSheet(uri.spec, false, true); - else { - let lines = file.read().split(/\r\n|[\r\n]/); - - this.readHeredoc = function (end) { - let res = []; - io.sourcing.line++; - while (++i < lines.length) { - if (lines[i] === end) - return res.join("\n"); - res.push(lines[i]); - } - dactyl.assert(false, "Unexpected end of file waiting for " + end); - }; - - for (var i = 0; i < lines.length && !this.sourcing.finished; i++) { - // Deal with editors from Silly OSs. - let line = lines[i].replace(/\r$/, ""); - - this.sourcing.line = i + 1; - - // Process escaped new lines - while (i < lines.length && /^\s*\\/.test(lines[i + 1])) - line += "\n" + lines[++i].replace(/^\s*\\/, ""); - - try { - dactyl.execute(line, { setFrom: file }); - } - catch (e) { - if (!silent) { - dactyl.echoerr("Error detected while processing " + file.path); - dactyl.echomsg("line\t" + this.sourcing.line + ":"); - dactyl.reportError(e, true); - } - } - } - } - - if (this._scriptNames.indexOf(file.path) == -1) - this._scriptNames.push(file.path); - - dactyl.echomsg("finished sourcing " + filename.quote(), 2); - - dactyl.log("Sourced: " + filename, 3); - } - catch (e) { - if (!(e instanceof FailedAssertion)) - dactyl.reportError(e); - let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e); + if (!file.exists() || !file.isReadable() || file.isDirectory()) { if (!silent) - dactyl.echoerr(message); + dactyl.echoerr("E484: Can't open file " + filename.quote()); + return; } - finally { - defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms"); + + dactyl.echomsg("sourcing " + filename.quote(), 2); + + let uri = services.get("io").newFileURI(file); + + // handle pure JavaScript files specially + if (/\.js$/.test(filename)) { + try { + dactyl.loadScript(uri.spec, Script(file)); + dactyl.helpInitialized = false; + } + catch (e) { + if (e.fileName) + try { + e.fileName = e.fileName.replace(/^(chrome|resource):.*? -> /, ""); + if (e.fileName == uri.spec) + e.fileName = filename; + e.echoerr = <>{e.fileName}:{e.lineNumber}: {e} + } + catch (e) {} + throw e; + } } - }); + else if (/\.css$/.test(filename)) + storage.styles.registerSheet(uri.spec, false, true); + else { + commands.execute(file.read(), null, silent, null, + { file: file.path, line: 1 }); + } + + if (this._scriptNames.indexOf(file.path) == -1) + this._scriptNames.push(file.path); + + dactyl.echomsg("finished sourcing " + filename.quote(), 2); + + dactyl.log("Sourced: " + filename, 3); + } + catch (e) { + if (!(e instanceof FailedAssertion)) + dactyl.reportError(e); + let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e); + if (!silent) + dactyl.echoerr(message); + } + finally { + defineModule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms"); + } }, // TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is diff --git a/common/content/mappings.js b/common/content/mappings.js index a3ec6461..da98c0c6 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -384,8 +384,8 @@ const Mappings = Module("mappings", { } else if (args["-ex"]) { rhs = ["-ex", rhs]; - action = function action(count) - dactyl.execute(commands.replaceTokens(rhs[1], { count: count }), null, true, action.sourcing); + action = function action(count) commands.execute(rhs[1], { count: count }, + false, null, action.sourcing); action.sourcing = io.sourcing && update({}, io.sourcing); } else {