]> Sergey Matveev's repositories - nnn.git/commitdiff
Polish change directory logic
authorArun Prakash Jana <engineerarun@gmail.com>
Tue, 25 Apr 2017 04:31:52 +0000 (10:01 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Tue, 25 Apr 2017 16:37:09 +0000 (22:07 +0530)
1. Strip end spaces and slashes
2. Do NOT change dir if in the same dir
3. Don't go back beyond startup dir with '-'
4. Reset oldpath on cd (other than cd . and ..)
5. Reset filter
6. Update features in README

README.md
config.def.h
nnn.c

index 47f35fffb4af491ebf652435216a82d23f62ef18..c6d40673e6576fded3f1b89beac3a6b37045a559 100644 (file)
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ Noice is Not Noice, a noicer fork...
 - [How to](#how-to)
   - [cd on quit](#cd-on-quit)
   - [Copy current file path to clipboard](#copy-current-file-path-to-clipboard)
+  - [Boost chdir prompt](#boost-chdir-prompt)
   - [Change file associations](#change-file-associations)
 - [Why fork?](#why-fork)
 - [Developers](#developers)
@@ -54,12 +55,12 @@ Have fun with it! PRs are welcome. Check out [#1](https://github.com/jarun/nnn/i
 ### Features
 
 - Super-easy navigation with roll-over at edges
-- Jump HOME or back to the last visited directory (as you normally do!)
+- Jump HOME or back to the last visited directory (as usual!)
+- Jump to initial dir, chdir prompt, cd ..... (with . as PWD)
 - Desktop opener integration to handle mime types
 - Customizable bash script nlay to handle known file types
 - Disk usage analyzer mode
-- Basic and detail views
-- Show stat and file information
+- Basic and detail view (with stat and file information)
 - Show media information (needs mediainfo)
 - Sort by modification time, size
 - Sort numeric names in numeric order (1, 2, ... 10, 11, ...)
@@ -260,6 +261,10 @@ export `NNN_OPENER`:
 
 Start nnn and use `^K` to copy the absolute path (from `/`) of the file under the cursor to clipboard.
 
+#### Boost chdir prompt
+
+nnn uses libreadline for the chdir prompt input. So all the fantastic features of readline (e.g. case insensitive tab completion, history, reverse-i-search) is available to you based on your readline [configuration](https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC9).
+
 #### Change file associations
 
 If `NNN_OPENER` is not set, nnn tries to recognize a file by the file extension and invokes nlay. To change the extensions recognized by nnn, modify the `assocs` structure in [config.def.h](https://github.com/jarun/nnn/blob/master/config.def.h) (it's easy). Then re-compile and install.
index 1b53f6b72019e375f91ef9987ebe039f20b09c15..e23fe3c374f18b955545fd1bb002d0a99922df48 100644 (file)
@@ -66,7 +66,7 @@ static struct key bindings[] = {
        /* Initial directory */
        { '&',            SEL_CDBEGIN,   "",     "" },
        /* Last visited dir */
-       { '-',            SEL_LAST,      "",     "" },
+       { '-',            SEL_CDLAST,    "",     "" },
        /* Toggle hide .dot files */
        { '.',            SEL_TOGGLEDOT, "",     "" },
        /* Detailed listing */
diff --git a/nnn.c b/nnn.c
index 00f7d9878800007dc1f11204386ad000f44fe049..031ffe2d25eaa883c8ab417ccc645c08ceb86921 100644 (file)
--- a/nnn.c
+++ b/nnn.c
@@ -90,7 +90,7 @@ enum action {
        SEL_CD,
        SEL_CDHOME,
        SEL_CDBEGIN,
-       SEL_LAST,
+       SEL_CDLAST,
        SEL_TOGGLEDOT,
        SEL_DETAIL,
        SEL_STATS,
@@ -386,22 +386,18 @@ xstricmp(const char *s1, const char *s2)
        return (int) (TOUPPER(*s1) - TOUPPER(*s2));
 }
 
-/* Trim all white space from both ends */
+/* Trim all whitespace from both ends, / from end */
 static char *
 strstrip(char *s)
 {
-       size_t size;
-       char *end;
-
-       size = strlen(s);
-
-       if (!size)
+       if (!s || !*s)
                return s;
 
-       end = s + size - 1;
-       while (end >= s && isspace(*end))
-               end--;
-       *(end + 1) = '\0';
+       size_t len = strlen(s) - 1;
+
+       while (len != 0 && (isspace(s[len]) || s[len] == '/'))
+               len--;
+       s[len + 1] = '\0';
 
        while (*s && isspace(*s))
                s++;
@@ -1281,10 +1277,10 @@ browse(char *ipath, char *ifilter)
        enum action sel = SEL_RUNARG + 1;
 
        xstrlcpy(path, ipath, sizeof(path));
-       xstrlcpy(lastdir, ipath, sizeof(lastdir));
        xstrlcpy(fltr, ifilter, sizeof(fltr));
        oldpath[0] = '\0';
        newpath[0] = '\0';
+       lastdir[0] = '\0'; /* Can't move back from initial directory */
 begin:
 
        if (sel == SEL_GOIN && S_ISDIR(sb.st_mode))
@@ -1471,56 +1467,66 @@ nochange:
                        break;
                case SEL_CD:
                {
-                       /* Read target dir */
+                       static char *tmp, *input;
+                       static int truecd;
+
+                       /* Save the program start dir */
                        tmp = getcwd(newpath, PATH_MAX);
                        if (tmp == NULL) {
                                printwarn();
                                goto nochange;
                        }
 
+                       /* Switch to current path for readline(3) */
                        if (chdir(path) == -1) {
                                printwarn();
                                goto nochange;
                        }
 
                        exitcurses();
-                       char *tmp = readline("chdir: ");
+                       tmp = readline("chdir: ");
                        initcurses();
 
+                       /* Change back to program start dir */
                        if (chdir(newpath) == -1)
                                printwarn();
 
-                       /* Save current */
-                       if (ndents > 0)
-                               mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
-
                        if (tmp[0] == '\0')
                                break;
                        else
+                               /* Add to readline(3) history */
                                add_history(tmp);
 
-                       char *input = tmp;
+                       input = tmp;
                        tmp = strstrip(tmp);
                        if (tmp[0] == '\0') {
                                free(input);
                                break;
                        }
 
+                       truecd = 0;
+
                        if (tmp[0] == '~') {
+                               /* Expand ~ to HOME absolute path */
                                char *home = getenv("HOME");
                                if (home)
-                                       snprintf(newpath, PATH_MAX,
-                                               "%s%s", home, tmp + 1);
-                               else
-                                       mkpath(path, tmp, newpath, sizeof(newpath));
-
-                               oldpath[0] = '\0';
+                                       snprintf(newpath, PATH_MAX, "%s%s", home, tmp + 1);
+                               else {
+                                       free(input);
+                                       break;
+                               }
                        } else if (tmp[0] == '-' && tmp[1] == '\0') {
-                               xstrlcpy(newpath, lastdir, sizeof(newpath));
-                               oldpath[0] = '\0';
+                               if (lastdir[0] == '\0') {
+                                       free(input);
+                                       break;
+                               }
 
+                               /* Switch to last visited dir */
+                               xstrlcpy(newpath, lastdir, sizeof(newpath));
+                               truecd = 1;
                        } else if ((r = all_dots(tmp))) {
                                if (r == 1) {
+                                       /* Always in the current dir */
                                        free(input);
                                        break;
                                }
@@ -1529,15 +1535,17 @@ nochange:
                                dir = path;
 
                                for (fd = 0; fd < r; fd++) {
-                                       /* There is no going back */
+                                       /* Reached / ? */
                                        if (strcmp(path, "/") == 0 ||
                                            strchr(path, '/') == NULL) {
+                                               /* If it's a cd .. at / */
                                                if (fd == 0) {
                                                        printmsg("You are at /");
                                                        free(input);
                                                        goto nochange;
                                                }
 
+                                               /* Can't cd beyond / anyway */
                                                break;
                                        } else {
                                                dir = xdirname(dir);
@@ -1549,28 +1557,44 @@ nochange:
                                        }
                                }
 
-                               /* Save history */
-                               xstrlcpy(oldpath, path, sizeof(oldpath));
+                               truecd = 1;
+
+                               /* Save the path in case of cd ..
+                                  We mark the current dir in parent dir */
+                               if (r == 1) {
+                                       xstrlcpy(oldpath, path, sizeof(oldpath));
+                                       truecd = 2;
+                               }
+
                                xstrlcpy(newpath, dir, sizeof(newpath));
-                       } else {
+                       } else
                                mkpath(path, tmp, newpath, sizeof(newpath));
-                               oldpath[0] = '\0';
-                       }
 
                        if (canopendir(newpath) == 0) {
-                               /* Save current */
-                               if (ndents > 0)
-                                       mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
-
                                printwarn();
                                free(input);
                                break;
                        }
 
+                       if (truecd == 0) {
+                               /* Probable change in dir */
+                               /* No-op if it's the same directory */
+                               if (strcmp(path, newpath) == 0) {
+                                       free(input);
+                                       break;
+                               }
+
+                               oldpath[0] = '\0';
+                       } else if (truecd == 1)
+                               /* Sure change in dir */
+                               oldpath[0] = '\0';
+
                        /* Save last working directory */
                        xstrlcpy(lastdir, path, sizeof(lastdir));
 
+                       /* Save the newly opted dir in path */
                        xstrlcpy(path, newpath, sizeof(path));
+
                        /* Reset filter */
                        xstrlcpy(fltr, ifilter, sizeof(fltr));
                        DPRINTF_S(path);
@@ -1583,15 +1607,20 @@ nochange:
                                clearprompt();
                                goto nochange;
                        }
+
                        if (canopendir(tmp) == 0) {
                                printwarn();
                                goto nochange;
                        }
 
+                       if (strcmp(path, tmp) == 0)
+                               break;
+
                        /* Save last working directory */
                        xstrlcpy(lastdir, path, sizeof(lastdir));
 
                        xstrlcpy(path, tmp, sizeof(path));
+                       oldpath[0] = '\0';
                        /* Reset filter */
                        xstrlcpy(fltr, ifilter, sizeof(fltr));
                        DPRINTF_S(path);
@@ -1602,19 +1631,33 @@ nochange:
                                goto nochange;
                        }
 
+                       if (strcmp(path, ipath) == 0)
+                               break;
+
                        /* Save last working directory */
                        xstrlcpy(lastdir, path, sizeof(lastdir));
 
                        xstrlcpy(path, ipath, sizeof(path));
+                       oldpath[0] = '\0';
                        /* Reset filter */
                        xstrlcpy(fltr, ifilter, sizeof(fltr));
                        DPRINTF_S(path);
                        goto begin;
-               case SEL_LAST:
+               case SEL_CDLAST:
+                       if (lastdir[0] == '\0')
+                               break;
+
+                       if (canopendir(lastdir) == 0) {
+                               printwarn();
+                               goto nochange;
+                       }
+
                        xstrlcpy(newpath, lastdir, sizeof(newpath));
                        xstrlcpy(lastdir, path, sizeof(lastdir));
                        xstrlcpy(path, newpath, sizeof(path));
                        oldpath[0] = '\0';
+                       /* Reset filter */
+                       xstrlcpy(fltr, ifilter, sizeof(fltr));
                        DPRINTF_S(path);
                        goto begin;
                case SEL_TOGGLEDOT: