From 678a5657fd032a6b685c8f8cb2ce2273264fea5a Mon Sep 17 00:00:00 2001 From: Martin Stubenschrott Date: Tue, 20 Nov 2007 00:40:40 +0000 Subject: [PATCH] many bug fixes, :cd and :pwd commands, ~ mapping --- NEWS | 4 ++++ content/commands.js | 35 +++++++++++++++++++++++++++++---- content/completion.js | 11 +++++++---- content/io.js | 45 ++++++++++++++++++++++++++++++++++++++++--- content/mappings.js | 7 +++++++ content/util.js | 45 ++++++++++++++++++++++++++----------------- 6 files changed, 118 insertions(+), 29 deletions(-) diff --git a/NEWS b/NEWS index 037edf67..d9527629 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ read up the new help for the f, F and ; commands for details removed the following hint options: 'hintchars' 'maxhints' added the following hint options: 'hinttimeout' + * new ~ mapping to open the home directory + * :open tries to open a relative filename now, if you do a :open foo.html + or :open ../hello.txt; + * new :cd and :pwd commands * new :dialog command to open various firefox dialogs * new a and A mappings to deal with bookmarks * added ]n and ]p to navigate to the next/previous document based on diff --git a/content/commands.js b/content/commands.js index 7f38269b..c1b5cc55 100644 --- a/content/commands.js +++ b/content/commands.js @@ -734,6 +734,34 @@ vimperator.Commands = function () //{{{ completer: function (filter) { return [0, vimperator.bookmarks.get(filter)]; } } )); + commandManager.add(new vimperator.Command(["cd", "chd[ir]"], + function (args) + { + if (!args || vimperator.io.setCurrentDirectory(args)) + vimperator.echo(vimperator.io.getCurrentDirectory()); + }, + { + usage: ["cd [-|path]"], + shortHelp: "Change the current directory", + help: ":cd - changes to the last directory.", + completer: function (filter) { return vimperator.completion.file(filter, true); } + } + )); + commandManager.add(new vimperator.Command(["pwd"], + function (args) + { + if (args) + vimperator.echoerr("E488: Trailing characters"); + else + vimperator.echo(vimperator.io.getCurrentDirectory()); + }, + { + usage: ["cd [-|path]"], + shortHelp: "Change the current directory", + help: ":cd - changes to the last directory.", + completer: function (filter) { return vimperator.completion.file(filter, true); } + } + )); commandManager.add(new vimperator.Command(["com[mand]"], function (args) { @@ -1477,10 +1505,9 @@ vimperator.Commands = function () //{{{ help: "Multiple URLs can be separated with \", \". Note that the space after the comma is required.
" + "Each token is analyzed and in this order:
" + "
    " + - "
  1. Transformed to a relative URL of the current location if it starts with . or .. or ...;
    " + - "... is special and moves up the directory hierarchy as far as possible." + - "
    • :open ... with current location \"http://www.example.com/dir1/dir2/file.html\" opens \"http://www.example.com\"
    • " + - "
    • :open ./foo.html with current location \"http://www.example.com/dir1/dir2/file.html\" opens \"http://www.example.com/dir1/dir2/foo.html\"
  2. " + + "
  3. Opened as a local file if it is an existing relative or absolute filename. " + + "
    • :open /etc/fstab shows the file system table.
    • " + + "
    • :open ../other/foo.html in your home directory opens \"/home/other/foo.html\"
  4. " + "
  5. Opened with the specified search engine if the token looks like a search string " + "and the first word is the name of a search engine (:open wikipedia linus torvalds " + "opens the wikipedia entry for linus torvalds). The short name of a search engine is automatically guessed from its name. " + diff --git a/content/completion.js b/content/completion.js index 12dcb6e2..9998ecd3 100644 --- a/content/completion.js +++ b/content/completion.js @@ -190,12 +190,12 @@ vimperator.Completion = function () //{{{ { if (cpt[i] == "s") completions = completions.concat(this.search(filter)[1]); + else if (cpt[i] == "f") + completions = completions.concat(this.file(filter, false)[1]); else if (cpt[i] == "b") completions = completions.concat(vimperator.bookmarks.get(filter)); else if (cpt[i] == "h") completions = completions.concat(vimperator.history.get(filter)); - else if (cpt[i] == "f") - completions = completions.concat(this.file(filter, false)[1]); } return [start, completions]; @@ -237,7 +237,7 @@ vimperator.Completion = function () //{{{ { files = vimperator.io.readDirectory(dir); mapped = files.map(function (file) { - return [[short ? file.leafName : dir + file.leafName], file.isDirectory() ? "Directory" : "File"]; + return [[short ? file.leafName : (dir + file.leafName)], file.isDirectory() ? "Directory" : "File"]; }); } catch (e) @@ -245,7 +245,10 @@ vimperator.Completion = function () //{{{ return []; } - return [short ? dir.length : 0, buildLongestStartingSubstring(mapped, compl)]; + if (short) + return [dir.length, buildLongestStartingSubstring(mapped, compl)]; + else + return [0, buildLongestStartingSubstring(mapped, filter)]; }, help: function (filter) diff --git a/content/io.js b/content/io.js index af8b0823..1d705488 100644 --- a/content/io.js +++ b/content/io.js @@ -37,6 +37,7 @@ vimperator.IO = function ()//{{{ .getService(Components.interfaces.nsIEnvironment); const WINDOWS = navigator.platform == "Win32"; + var cwd = null, oldcwd = null; /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// PUBLIC SECTION ////////////////////////////////////////// @@ -92,6 +93,41 @@ vimperator.IO = function ()//{{{ return path; }, + getCurrentDirectory: function () + { + var dirs = [cwd, "$PWD", "~"]; + for (var i = 0; i < dirs.length; i++) + { + if (!dirs[i]) + continue; + + if (this.getFile(dirs[i]).exists()) + return this.expandPath(dirs[i]); + } + }, + + setCurrentDirectory: function (newdir) + { + if (!newdir) + newdir = "~"; + + if (newdir == "-") + { + [cwd, oldcwd] = [oldcwd, cwd]; + } + else + { + newdir = this.expandPath(newdir); + if (!this.getFile(newdir).isDirectory()) + { + vimperator.echoerr("E344: Can't find directory \"" + newdir + "\" in path"); + return this.getCurrentDirectory(); + } + [cwd, oldcwd] = [newdir, cwd]; + } + return this.getCurrentDirectory(); + }, + getPluginDir: function () { var pluginDir; @@ -122,6 +158,7 @@ vimperator.IO = function ()//{{{ return null; }, + // 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 @@ -130,10 +167,12 @@ vimperator.IO = function ()//{{{ var file = Components.classes["@mozilla.org/file/local;1"]. createInstance(Components.interfaces.nsILocalFile); - // convert relative to absolute pathnames + // convert relative to absolute pathname path = this.expandPath(path); - if (!/^([a-zA-Z]+:|\/)/.test(path)) // starts not with either /, C: or file: - path = this.expandPath("~") + (WINDOWS ? "\\" : "/") + path; // TODO: for now homedir, later relative to current dir? + if (!/^(file:|[a-zA-Z]:|\/)/.test(path)) // starts not with either /, C: or file: + path = this.getCurrentDirectory() + (WINDOWS ? "\\" : "/") + path; // TODO: for now homedir, later relative to current dir? + else + path = path.replace(/^file:/, ""); file.initWithPath(path); return file; diff --git a/content/mappings.js b/content/mappings.js index fe36d567..74c2fbd4 100644 --- a/content/mappings.js +++ b/content/mappings.js @@ -504,6 +504,13 @@ vimperator.Mappings = function () //{{{ flags: vimperator.Mappings.flags.COUNT } )); + addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["~"], + function () { vimperator.open("~"); }, + { + shortHelp: "Open home directory", + help: "You can also use the hints to create the probably fastest file browser on earth." + } + )); addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["gh"], BrowserHome, { diff --git a/content/util.js b/content/util.js index 55343ec5..99ad4119 100644 --- a/content/util.js +++ b/content/util.js @@ -104,28 +104,37 @@ vimperator.util = { //{{{ // strip each 'URL' - makes things simpler later on urls[url] = urls[url].replace(/^\s+/, "").replace(/\s+$/, ""); - // FIXME: not really that good (doesn't handle .. in the middle) - // check for ./ and ../ (or even .../) to go to a file in the upper directory - if (matches = urls[url].match(/^(?:\.$|\.\/(\S*))/)) + // first check if it is an existing local file + var file = vimperator.io.getFile(urls[url]); + if (file.exists()) { - var tail = matches[1] || ""; - urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1" + tail); // NOTE: escape / in character sets so as not to break Vim syntax highlighting - continue; - } - else if (matches = urls[url].match(/^(?:\.\.$|\.\.\/(\S*))/)) - { - var tail = matches[1] || ""; - urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1../" + tail); - continue; - } - else if (matches = urls[url].match(/^(?:\.\.\.$|\.\.\.\/(\S*))/)) - { - var location = window.content.document.location; - var tail = matches[1] || ""; - urls[url] = location.protocol + "//" + location.host + "/" + tail; + urls[url] = file.path; continue; } +// Disabled for now, use gu and GU or O and change the last part +// // FIXME: not really that good (doesn't handle .. in the middle) +// // check for ./ and ../ (or even .../) to go to a file in the upper directory +// if (matches = urls[url].match(/^(?:\.$|\.\/(\S*))/)) +// { +// var tail = matches[1] || ""; +// urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1" + tail); // NOTE: escape / in character sets so as not to break Vim syntax highlighting +// continue; +// } +// else if (matches = urls[url].match(/^(?:\.\.$|\.\.\/(\S*))/)) +// { +// var tail = matches[1] || ""; +// urls[url] = newURL.replace(/(.+\/)[^\/]*/, "$1../" + tail); +// continue; +// } +// else if (matches = urls[url].match(/^(?:\.\.\.$|\.\.\.\/(\S*))/)) +// { +// var location = window.content.document.location; +// var tail = matches[1] || ""; +// urls[url] = location.protocol + "//" + location.host + "/" + tail; +// continue; +// } + // if the string doesn't look like a valid URL (i.e. contains a space // or does not contain any of: .:/) try opening it with a search engine // or keyword bookmark