diff --git a/HACKING b/HACKING index 758ab2c1..6ac51844 100644 --- a/HACKING +++ b/HACKING @@ -80,6 +80,7 @@ We try to be quite consistent, but of course, that's not always possible. Right: if (HACK) // TODO: remove hack Wrong: if (HACK) /* TODO: remove hack */ Documentation comment blocks use /** ... */ + Wrap comment documentation comment lines at 80 characters. * Only wrap lines if it makes the code obviously clearer. Lines longer than 132 characters should probably be broken up rather than wrapped anyway. diff --git a/common/content/buffer.js b/common/content/buffer.js index f2a62807..316c2279 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -1159,7 +1159,7 @@ function Buffer() //{{{ * Saves a page link to disk. * * @param {HTMLAnchorElement} elem The page link to save. - * @param {boolean} skipPrompt Whether to open the "Save Link As..." dialog + * @param {boolean} skipPrompt Whether to open the "Save Link As..." dialog. */ saveLink: function (elem, skipPrompt) { diff --git a/common/content/commands.js b/common/content/commands.js index e8a0a50f..13833b41 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -150,7 +150,7 @@ Command.prototype = { * @param {number} count @deprecated Whether this command was * executed with a leading count. * @param modifiers Any modifiers to be passed to - * {@link action} + * {@link #action}. */ execute: function (args, bang, count, modifiers) { diff --git a/common/content/events.js b/common/content/events.js index 0cd60e18..fdea9340 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -189,8 +189,8 @@ function AutoCommands() //{{{ * * @param {Array} events The array of event names for which this * autocommand should be executed. - * @param {string} regex The URL pattern to match against the buffer URL - * @param {string} cmd The Ex command to run + * @param {string} regex The URL pattern to match against the buffer URL. + * @param {string} cmd The Ex command to run. */ add: function (events, regex, cmd) { diff --git a/common/content/io.js b/common/content/io.js index 9da85767..bcec870a 100644 --- a/common/content/io.js +++ b/common/content/io.js @@ -55,6 +55,7 @@ Script.prototype = plugins; // TODO: why are we passing around strings rather than file objects? /** + * Provides a basic interface to common system I/O operations. * @instance io */ function IO() //{{{ @@ -394,23 +395,99 @@ function IO() //{{{ const self = { + /** + * @property {number} Open for reading only. + * @final + */ MODE_RDONLY: 0x01, + + /** + * @property {number} Open for writing only. + * @final + */ MODE_WRONLY: 0x02, + + /** + * @property {number} Open for reading and writing. + * @final + */ MODE_RDWR: 0x04, + + /** + * @property {number} If the file does not exist, the file is created. + * If the file exists, this flag has no effect. + * @final + */ MODE_CREATE: 0x08, + + /** + * @property {number} The file pointer is set to the end of the file + * prior to each write. + * @final + */ MODE_APPEND: 0x10, + + /** + * @property {number} If the file exists, its length is truncated to 0. + * @final + */ MODE_TRUNCATE: 0x20, + + /** + * @property {number} If set, each write will wait for both the file + * data and file status to be physically updated. + * @final + */ MODE_SYNC: 0x40, + + /** + * @property {number} With MODE_CREATE, if the file does not exist, the + * file is created. If the file already exists, no action and NULL + * is returned. + * @final + */ MODE_EXCL: 0x80, + /** + * @property {Object} The current file sourcing context. As a file is + * being sourced the 'file' and 'line' properties of this context + * object are updated appropriately. + */ sourcing: null, + /** + * @property {string} The OS's path separator. + */ pathSeparator: WINDOWS ? "\\" : "/", + /** + * Expands "~" and environment variables in path. + * + * "~" is expanded to to the value of $HOME. On Windows if this is not + * set then the following are tried in order: + * $USERPROFILE + * ${HOMDRIVE}$HOMEPATH + * + * The variable notation is $VAR (terminated by a non-word character) + * or ${VAR}. %VAR% is also supported on Windows. + * + * @param {string} path The unexpanded path string. + * @param {boolean} relative Whether the path is relative or absolute. + * @returns {string} + */ expandPath: IO.expandPath, // TODO: there seems to be no way, short of a new component, to change // Firefox's CWD - see // https://bugzilla.mozilla.org/show_bug.cgi?id=280953 + /** + * Returns the current working directory. + * + * It's not possible to change the real CWD of Firefox so this state is + * maintained internally. External commands run via {@link #system} are + * executed in this directory. + * + * @returns {nsIFile} + */ getCurrentDirectory: function () { let dir = self.getFile(cwd.path); @@ -423,17 +500,23 @@ function IO() //{{{ return processDir; }, - setCurrentDirectory: function (newdir) + /** + * Sets the current working directory. + * + * @param {string} newDir The new CWD. This may be a relative or + * absolute path and is expanded by (@link #expandPath). + */ + setCurrentDirectory: function (newDir) { - newdir = newdir || "~"; + newDir = newDir || "~"; - if (newdir == "-") + if (newDir == "-") { [cwd, oldcwd] = [oldcwd, this.getCurrentDirectory()]; } else { - let dir = self.getFile(newdir); + let dir = self.getFile(newDir); if (!dir.exists() || !dir.isDirectory()) { @@ -447,16 +530,28 @@ function IO() //{{{ return self.getCurrentDirectory(); }, - getRuntimeDirectories: function (specialDirectory) + /** + * Returns all directories named name in 'runtimepath'. + * + * @param {string} name + * @returns {nsIFile[]) + */ + getRuntimeDirectories: function (name) { let dirs = getPathsFromPathList(options["runtimepath"]); - dirs = dirs.map(function (dir) joinPaths(dir, specialDirectory)) + dirs = dirs.map(function (dir) joinPaths(dir, name)) .filter(function (dir) dir.exists() && dir.isDirectory() && dir.isReadable()); return dirs; }, + /** + * Returns the first user RC file found in dir. + * + * @param {string} dir The directory to search. + * @default $HOME. + */ getRCFile: function (dir) { dir = dir || "~"; @@ -478,6 +573,14 @@ function IO() //{{{ // return a nsILocalFile for path where you can call isDirectory(), etc. on // caller must check with .exists() if the returned file really exists // also expands relative paths + /** + * Returns an nsIFile object for path, which is expanded + * according to {@link #expandPath}. + * + * @param {string} path The path used to create the file object. + * @param {boolean} noCheckPWD Whether to allow a relative path. + * @returns {nsIFile} + */ getFile: function (path, noCheckPWD) { let file = services.create("file"); @@ -501,7 +604,11 @@ function IO() //{{{ }, // TODO: make secure - // returns a nsILocalFile or null if it could not be created + /** + * Creates a temporary file. + * + * @returns {nsIFile} + */ createTempFile: function () { let tmpName = EXTENSION_NAME + ".tmp"; @@ -532,17 +639,25 @@ function IO() //{{{ }, - // file is either a full pathname or an instance of file instanceof nsILocalFile - readDirectory: function (file, sort) + /** + * Returns the list of files in dir. + * + * @param {nsIFile|string} dir The directory to read, either a full + * pathname or an instance of nsIFile. + * @param {boolean} sort Whether to sort the returned directory + * entries. + * @returns {nsIFile[]} + */ + readDirectory: function (dir, sort) { - if (typeof file == "string") - file = self.getFile(file); - else if (!(file instanceof Ci.nsILocalFile)) + if (typeof dir == "string") + dir = self.getFile(dir); + else if (!(dir instanceof Ci.nsILocalFile)) throw Cr.NS_ERROR_INVALID_ARG; // FIXME: does not work as expected, just shows undefined: undefined - if (file.isDirectory()) + if (dir.isDirectory()) { - let entries = file.directoryEntries; + let entries = dir.directoryEntries; let array = []; while (entries.hasMoreElements()) { @@ -558,8 +673,13 @@ function IO() //{{{ // Yes --djk }, - // file is either a full pathname or an instance of file instanceof nsILocalFile - // reads a file in "text" mode and returns the string + /** + * Reads a file in "text" mode and returns the content as a string. + * + * @param {nsIFile|string} file The file to read, either a full + * pathname or an instance of nsIFile. + * @returns {string} + */ readFile: function (file) { let ifstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream); @@ -585,9 +705,30 @@ function IO() //{{{ return buffer; }, - // file is either a full pathname or an instance of file instanceof nsILocalFile - // default permission = 0644, only used when creating a new file, does not change permissions if the file exists - // mode can be ">" or ">>" in addition to the normal MODE_* flags + /** + * Writes the string buf to a file. + * + * @param {nsIFile|string} file The file to write, either a full + * pathname or an instance of nsIFile. + * @param {string} buf The file content. + * @param {string|number} mode The file access mode, a bitwise OR of + * the following flags: + * (@link #MODE_RDONLY): 0x01 + * (@link #MODE_WRONLY): 0x02 + * (@link #MODE_RDWR): 0x04 + * (@link #MODE_CREATE): 0x08 + * (@link #MODE_APPEND): 0x10 + * (@link #MODE_TRUNCATE): 0x20 + * (@link #MODE_SYNC): 0x40 + * Alternatively, the following abbreviations may be used: + * ">" is equivalent to (@link #MODE_WRONLY) | (@link #MODE_CREATE) | (@link #MODE_TRUNCATE) + * ">>" is equivalent to (@link #MODE_WRONLY) | (@link #MODE_CREATE) | (@link #MODE_APPEND) + * @default ">" + * @param {number} perms The file mode bits of the created file. This + * is only used when creating a new file and does not change + * permissions if the file exists. + * @default 0644 + */ writeFile: function (file, buf, mode, perms) { let ofstream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); @@ -615,6 +756,13 @@ function IO() //{{{ ofstream.close(); }, + /** + * Runs an external program. + * + * @param {string} program The program to run. + * @param {string[]} args An array of arguments to pass to program. + * @param {boolean} blocking Whether to wait until the process terminates. + */ run: function (program, args, blocking) { args = args || []; @@ -673,47 +821,17 @@ lookup: return process.exitValue; }, - // when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is fixed - // is fixed, should use that instead of a tmpfile - system: function (command, input) - { - liberator.echomsg("Calling shell to execute: " + command, 4); - - function escape(str) '"' + str.replace(/[\\"$]/g, "\\$&") + '"'; - - return this.withTempFiles(function (stdin, stdout, stderr, cmd) { - - if (input) - this.writeFile(stdin, input); - - if (WINDOWS) - { - command = "cd /D " + cwd.path + " && " + command + " > " + stdout.path + " 2> " + stderr.path + " < " + stdin.path; - var res = this.run(options["shell"], options["shellcmdflag"].split(/\s+/).concat(command), true); - } - else - { - - this.writeFile(cmd, "cd " + escape(cwd.path) + "\n" + - ["exec", ">" + escape(stdout.path), "2>" + escape(stderr.path), "<" + escape(stdin.path), - escape(options["shell"]), options["shellcmdflag"], escape(command)].join(" ")); - res = this.run("/bin/sh", ["-e", cmd.path], true); - } - - if (res > 0) // FIXME: Is this really right? Shouldn't we always show both? - var output = self.readFile(stderr) + "\nshell returned " + res; - else - output = self.readFile(stdout); - - // if there is only one \n at the end, chop it off - if (output && output.indexOf("\n") == output.length - 1) - output = output.substr(0, output.length - 1); - - return output; - }) || ""; - }, - // FIXME: multiple paths? + /** + * Sources files found in 'runtimepath'. For each relative path in + * paths each directory in 'runtimepath' is searched and if a + * matching file is found it is sourced. Only the first file found (per + * specified path) is sourced unless all is specified, then + * all found files are sourced. + * + * @param {string[]} paths An array of relative paths to source. + * @param {boolean} all Whether all found files should be sourced. + */ sourceFromRuntimePath: function (paths, all) { let dirs = getPathsFromPathList(options["runtimepath"]); @@ -748,8 +866,12 @@ lookup: return found; }, - // files which end in .js are sourced as pure JavaScript files, - // no need (actually forbidden) to add: js <filename. + * + * @param {string} filename The name of the file to source. + * @param {boolean} silent Whether errors should be reported. + */ source: function (filename, silent) { let wasSourcing = self.sourcing; @@ -903,11 +1025,68 @@ lookup: } }, + // TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is + // fixed is fixed, should use that instead of a tmpfile + /** + * Runs command in a subshell and returns the output in a + * string. The shell used is that specified by the 'shell' option. + * + * @param {string} command The command to run. + * @param {string} input Any input to be provided to the command on stdin. + * @returns {string} + */ + system: function (command, input) + { + liberator.echomsg("Calling shell to execute: " + command, 4); + + function escape(str) '"' + str.replace(/[\\"$]/g, "\\$&") + '"'; + + return this.withTempFiles(function (stdin, stdout, stderr, cmd) { + if (input) + this.writeFile(stdin, input); + + if (WINDOWS) + { + command = "cd /D " + cwd.path + " && " + command + " > " + stdout.path + " 2> " + stderr.path + " < " + stdin.path; + var res = this.run(options["shell"], options["shellcmdflag"].split(/\s+/).concat(command), true); + } + else + { + + this.writeFile(cmd, "cd " + escape(cwd.path) + "\n" + + ["exec", ">" + escape(stdout.path), "2>" + escape(stderr.path), "<" + escape(stdin.path), + escape(options["shell"]), options["shellcmdflag"], escape(command)].join(" ")); + res = this.run("/bin/sh", ["-e", cmd.path], true); + } + + // FIXME: Is this really right? Shouldn't we always show both? + if (res > 0) + var output = self.readFile(stderr) + "\nshell returned " + res; + else + output = self.readFile(stdout); + + // if there is only one \n at the end, chop it off + if (output && output.indexOf("\n") == output.length - 1) + output = output.substr(0, output.length - 1); + + return output; + }) || ""; + }, + + /** + * Creates a temporary file context for executing external commands. + * fn is called with a temp file, created with + * {@link #createTempFile}, as each argument. + * + * @param {function} fn The fn to execute. + * @param {Object} self The calling object used when executing fn. + */ withTempFiles: function (fn, self) { let args = util.map(util.range(0, fn.length), this.createTempFile); if (!args.every(util.identity)) return false; + try { return fn.apply(self || this, args); @@ -923,6 +1102,10 @@ lookup: }; //}}} +/** + * @property {string} The value of the $VIMPERATOR_RUNTIME environment + * variable. + */ IO.__defineGetter__("runtimePath", function () { const rtpvar = config.name.toUpperCase() + "_RUNTIME"; let rtp = services.get("environment").get(rtpvar); diff --git a/common/content/ui.js b/common/content/ui.js index 82dea5bc..0fd3a6b9 100644 --- a/common/content/ui.js +++ b/common/content/ui.js @@ -29,10 +29,10 @@ the terms of any one of the MPL, the GPL or the LGPL. /** @scope modules */ /** - * This class is used for prompting of user input and echoing of messages + * This class is used for prompting of user input and echoing of messages. * - * it consists of a prompt and command field - * be sure to only create objects of this class when the chrome is ready + * It consists of a prompt and command field be sure to only create objects of + * this class when the chrome is ready. */ function CommandLine() //{{{ { @@ -76,7 +76,7 @@ function CommandLine() //{{{ var lastEcho = null; /** - * A class for managing the history of an inputField + * A class for managing the history of an inputField. * * @param {Object} inputField * @param {string} mode @@ -99,7 +99,7 @@ function CommandLine() //{{{ this.index = null; }, /** - * Permanently save the history + * Permanently save the history. */ save: function () { @@ -111,7 +111,7 @@ function CommandLine() //{{{ this.store.truncate(options["history"], true); }, /** - * Set the current match to val + * Set the current match to val. * * @param {string} val */ @@ -177,7 +177,7 @@ function CommandLine() //{{{ }; /** - * A class for tab completions on an input field + * A class for tab completions on an input field. * * @param {Object} input */ @@ -597,7 +597,7 @@ function CommandLine() //{{{ var multilineCallback = null; /** - * Highlight the messageBox according to group. + * Highlight the messageBox according to group. */ function setHighlightGroup(group) { @@ -605,7 +605,7 @@ function CommandLine() //{{{ } /** - * Determines whether the command line should be visible. + * Determines whether the command-line should be visible. * * @return {boolean} */ @@ -714,8 +714,7 @@ function CommandLine() //{{{ } /** - * Ensure that the Multiline input widget is the - * correct size. + * Ensure that the multiline input widget is the correct size. */ function autosizeMultilineInputWidget() { @@ -1027,7 +1026,7 @@ function CommandLine() //{{{ get message() messageBox.value, /** - * Open the command line. The main mode is set to + * Open the command-line. The main mode is set to * COMMAND_LINE, the extended mode to extendedMode. * Further, callbacks defined for extendedMode are * triggered as appropriate (see {@link Liberator#registerCallback}). @@ -1061,10 +1060,9 @@ function CommandLine() //{{{ }, /** - * Closes the command line. This is ordinarilly triggered - * automatically by a mode change. Will not hide the command - * line immediately if called directly after a successful - * command, otherwise it will. + * Closes the command-line. This is ordinarily triggered automatically + * by a mode change. Will not hide the command-line immediately if + * called directly after a successful command, otherwise it will. */ close: function close() { @@ -1101,7 +1099,7 @@ function CommandLine() //{{{ /** - * Hides the command line, and shows any status messages that + * Hides the command-line, and shows any status messages that * are under it. */ hide: function hide() @@ -1110,24 +1108,24 @@ function CommandLine() //{{{ }, /** - * Output the given string onto the command line. With no - * flags, the message will be shown in the status line if it's - * short enough to fit, and contains no new lines, and isn't - * XML. Otherwise, it will be shown in the MOW. + * Output the given string onto the command-line. With no flags, the + * message will be shown in the status line if it's short enough to + * fit, and contains no new lines, and isn't XML. Otherwise, it will be + * shown in the MOW. * * @param {string} str * @param {string} highlightGroup The Highlight group for the * message. @default "Normal" - * @param {number} flags Changes the bahavior as follows: - * commandline.APPEND_TO_MESSAGES - Causes message to be added to the messages - * history, and shown by :messages. - * commandline.FORCE_SINGLELINE - Forbids the command from - * being pushed to the MOW if it's too long or of - * there are already status messages being shown. - * commandline.DISALLOW_MULTILINE - Cancels the operation if - * the MOW is already visible. - * commandline.FORCE_MULTILINE - Forces the message to - * appear in the MOW. + * @param {number} flags Changes the behavior as follows: + * commandline.APPEND_TO_MESSAGES - Causes message to be added to the + * messages history, and shown by :messages. + * commandline.FORCE_SINGLELINE - Forbids the command from being + * pushed to the MOW if it's too long or of there are already + * status messages being shown. + * commandline.DISALLOW_MULTILINE - Cancels the operation if the MOW + * is already visible. + * commandline.FORCE_MULTILINE - Forces the message to appear in + * the MOW. */ echo: function echo(str, highlightGroup, flags) { @@ -1177,15 +1175,18 @@ function CommandLine() //{{{ }, /** - * Prompt the user. Sets modes.main to COMMAND_LINE, which the - * user may pop at any time to close the prompt. + * Prompt the user. Sets modes.main to COMMAND_LINE, which the user may + * pop at any time to close the prompt. * * @param {string} prompt The input prompt to use. * @param {function(string)} callback * @param {object} extra - * @... {function} onChange - A function to be called with the current input every time it changes - * @... {function(CompletionContext)} completer - A completion function for the user's input. - * @... {string} promptHighlight - The HighlightGroup used for the prompt. @default "Question" + * @... {function} onChange - A function to be called with the current + * input every time it changes. + * @... {function(CompletionContext)} completer - A completion function + * for the user's input. + * @... {string} promptHighlight - The HighlightGroup used for the + * prompt. @default "Question" */ input: function input(prompt, callback, extra) { @@ -1207,9 +1208,9 @@ function CommandLine() //{{{ }, /** - * Get a multiline input from a user, up to but not including - * the line which matches the given regular expression. Then - * execute the callback with that string as a parameter. + * Get a multiline input from a user, up to but not including the line + * which matches the given regular expression. Then execute the + * callback with that string as a parameter. * * @param {RegExp} untilRegexp * @param {function(string)} callbackFunc @@ -1235,10 +1236,9 @@ function CommandLine() //{{{ }, /** - * Handles all command line events. All key events are passed - * here when COMMAND_LINE mode is active, as well as all - * input, keyup, focus, and blur events sent to the - * command-line XUL element. + * Handles all command-line events. All key events are passed here when + * COMMAND_LINE mode is active, as well as all input, keyup, focus, and + * blur events sent to the command-line XUL element. * * @param {Event} event * @private @@ -1377,9 +1377,9 @@ function CommandLine() //{{{ }, /** - * Handle events when we are in multiline output mode, - * these come from liberator when modes.extended & modes.MULTILINE_OUTPUT - * and also from #liberator-multiline-output in the XUL + * Handle events when we are in multiline output mode, these come from + * liberator when modes.extended & modes.MULTILINE_OUTPUT and also from + * #liberator-multiline-output in the XUL. * * @param {Event} event */ @@ -1595,13 +1595,12 @@ function CommandLine() //{{{ }, /** - * Update or remove the multiline output widget's "MORE" - * prompt. + * Update or remove the multiline output widget's "MORE" prompt. * - * @param {boolean} force If true, "-- More --" is shown - * even if we're at the end of the output. - * @param {boolean} showHelp When true, show the valid key - * sequences and what they do. + * @param {boolean} force If true, "-- More --" is shown even if we're + * at the end of the output. + * @param {boolean} showHelp When true, show the valid key sequences + * and what they do. */ updateMorePrompt: function updateMorePrompt(force, showHelp) { @@ -1621,11 +1620,11 @@ function CommandLine() //{{{ }, /** - * Changes the height of the multilineOutputWidget to fit in - * the available space. + * Changes the height of the multilineOutputWidget to fit in the + * available space. * - * @param {boolean} open If true, the widget will be opened if - * it's not already so. + * @param {boolean} open If true, the widget will be opened if it's not + * already so. */ updateOutputHeight: function updateOutputHeight(open) { @@ -1665,12 +1664,12 @@ function CommandLine() //{{{ }; //}}} /** - * The list which is used for the completion box (and QuickFix window - * in future). + * The list which is used for the completion box (and QuickFix window in + * future). * - * @param {string} id The id of the