]> Sergey Matveev's repositories - nnn.git/commitdiff
Support file and dir create
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 10 Sep 2017 07:35:25 +0000 (13:05 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 10 Sep 2017 07:35:25 +0000 (13:05 +0530)
README.md
nnn.1
nnn.c
nnn.h

index ef92c3241db26563f95b83b4e8804b12edf450df..c055ca3f9568eb18401ce0fc394125146f9e3f26 100644 (file)
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ Have fun with it! PRs are welcome. Check out [#1](https://github.com/jarun/nnn/i
   - Numeric order (1, 2, ... 10, 11, ...) for numeric names
   - Sort by modification time, size
 - Convenience
-  - Rename files
+  - Create, rename files and directories
   - Spawn SHELL (fallback sh) in the current directory
   - Invoke file path copier (*easy* shell integration)
   - Change directory at exit (*easy* shell integration)
@@ -209,17 +209,18 @@ Search keyword and option completion scripts for Bash, Fish and Zsh can be found
               - | Go to last visited dir
               / | Filter dir contents
              ^/ | Open desktop search tool
-              . | Toggle hide .dot files
-              b | Show bookmark prompt
+              . | Toggle hide . files
+              b | Bookmark prompt
              ^B | Pin current dir
              ^V | Go to pinned dir
-              c | Show change dir prompt
+              c | Change dir prompt
               d | Toggle detail view
-              D | Show current file details
-              m | Show concise media info
-              M | Show full media info
+              D | File details
+              m | Brief media info
+              M | Full media info
+              n | Create new
              ^R | Rename selected entry
-              s | Toggle sort by file size
+              s | Toggle sort by size
               S | Toggle disk usage mode
               t | Toggle sort by mtime
               ! | Spawn SHELL in dir
@@ -228,7 +229,7 @@ Search keyword and option completion scripts for Bash, Fish and Zsh can be found
               p | Open entry in PAGER
              ^K | Invoke file path copier
              ^L | Redraw, clear prompt
-              ? | Show help, settings
+              ? | Help, settings
               Q | Quit and change dir
           q, ^Q | Quit
 ```
diff --git a/nnn.1 b/nnn.1
index cd1446ad54e554116406836dac98edeec192f1f8..9ad5c824245021b4f4a8c71ccab25c2cf92bb82e 100644 (file)
--- a/nnn.1
+++ b/nnn.1
@@ -72,9 +72,11 @@ Toggle detail view
 .It Ic D
 Show current file details screen
 .It Ic m
-Show concise media info
+Show brief media info
 .It Ic M
 Show full media info
+.It Ic n
+Create a new file or directory
 .It Ic ^R
 Rename selected entry
 .It Ic s
diff --git a/nnn.c b/nnn.c
index 547c471f04f3555189b5a3d0526a566c52f683df..0709f53e05d8d50d3229ba7ee7ea627c018b9f7d 100644 (file)
--- a/nnn.c
+++ b/nnn.c
@@ -254,6 +254,7 @@ static char * const utils[] = {
 static char *STR_NFTWFAIL = "nftw(3) failed";
 static char *STR_ATROOT = "You are at /";
 static char *STR_NOHOME = "HOME not set";
+static char *STR_INPUT = "No traversal delimiter allowed";
 
 /* For use in functions which are isolated and don't return the buffer */
 static char g_buf[MAX_CMD_LEN];
@@ -1016,8 +1017,12 @@ xreadline(char *fname)
        wchar_t *buf = (wchar_t *)g_buf;
        size_t buflen = NAME_MAX - 1;
 
-       DPRINTF_S(fname)
-       len = pos = mbstowcs(buf, fname, NAME_MAX);
+       if (fname) {
+               DPRINTF_S(fname);
+               len = pos = mbstowcs(buf, fname, NAME_MAX);
+       } else
+               len = (size_t)-1;
+
        /* For future: handle NULL, say for a new name */
        if (len == (size_t)-1) {
                buf[0] = '\0';
@@ -1083,7 +1088,7 @@ xreadline(char *fname)
        if (old_curs != ERR) curs_set(old_curs);
 
        settimeout();
-       DPRINTF_S(buf)
+       DPRINTF_S(buf);
        wcstombs(g_buf, buf, NAME_MAX);
        return g_buf;
 }
@@ -1647,17 +1652,18 @@ show_help(char *path)
              "e- | Go to last visited dir\n"
              "e/ | Filter dir contents\n"
             "d^/ | Open desktop search tool\n"
-             "e. | Toggle hide .dot files\n"
-             "eb | Show bookmark prompt\n"
+             "e. | Toggle hide . files\n"
+             "eb | Bookmark prompt\n"
             "d^B | Pin current dir\n"
             "d^V | Go to pinned dir\n"
-             "ec | Show change dir prompt\n"
+             "ec | Change dir prompt\n"
              "ed | Toggle detail view\n"
-             "eD | Show current file details\n"
-             "em | Show concise media info\n"
-             "eM | Show full media info\n"
+             "eD | File details\n"
+             "em | Brief media info\n"
+             "eM | Full media info\n"
+            "en | Create new\n"
             "d^R | Rename selected entry\n"
-             "es | Toggle sort by file size\n"
+             "es | Toggle sort by size\n"
              "eS | Toggle disk usage mode\n"
              "et | Toggle sort by mtime\n"
              "e! | Spawn SHELL in dir\n"
@@ -1666,7 +1672,7 @@ show_help(char *path)
              "ep | Open entry in PAGER\n"
             "d^K | Invoke file path copier\n"
             "d^L | Redraw, clear prompt\n"
-             "e? | Show help, settings\n"
+             "e? | Help, settings\n"
              "eQ | Quit and change dir\n"
          "aq, ^Q | Quit\n\n");
 
@@ -2607,6 +2613,56 @@ nochange:
                        } else if (!copier)
                                printmsg("NNN_COPIER is not set");
                        goto nochange;
+               case SEL_NEW:
+                       printprompt("name: ");
+                       tmp = xreadline(NULL);
+                       clearprompt();
+                       if (tmp == NULL || tmp[0] == '\0')
+                               break;
+
+                       /* Allow only relative, same dir paths */
+                       if (tmp[0] == '/' || basename(tmp) != tmp) {
+                               printmsg(STR_INPUT);
+                               goto nochange;
+                       }
+
+                       /* Open the descriptor to currently open directory */
+                       fd = open(path, O_RDONLY | O_DIRECTORY);
+                       if (fd == -1) {
+                               printwarn();
+                               goto nochange;
+                       }
+
+                       /* Check if another file with same name exists */
+                       if (faccessat(fd, tmp, F_OK, AT_SYMLINK_NOFOLLOW) != -1) {
+                               printmsg("Entry exists");
+                               goto nochange;
+                       }
+
+                       /* Check if it's a dir or file */
+                       printprompt("Press 'f' for file or 'd' for dir");
+                       cleartimeout();
+                       r = getch();
+                       settimeout();
+                       if (r == 'f') {
+                               r = openat(fd, tmp, O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+                               close(r);
+                       } else if (r == 'd')
+                               r = mkdirat(fd, tmp, S_IRWXU | S_IRWXG | S_IRWXO);
+                       else {
+                               close(fd);
+                               break;
+                       }
+
+                       if (r == -1) {
+                               printwarn();
+                               close(fd);
+                               goto nochange;
+                       }
+
+                       close(fd);
+                       mkpath(path, tmp, oldpath, PATH_MAX);
+                       goto begin;
                case SEL_RENAME:
                        if (ndents <= 0)
                                break;
@@ -2617,9 +2673,9 @@ nochange:
                        if (tmp == NULL || tmp[0] == '\0')
                                break;
 
-                       /* Allow only relative paths */
+                       /* Allow only relative, same dir paths */
                        if (tmp[0] == '/' || basename(tmp) != tmp) {
-                               printmsg("relative paths only");
+                               printmsg(STR_INPUT);
                                goto nochange;
                        }
 
diff --git a/nnn.h b/nnn.h
index f6bb4a7df9710005956690f4ab3becaf3fb6ff44..2de943d44bae14a543cfd545d766e788fd1cbf98 100644 (file)
--- a/nnn.h
+++ b/nnn.h
@@ -34,6 +34,7 @@ enum action {
        SEL_MTIME,
        SEL_REDRAW,
        SEL_COPY,
+       SEL_NEW,
        SEL_RENAME,
        SEL_HELP,
        SEL_RUN,
@@ -138,12 +139,14 @@ static struct key bindings[] = {
        { 't',            SEL_MTIME,     "",     "" },
        /* Redraw window */
        { CONTROL('L'),   SEL_REDRAW,    "",     "" },
-       { KEY_F(5),       SEL_REDRAW,    "",     "" },
+       { KEY_F(5),       SEL_REDRAW,    "",     "" }, /* Undocumented */
        /* Copy currently selected file path */
        { CONTROL('K'),   SEL_COPY,      "",     "" },
+       /* Create a new file */
+       { 'n',            SEL_NEW,       "",     "" },
        /* Show rename prompt */
        { CONTROL('R'),   SEL_RENAME,    "",     "" },
-       { KEY_F(2),       SEL_RENAME,    "",     "" },
+       { KEY_F(2),       SEL_RENAME,    "",     "" }, /* Undocumented */
        /* Show help */
        { '?',            SEL_HELP,      "",     "" },
        /* Run command */