diff --git a/NEWS b/NEWS index 352b62ab..1a97900b 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@
 2008-08-16:
     * version 2.0 (probably)
+    * add 'cdpath' option
     * allow :dialog to open the cookies manager
     * add 'loadplugins' option
     * add count support to C-^ (Kazuo)
diff --git a/content/io.js b/content/io.js
index 1d327374..0c50fa8f 100644
--- a/content/io.js
+++ b/content/io.js
@@ -45,6 +45,13 @@ liberator.IO = function () //{{{
     ////////////////////// OPTIONS ////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////{{{
 
+    var cdpath = "," + (environmentService.get("CDPATH").replace(/[:;]/g, ",") || ",");
+
+    // TODO: setter should expand environment variables
+    liberator.options.add(["cdpath", "cd"],
+        "List of directories searched when executing :cd",
+        "stringlist", cdpath);
+
     var shell, shellcmdflag;
 
     if (WINDOWS)
@@ -94,8 +101,45 @@ liberator.IO = function () //{{{
                 }
             }
 
-            if (liberator.io.setCurrentDirectory(args))
-                liberator.echo(liberator.io.getCurrentDirectory());
+            // go directly to an absolute path or look for a relative path
+            // match in 'cdpath'
+            if (/^(~|\/|\.\/|\.\.\/)/.test(args))
+            {
+                // TODO: apparently we don't handle ../ or ./ paths yet
+                if (liberator.io.setCurrentDirectory(args))
+                    liberator.echo(liberator.io.getCurrentDirectory());
+            }
+            else
+            {
+                var directories = liberator.options["cdpath"].replace(/^,$|^,,|,,$/, "").split(",");
+
+                // empty 'cdpath' items mean the current directory
+                directories = directories.map(function (directory) {
+                    return directory == "" ? liberator.io.getCurrentDirectory() : directory;
+                });
+
+                var directoryFound = false;
+
+                for (let i = 0; i < directories.length; i++)
+                {
+                    var dir = directories[i] + liberator.io.directorySeperator + args;
+                    if (liberator.io.setCurrentDirectory(dir))
+                    {
+                        // FIXME: we're just overwriting the error message from
+                        // setCurrentDirectory here
+                        liberator.echo(liberator.io.getCurrentDirectory());
+                        directoryFound = true;
+                        break;
+                    }
+                }
+
+                if (!directoryFound)
+                {
+                    liberator.echoerr("E344: Can't find directory \"" + args + "\" in cdpath"
+                                    + "\n"
+                                    + "E472: Command failed");
+                }
+            }
         },
         {
             completer: function (filter) { return liberator.completion.file(filter, true); }
@@ -324,6 +368,7 @@ liberator.IO = function () //{{{
                 }
                 [cwd, oldcwd] = [newdir, this.getCurrentDirectory()];
             }
+
             return ioManager.getCurrentDirectory();
         },
 
diff --git a/locale/en-US/options.txt b/locale/en-US/options.txt
index daf89380..a61b5027 100644
--- a/locale/en-US/options.txt
+++ b/locale/en-US/options.txt
@@ -203,6 +203,15 @@ Foreground color of the current active link during hint mode.
 ____
 
 
+|\'cd'| |\'cdpath'|
+||'cdpath' 'cd'|| string (default: black)
+____
+List of directories searched when executing the :cd command. This is only used
+for relative paths, if an absolute path is specified then the option is
+ignored. 
+____
+
+
 |\'cpt'| |\'complete'|
 ||'complete' 'cpt'|| charlist (default: sfbh)
 ____
@@ -444,8 +453,8 @@ This includes (X)HTML elements with an "href" atrribute and XLink "simple" links
 ____
 
 
-|\'noloadplugins'| |\'loadplugins'|
-||'loadplugins'|| boolean (default on)
+|\'nolpl'| |\'lpl'||\'noloadplugins'| |\'loadplugins'|
+||'loadplugins' 'lpl'|| boolean (default on)
 ____
 Load plugin scripts when starting up.
 ____