aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Arun Prakash Jana <engineerarun@gmail.com>2017-09-10 13:05:25 +0530
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2017-09-10 13:05:25 +0530
commit28f69e59faa0f067ee404cc85b7d2e36a6432d90 (patch)
tree7c5fccfe0ccea606df28144ace8da91f5eaeb3f6
parent5ab6dd2feddfeb04eb873ff82626184f556548a2 (diff)
downloadnnn-28f69e59faa0f067ee404cc85b7d2e36a6432d90.tar.gz
Support file and dir create
-rw-r--r--README.md19
-rw-r--r--nnn.14
-rw-r--r--nnn.c82
-rw-r--r--nnn.h7
4 files changed, 87 insertions, 25 deletions
diff --git a/README.md b/README.md
index ef92c32..c055ca3 100644
--- 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 cd1446a..9ad5c82 100644
--- 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 547c471..0709f53 100644
--- 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 f6bb4a7..2de943d 100644
--- 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 */