Hello community, here is the log from the commit of package nnn for openSUSE:Factory checked in at 2018-08-12 20:55:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nnn (Old) and /work/SRC/openSUSE:Factory/.nnn.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nnn" Sun Aug 12 20:55:30 2018 rev:4 rq:628672 version:1.9 Changes: -------- --- /work/SRC/openSUSE:Factory/nnn/nnn.changes 2018-05-02 12:19:50.641068081 +0200 +++ /work/SRC/openSUSE:Factory/.nnn.new/nnn.changes 2018-08-12 20:55:33.589490032 +0200 @@ -1,0 +2,11 @@ +Fri Aug 10 06:17:44 UTC 2018 - dilawar.s.raj...@gmail.com + +- Update to 1.9 + * Support unlimited number of scripts + * Pass currently selected filename as first argument to custom scripts + * Support directory auto-select in navigate-as-you-type mode + * Show selection name in archive name prompt + * Better support on RHEL 25 with earlier version on curses + * Sample script for fzy integration + +------------------------------------------------------------------- Old: ---- nnn-1.8.tar.gz New: ---- nnn-1.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nnn.spec ++++++ --- /var/tmp/diff_new_pack.xPf770/_old 2018-08-12 20:55:33.953490771 +0200 +++ /var/tmp/diff_new_pack.xPf770/_new 2018-08-12 20:55:33.953490771 +0200 @@ -17,12 +17,12 @@ Name: nnn -Version: 1.8 +Version: 1.9 Release: 0 Summary: Terminal based file browser License: GPL-2.0-or-later Group: Productivity/File utilities -URL: https://github.com/jarun/nnn#nnn +Url: https://github.com/jarun/nnn#nnn Source0: https://github.com/jarun/nnn/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz BuildRequires: pkgconfig BuildRequires: readline-devel ++++++ nnn-1.8.tar.gz -> nnn-1.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/.travis.yml new/nnn-1.9/.travis.yml --- old/nnn-1.8/.travis.yml 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/.travis.yml 2018-08-10 04:51:49.000000000 +0200 @@ -33,7 +33,8 @@ - unset CFLAGS - sudo apt-get update -qy - sudo apt-get install -qy python3 python3-pip - - sudo python3 -m pip install packagecore + - sudo python3 -m pip install --upgrade pip + - sudo python3 -m pip install --upgrade packagecore setuptools - packagecore -o dist/ "${TRAVIS_TAG#v}" - mv ../$REPO-${TRAVIS_TAG}.tar.gz dist/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/CHANGELOG new/nnn-1.9/CHANGELOG --- old/nnn-1.8/CHANGELOG 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/CHANGELOG 2018-08-10 04:51:49.000000000 +0200 @@ -1,3 +1,19 @@ +nnn v1.9 +2018-08-10 + +What's in? +- Support unlimited number of scripts +- Pass currently selected filename as first argument to custom scripts +- Support directory auto-select in _navigate-as-you-type_ mode +- Show selection name in archive name prompt +- Support Cygwin opener +- Better support on RHEL 25 with earlier version on curses +- Sample script for `fzy` integration +- Now available on OpenBSD +- Disabled package generation for Ubuntu 17.10 + +------------------------------------------------------------------------------- + nnn v1.8 2018-05-02 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/Makefile new/nnn-1.9/Makefile --- old/nnn-1.8/Makefile 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/Makefile 2018-08-10 04:51:49.000000000 +0200 @@ -1,4 +1,4 @@ -VERSION = 1.8 +VERSION = 1.9 PREFIX ?= /usr/local MANPREFIX ?= $(PREFIX)/share/man diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/README.md new/nnn-1.9/README.md --- old/nnn-1.8/README.md 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/README.md 2018-08-10 04:51:49.000000000 +0200 @@ -19,15 +19,17 @@ [![nnn screencast](https://i.imgur.com/wNtI24c.jpg)](https://vimeo.com/233223942 "Click to see nnn in action!") -<p align="center"><i>nnn in action!</i></a></p> +<p align="center"><i>nnn in action! (click to play video)</i></a></p> -`nnn` is probably the [fastest and most resource-sensitive](#performance) (with all its capabilities) file browser you have ever used. It's extremely flexible too - integrates with your DE and favourite GUI utilities, works with the desktop opener, supports bookmarks, has smart navigation shortcuts, [navigate-as-you-type](#navigate-as-you-type-mode) mode, disk usage analyzer mode, comprehensive file details and much more. `nnn` was initially forked from [noice](http://git.2f30.org/noice/) but is significantly [different](https://github.com/jarun/nnn/wiki/nnn-vs.-noice) today. +`nnn` is probably the [fastest and most resource-sensitive](#performance) (with all its capabilities) file manager you have ever used. It's extremely flexible too - integrates with your DE and favourite GUI utilities, works with the desktop opener, supports bookmarks, has smart navigation shortcuts, [navigate-as-you-type](#navigate-as-you-type-mode) mode, disk usage analyzer mode, comprehensive file details and much more. `nnn` was initially forked from [noice](http://git.2f30.org/noice/) but is significantly [different](https://github.com/jarun/nnn/wiki/nnn-vs.-noice) today. If you want to edit a file in vi with some soothing music in the background while referring to a spec in your GUI PDF viewer, `nnn` got it! [Quickstart](#quickstart) and see how `nnn` simplifies those long desktop sessions... -Have fun with it! Missing a feature? Want to contribute? Head to the rolling [ToDo list](https://github.com/jarun/nnn/issues/58). +`nnn` supports as many scripts as you want to run! So you can [integrate utilities](https://github.com/jarun/nnn#sample-scripts) like sxiv (to view images in a directory) or fzy (to fuzzy find files in a directory tree) easily. -*Love smart and efficient terminal utilities? Explore my repositories. Buy me a cup of coffee if they help you.* +Have fun with it! Missing a feature? Want to contribute? Head to the rolling [ToDo list](https://github.com/jarun/nnn/issues/110). + +*Love smart and efficient utilities? Explore [my repositories](https://github.com/jarun?tab=repositories). Buy me a cup of coffee if they help you.* <p align="center"> <a href="https://saythanks.io/to/jarun"><img src="https://img.shields.io/badge/say-thanks!-ff69b4.svg" /></a> @@ -49,7 +51,7 @@ - [Keyboard shortcuts](#keyboard-shortcuts) - [Filters](#filters) - [Navigate-as-you-type mode](#navigate-as-you-type-mode) - - [File type abbreviations](#file-type-abbreviations) + - [File indicators](#file-indicators) - [File handling](#file-handling) - [Help](#help) - [Quickstart](#quickstart) @@ -59,7 +61,8 @@ - [cd on quit](#cd-on-quit) - [copy file paths to clipboard](#copy-file-paths-to-clipboard) - [copy file paths when X is missing](#copy-file-paths-when-x-is-missing) - - [run a custom script](#run-a-custom-script) + - [run custom scripts](#run-custom-scripts) + - [sample scripts](#sample-scripts) - [change dir color](#change-dir-color) - [file copy, move, delete](#file-copy-move-delete) - [boost chdir prompt](#boost-chdir-prompt) @@ -76,7 +79,7 @@ - Modes - basic, detail, disk usage analyzer (du) - Navigation - Familiar, easy shortcuts (arrows, `~`, `-`, `&`) - - *Navigate-as-you-type* mode for the maverick + - *Navigate-as-you-type* mode with dir auto-select for the maverick - Handy bookmarks, start at bookmark, pin and visit directory - chdir prompt with tab completion (interprets cd ..... too!) - Roll-over at edges, page through entries @@ -100,11 +103,11 @@ - Create, rename files and directories - Batch rename/move/delete current directory entries in vidir (from moreutils) - Spawn SHELL (fallback sh) in the current directory - - Run a custom script in the current directory + - Run custom scripts in the current directory - Copy absolute file paths with/without X (*easy* shell integration) - Change directory at exit (*easy* shell integration) - Open any file in EDITOR (fallback vi) or PAGER (fallback less) - - Open current directory in a custom GUI file browser + - Open current directory in a custom GUI file manager - Terminal screensaver/locker (default vlock, customizable) integration - Unicode support - Highly optimized code, minimal resource usage @@ -145,6 +148,7 @@ - [Gentoo](https://packages.gentoo.org/packages/app-misc/nnn) (`emerge nnn`) - [Homebrew](http://formulae.brew.sh/formula/nnn) (`brew install nnn`) - [NixOS](https://github.com/NixOS/nixpkgs/tree/master/pkgs/applications/misc/nnn) (`nix-env -i nnn`) +- [OpenBSD](https://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/sysutils/nnn/) (`pkg_add nnn`) - [openSUSE](https://software.opensuse.org/package/nnn) (and packages for several other distros) (`zypper in nnn`) - [Slackware](http://slackbuilds.org/repository/14.2/system/nnn/) (`slackpkg install nnn`) - [Source Mage](http://codex.sourcemage.org/test/shell-term-fm/nnn/) (`cast nnn`) @@ -178,7 +182,7 @@ usage: nnn [-b key] [-c N] [-e] [-i] [-l] [-p nlay] [-S] [-v] [-h] [PATH] -The missing terminal file browser for X. +The missing terminal file manager for X. positional arguments: PATH start dir [default: current dir] @@ -240,7 +244,7 @@ f | Archive entry F | List archive ^F | Extract archive - ^K | Copy file path + Space, ^K | Copy file path ^Y | Toggle multi-copy ^T | Toggle path quote ^L | Redraw, clear prompt @@ -272,11 +276,13 @@ In this mode directories are opened in filter mode, allowing continuous navigation. Works best with the **arrow keys**. -#### File type abbreviations +In case of only one match and it's a directory, `nnn` auto selects the directory and enters it in this mode. + +#### File indicators -The following abbreviations are used in the detail view: +The following indicators are used in the detail view: -| Symbol | File Type | +| Indicator | File Type | | --- | --- | | `/` | Directory | | `*` | Executable | @@ -415,19 +421,43 @@ Note that you may want to keep quotes disabled in this case. -#### run a custom script +#### run custom scripts -Export the path to the custom script: +`nnn` can invoke custom scripts with the currently selected file name as argument 1. - export NNN_SCRIPT=/usr/local/bin/script.sh +Export the path to the custom executable script: -Sample script to open image files in current dir in sxiv: + export NNN_SCRIPT=/usr/local/bin/nscript - #!/usr/bin/env sh +Press <kbd>R</kbd> to run the script in the current directory. - sxiv -q * >/dev/null 2>&1 +It's possible to run multiple scripts with `nnn` as long as the scripts are in the same location and share the same prefix. To enable multiple scripts, -Press <kbd>R</kbd> to run the script in the current directory. + export NNN_MULTISCRIPT=1 + +With the example of `NNN_SCRIPT` above, some more scripts could be: + + /usr/local/bin/nscript1 + /usr/local/bin/nscript2 + /usr/local/bin/nscriptcustom1 + /usr/local/bin/nscriptcustom2 + and so on... + +Type the correct suffix when prompted on pressing the keybind <kbd>R</kbd>. To use the base script (`NNN_SCRIPT`), just press <kbd>Enter</kbd>. + +##### sample scripts + +- Open image files in current dir in **sxiv**: + + #!/usr/bin/env sh + + sxiv -q * >/dev/null 2>&1 + +- Fuzzy find files in **fzy** and open with xdg-open: + + #!/usr/bin/env sh + + xdg-open $(find -type f | fzy) >/dev/null 2>&1 #### change dir color @@ -449,7 +479,7 @@ #### 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) are available to you based on your readline [configuration](https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC9). +`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) are available to you based on your readline [configuration](https://wiki.archlinux.org/index.php/Readline). #### work faster at rename prompt @@ -477,6 +507,7 @@ - [It's FOSS](https://itsfoss.com/nnn-file-browser-linux/) - [FOSSMint](https://www.fossmint.com/nnn-linux-terminal-file-browser/) +- [LinuxLinks](https://www.linuxlinks.com/nnn-fast-and-flexible-file-manager/) ### Developers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/nnn.1 new/nnn-1.9/nnn.1 --- old/nnn-1.8/nnn.1 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/nnn.1 2018-08-10 04:51:49.000000000 +0200 @@ -1,9 +1,9 @@ -.Dd May 02, 2018 +.Dd Aug 10, 2018 .Dt NNN 1 .Os .Sh NAME .Nm nnn -.Nd the missing terminal file browser for X +.Nd the missing terminal file manager for X .Sh SYNOPSIS .Nm .Op Ar -b key @@ -18,7 +18,7 @@ .Op Ar PATH .Sh DESCRIPTION .Nm -(Noice is Not Noice) is a performance-optimized, feature-packed fork of the noice terminal file browser with seamless desktop integration, simplified navigation, \fInavigate-as-you-type\fR mode, bookmarks, disk usage analyzer mode, comprehensive file details and much more. It remains a simple and efficient file browser that stays out of your way. +(Noice is Not Noice) is a performance-optimized, feature-packed fork of noice (http://git.2f30.org/noice/) with seamless desktop integration, simplified navigation, \fInavigate-as-you-type\fR mode, bookmarks, disk usage analyzer mode, comprehensive file details and much more. It remains a simple and efficient file manager that stays out of your way. .Pp .Nm opens the current working directory by default if @@ -26,8 +26,7 @@ is not specified. .Pp .Nm -supports both vi-like and emacs-like key bindings in the default -configuration. The default key bindings are listed below. +supports both vi-like and emacs-like key bindings as listed below. .Pp .Bl -tag -width "l, [Right], [Return] or C-mXXXX" -offset indent -compact .It Ic [Up], k, ^P @@ -106,7 +105,7 @@ List files in archive .It Ic ^F Extract archive in current directory -.It Ic ^K +.It Ic Space, ^K Invoke file path copier .It Ic ^Y Toggle multiple file path copy mode @@ -207,6 +206,8 @@ .Pp In the \fInavigate-as-you-type\fR mode directories are opened in filter mode, allowing continuous navigation. Works best with the \fBarrow keys\fR. +.br +In case of only one match and it's a directory, `nnn` auto selects the directory and enters it in this mode. .Sh MULTI-COPY MODE The absolute path of a single file can be copied to clipboard by pressing \fI^K\fR if NNN_COPIER is set (see ENVIRONMENT section below). @@ -264,10 +265,16 @@ \fBNNN_QUOTE_ON:\fR wrap copied paths within single quotes. Useful for pasting names in the shell. .Pp -\fBNNN_SCRIPT:\fR path to a custom script to run. +\fBNNN_SCRIPT:\fR path to a custom script to invoke with currently selected file name as argument 1. .Bd -literal - export NNN_SCRIPT=/usr/local/bin/script.sh + export NNN_SCRIPT=/usr/local/bin/nscript .Ed +.Pp +\fBNNN_MULTISCRIPT:\fR run multiple custom scripts. +.Bd -literal + export NNN_MULTISCRIPT=1 +.Ed +.Pp \fBNNN_SHOW_HIDDEN:\fR show hidden files. .Bd -literal export NNN_SHOW_HIDDEN=1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/nnn.c new/nnn-1.9/nnn.c --- old/nnn-1.8/nnn.c 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/nnn.c 2018-08-10 04:51:49.000000000 +0200 @@ -138,7 +138,7 @@ #endif /* DEBUGMODE */ /* Macro definitions */ -#define VERSION "1.8" +#define VERSION "1.9" #define GENERAL_INFO "License: BSD 2-Clause\nWebpage: https://github.com/jarun/nnn" #define LEN(x) (sizeof(x) / sizeof(*(x))) @@ -213,7 +213,7 @@ blkcnt_t blocks; /* number of 512B blocks allocated */ mode_t mode; uint nlen; /* Length of file name; can be uchar (< NAME_MAX + 1) */ -}__attribute__ ((packed, aligned(_ALIGNMENT))) *pEntry; +} __attribute__ ((packed, aligned(_ALIGNMENT))) *pEntry; /* Bookmark */ typedef struct { @@ -279,6 +279,7 @@ #define ATOOL 4 #define APACK 5 #define VIDIR 6 +#define UNKNOWN 7 /* Utilities to open files, run actions */ static char * const utils[] = { @@ -286,28 +287,28 @@ "exiftool", #ifdef __APPLE__ "/usr/bin/open", +#elif defined __CYGWIN__ + "cygstart", #else "xdg-open", #endif "nlay", "atool", "apack", - "vidir" + "vidir", + "UNKNOWN" }; /* Common strings */ #define STR_NFTWFAIL_ID 0 -#define STR_ATROOT_ID 1 -#define STR_NOHOME_ID 2 -#define STR_INPUT_ID 3 -#define STR_INVBM_ID 4 -#define STR_COPY_ID 5 -#define STR_DATE_ID 6 +#define STR_NOHOME_ID 1 +#define STR_INPUT_ID 2 +#define STR_INVBM_ID 3 +#define STR_COPY_ID 4 +#define STR_DATE_ID 5 -static const char messages[][16] = -{ +static const char messages[][16] = { "nftw failed", - "already at /", "HOME not set", "no traversal", "invalid key", @@ -358,17 +359,17 @@ static uchar crc8fast(uchar const message[], size_t n) { - static uchar data, remainder; - static size_t byte; + static uchar data, remainder; + static size_t byte; - /* Divide the message by the polynomial, a byte at a time */ - for (remainder = byte = 0; byte < n; ++byte) { - data = message[byte] ^ (remainder >> (WIDTH - 8)); - remainder = crc8table[data] ^ (remainder << 8); - } + /* Divide the message by the polynomial, a byte at a time */ + for (remainder = byte = 0; byte < n; ++byte) { + data = message[byte] ^ (remainder >> (WIDTH - 8)); + remainder = crc8table[data] ^ (remainder << 8); + } - /* The final remainder is the CRC */ - return remainder; + /* The final remainder is the CRC */ + return remainder; } /* Messages show up at the bottom */ @@ -442,24 +443,6 @@ } /* - * Custom xstrlen() - */ -static size_t -xstrlen(const char *s) -{ - static size_t len; - len = 0; - - if (!s) - return len; - - while (*s) - ++len, ++s; - - return len; -} - -/* * Just a safe strncpy(3) * Always null ('\0') terminates if both src and dest are valid pointers. * Returns the number of bytes copied including terminating null byte. @@ -475,7 +458,7 @@ if (!src || !dest || !n) return 0; - len = xstrlen(src) + 1; + len = strlen(src) + 1; if (n > len) n = len; else if (len > n) @@ -518,22 +501,6 @@ } /* - * Custom strcmp(), just what we need. - * Returns 0 if same, -ve if s1 < s2, +ve if s1 > s2. - */ -static int -xstrcmp(const char *s1, const char *s2) -{ - if (!s1 || !s2) - return -1; - - while (*s1 && *s1 == *s2) - ++s1, ++s2; - - return *s1 - *s2; -} - -/* * The poor man's implementation of memrchr(3). * We are only looking for '/' in this program. * And we are NOT expecting a '/' at the end. @@ -573,7 +540,7 @@ xstrlcpy(buf, path, PATH_MAX); /* Find last '/'. */ - last_slash = xmemrchr((uchar *)buf, '/', xstrlen(buf)); + last_slash = xmemrchr((uchar *)buf, '/', strlen(buf)); if (last_slash != NULL && last_slash != buf && last_slash[1] == '\0') { /* Determine whether all remaining characters are slashes. */ @@ -625,7 +592,7 @@ { static char *base; - base = xmemrchr((uchar *)path, '/', xstrlen(path)); + base = xmemrchr((uchar *)path, '/', strlen(path)); return base ? base + 1 : path; } @@ -886,7 +853,7 @@ if (!s || !*s) return s; - size_t len = xstrlen(s) - 1; + size_t len = strlen(s) - 1; while (len != 0 && (isspace(s[len]) || s[len] == '/')) --len; @@ -1115,7 +1082,7 @@ printprompt(ln); while ((r = get_wch(ch)) != ERR) { - if (*ch == 127 /* handle DEL */ || *ch == KEY_DC || *ch == KEY_BACKSPACE) { + if (*ch == 127 /* handle DEL */ || *ch == KEY_DC || *ch == KEY_BACKSPACE || *ch == '\b') { if (len == 1) { cur = oldcur; *ch = CONTROL('L'); @@ -1155,26 +1122,6 @@ redraw(path); goto end; -#if 0 - case CONTROL('L'): // fallthrough - case CONTROL('K'): // fallthrough - case CONTROL('Y'): // fallthrough - case CONTROL('_'): // fallthrough - case CONTROL('R'): // fallthrough - case CONTROL('O'): // fallthrough - case CONTROL('B'): // fallthrough - case CONTROL('V'): // fallthrough - case CONTROL('J'): // fallthrough - case CONTROL(']'): // fallthrough - case CONTROL('G'): // fallthrough - case CONTROL('X'): // fallthrough - case CONTROL('F'): // fallthrough - case CONTROL('I'): // fallthrough - case CONTROL('T'): - if (len == 1) - cur = oldcur; - goto end; -#endif case '?': // '?' is an invalid regex, show help instead if (len == 1) { cur = oldcur; @@ -1191,9 +1138,29 @@ wln[len] = (wchar_t)*ch; wln[++len] = '\0'; wcstombs(ln, wln, REGEX_MAX); - ndents = total; + + /* Forward-filtering optimization: + * - new matches can only be a subset of current matches. + */ + /* ndents = total; */ + if (matches(pln) == -1) continue; + + /* If the only match is a dir, auto-select and cd into it */ + if (cfg.filtermode && ndents == 1 && S_ISDIR(dents[0].mode)) { + *ch = KEY_ENTER; + cur = 0; + goto end; + } + + /* + * redraw() should be above the auto-select optimization, for + * the case where there's an issue with dir auto-select, say, + * due to a permission problem. The transition is jumpy in + * case of such an error. However, we optimize for successful + * cases where the dir has permissions. This skips a redraw(). + */ redraw(path); printprompt(ln); } @@ -1243,29 +1210,33 @@ mvaddnwstr(y, x, buf, len + 1); move(y, x + wcswidth(buf, pos)); - if ((r = get_wch(ch)) != ERR) { + r = get_wch(ch); + if (r != ERR) { if (r == OK) { - if (*ch == KEY_ENTER || *ch == '\n' || *ch == '\r') - break; - - if (*ch == CONTROL('L')) { + switch (*ch) { + case KEY_ENTER: //fallthrough + case '\n': //fallthrough + case '\r': + goto END; + case '\b': /* some old curses (e.g. rhel25) still send '\b' for backspace */ + if (pos > 0) { + memmove(buf + pos - 1, buf + pos, (len - pos) << 2); + --len, --pos; + } //fallthrough + case '\t': /* TAB breaks cursor position, ignore it */ + continue; + case CONTROL('L'): clearprompt(); printprompt(prompt); len = pos = 0; continue; - } - - if (*ch == CONTROL('A')) { + case CONTROL('A'): pos = 0; continue; - } - - if (*ch == CONTROL('E')) { + case CONTROL('E'): pos = len; continue; - } - - if (*ch == CONTROL('U')) { + case CONTROL('U'): clearprompt(); printprompt(prompt); memmove(buf, buf + pos, (len - pos) << 2); @@ -1278,10 +1249,6 @@ if (keyname(*ch)[0] == '^') continue; - /* TAB breaks cursor position, ignore it */ - if (*ch == '\t') - continue; - if (pos < NAME_MAX - 1) { memmove(buf + pos + 1, buf + pos, (len - pos) << 2); buf[pos] = *ch; @@ -1317,6 +1284,7 @@ } } +END: buf[len] = '\0'; if (old_curs != ERR) curs_set(old_curs); @@ -1340,13 +1308,12 @@ /* Handle absolute path */ if (name[0] == '/') return xstrlcpy(out, name, n); - else { - /* Handle root case */ - if (istopdir(dir)) - len = 1; - else - len = xstrlcpy(out, dir, n); - } + + /* Handle root case */ + if (istopdir(dir)) + len = 1; + else + len = xstrlcpy(out, dir, n); out[len - 1] = '/'; return (xstrlcpy(out + len, name, n - len) + len); @@ -1405,7 +1372,7 @@ return NULL; for (r = 0; bookmark[r].key && r < BM_MAX; ++r) { - if (xstrcmp(bookmark[r].key, key) == 0) { + if (strcmp(bookmark[r].key, key) == 0) { if (bookmark[r].loc[0] == '~') { char *home = getenv("HOME"); @@ -1763,6 +1730,28 @@ return NULL; } +static char * +xgetpwuid(uid_t uid) +{ + struct passwd *pwd = getpwuid(uid); + + if (!pwd) + return utils[UNKNOWN]; + + return pwd->pw_name; +} + +static char * +xgetgrgid(gid_t gid) +{ + struct group *grp = getgrgid(gid); + + if (!grp) + return utils[UNKNOWN]; + + return grp->gr_name; +} + /* * Follows the stat(1) output closely */ @@ -1822,7 +1811,7 @@ /* Show permissions, owner, group */ dprintf(fd, "\n Access: 0%d%d%d/%s Uid: (%u/%s) Gid: (%u/%s)", (sb->st_mode >> 6) & 7, (sb->st_mode >> 3) & 7, - sb->st_mode & 7, perms, sb->st_uid, (getpwuid(sb->st_uid))->pw_name, sb->st_gid, (getgrgid(sb->st_gid))->gr_name); + sb->st_mode & 7, perms, sb->st_uid, xgetpwuid(sb->st_uid), sb->st_gid, xgetgrgid(sb->st_gid)); /* Show last access time */ strftime(g_buf, 40, messages[STR_DATE_ID], localtime(&sb->st_atime)); @@ -1964,7 +1953,7 @@ "ef | Archive entry\n" "eF | List archive\n" "d^F | Extract archive\n" - "d^K | Copy file path\n" + "6Space, ^K | Copy file path\n" "d^Y | Toggle multi-copy\n" "d^T | Toggle path quote\n" "d^L | Redraw, clear prompt\n" @@ -2017,6 +2006,8 @@ dprintf(fd, "NNN_NO_X: %s (%s)\n", getenv("NNN_NO_X"), g_cppath); if (getenv("NNN_SCRIPT")) dprintf(fd, "NNN_SCRIPT: %s\n", getenv("NNN_SCRIPT")); + if (getenv("NNN_MULTISCRIPT")) + dprintf(fd, "NNN_MULTISCRIPT: %s\n", getenv("NNN_MULTISCRIPT")); if (getenv("NNN_SHOW_HIDDEN")) dprintf(fd, "NNN_SHOW_HIDDEN: %s\n", getenv("NNN_SHOW_HIDDEN")); @@ -2237,7 +2228,7 @@ DPRINTF_S(fname); for (i = 0; i < n; ++i) - if (xstrcmp(fname, dents[i].name) == 0) + if (strcmp(fname, dents[i].name) == 0) return i; return 0; @@ -2312,7 +2303,7 @@ } /* Strip trailing slashes */ - for (i = xstrlen(path) - 1; i > 0; --i) + for (i = strlen(path) - 1; i > 0; --i) if (path[i] == '/') path[i] = '\0'; else @@ -2331,7 +2322,7 @@ ncols = PATH_MAX; /* No text wrapping in cwd line */ - /* Show CWD: - xstrlen(CWD) - 1 = 6 */ + /* Show CWD: - strlen(CWD) - 1 = 6 */ g_buf[ncols - 6] = '\0'; printw(CWD "%s\n\n", g_buf); @@ -2418,7 +2409,7 @@ static char oldname[NAME_MAX + 1] __attribute__ ((aligned)); char *dir, *tmp, *run = NULL, *env = NULL; struct stat sb; - int r, fd, presel, ncp, copystartid = 0, copyendid = 0; + int r, fd, presel, ncp = 0, copystartid = 0, copyendid = 0; enum action sel = SEL_RUNARG + 1; bool dir_changed = FALSE; @@ -2492,7 +2483,10 @@ case SEL_BACK: /* There is no going back */ if (istopdir(path)) { - printmsg(messages[STR_ATROOT_ID]); + /* Continue in navigate-as-you-type mode, if enabled */ + if (cfg.filtermode) + presel = FILTER; + goto nochange; } @@ -2684,8 +2678,12 @@ /* Show a message if already at / */ if (istopdir(path)) { - printmsg(messages[STR_ATROOT_ID]); free(input); + + /* Continue in navigate-as-you-type mode, if enabled */ + if (cfg.filtermode) + presel = FILTER; + goto nochange; } @@ -2730,7 +2728,7 @@ if (truecd == 0) { /* Probable change in dir */ /* No-op if it's the same directory */ - if (xstrcmp(path, newpath) == 0) + if (strcmp(path, newpath) == 0) break; oldname[0] = '\0'; @@ -2762,13 +2760,11 @@ if (sel == SEL_CDBEGIN) dir = ipath; - if (!xdiraccess(dir)) { + if (!xdiraccess(dir)) goto nochange; - } - if (xstrcmp(path, dir) == 0) { + if (strcmp(path, dir) == 0) break; - } /* Save last working directory */ xstrlcpy(lastdir, path, PATH_MAX); @@ -2785,7 +2781,7 @@ case SEL_CDLAST: // fallthrough case SEL_VISIT: if (sel == SEL_VISIT) { - if (xstrcmp(mark, path) == 0) + if (strcmp(mark, path) == 0) break; tmp = mark; @@ -2830,7 +2826,7 @@ if (!xdiraccess(newpath)) goto nochange; - if (xstrcmp(path, newpath) == 0) + if (strcmp(path, newpath) == 0) break; oldname[0] = '\0'; @@ -2987,83 +2983,91 @@ copycurname(); goto begin; case SEL_COPY: - if (!(cfg.noxdisplay || copier)) + if (!(cfg.noxdisplay || copier)) { printmsg(messages[STR_COPY_ID]); - else if (ndents) { - if (cfg.copymode) { - r = mkpath(path, dents[cur].name, newpath, PATH_MAX); - if (!appendfpath(newpath, r)) - goto nochange; - ++ncp; - printmsg(newpath); - } else if (cfg.quote) { - g_buf[0] = '\''; - r = mkpath(path, dents[cur].name, g_buf + 1, PATH_MAX); - g_buf[r] = '\''; - g_buf[r + 1] = '\0'; + goto nochange; + } - if (cfg.noxdisplay) - writecp(g_buf, r + 1); /* Truncate NULL from end */ - else - spawn(copier, g_buf, NULL, NULL, F_NOTRACE); + if (!ndents) + goto nochange; - g_buf[r] = '\0'; - printmsg(g_buf + 1); - } else { - r = mkpath(path, dents[cur].name, newpath, PATH_MAX); - if (cfg.noxdisplay) - writecp(newpath, r - 1); /* Truncate NULL from end */ - else - spawn(copier, newpath, NULL, NULL, F_NOTRACE); - printmsg(newpath); - } + if (cfg.copymode) { + r = mkpath(path, dents[cur].name, newpath, PATH_MAX); + if (!appendfpath(newpath, r)) + goto nochange; + ++ncp; + printmsg(newpath); + } else if (cfg.quote) { + g_buf[0] = '\''; + r = mkpath(path, dents[cur].name, g_buf + 1, PATH_MAX); + g_buf[r] = '\''; + g_buf[r + 1] = '\0'; + + if (cfg.noxdisplay) + writecp(g_buf, r + 1); /* Truncate NULL from end */ + else + spawn(copier, g_buf, NULL, NULL, F_NOTRACE); + + g_buf[r] = '\0'; + printmsg(g_buf + 1); + } else { + r = mkpath(path, dents[cur].name, newpath, PATH_MAX); + if (cfg.noxdisplay) + writecp(newpath, r - 1); /* Truncate NULL from end */ + else + spawn(copier, newpath, NULL, NULL, F_NOTRACE); + printmsg(newpath); } goto nochange; case SEL_COPYMUL: - if (!(cfg.noxdisplay || copier)) + if (!(cfg.noxdisplay || copier)) { printmsg(messages[STR_COPY_ID]); - else if (ndents) { - cfg.copymode ^= 1; - if (cfg.copymode) { - g_crc = crc8fast((uchar *)dents, ndents * sizeof(struct entry)); + goto nochange; + } + + if (!ndents) + goto nochange; + + cfg.copymode ^= 1; + if (cfg.copymode) { + g_crc = crc8fast((uchar *)dents, ndents * sizeof(struct entry)); + copystartid = cur; + copybufpos = 0; + ncp = 0; + printmsg("multi-copy on"); + DPRINTF_S("copymode on"); + goto nochange; + } + + if (!ncp) { /* Handle range selection */ + if (cur < copystartid) { + copyendid = copystartid; copystartid = cur; - copybufpos = 0; - ncp = 0; - printmsg("multi-copy on"); - DPRINTF_S("copymode on"); - } else { - if (!ncp) { /* Handle range selection */ - if (cur < copystartid) { - copyendid = copystartid; - copystartid = cur; - } else - copyendid = cur; - - if (copystartid < copyendid) { - for (r = copystartid; r <= copyendid; ++r) - if (!appendfpath(newpath, mkpath(path, dents[r].name, newpath, PATH_MAX))) - goto nochange; - - snprintf(newpath, PATH_MAX, "%d files copied", copyendid - copystartid + 1); - printmsg(newpath); - } - } + } else + copyendid = cur; - if (copybufpos) { /* File path(s) written to the buffer */ - if (cfg.noxdisplay) - writecp(pcopybuf, copybufpos - 1); /* Truncate NULL from end */ - else - spawn(copier, pcopybuf, NULL, NULL, F_NOTRACE); - - if (ncp) /* Some files cherry picked */ - { - snprintf(newpath, PATH_MAX, "%d files copied", ncp); - printmsg(newpath); - } - } else - printmsg("multi-copy off"); + if (copystartid < copyendid) { + for (r = copystartid; r <= copyendid; ++r) + if (!appendfpath(newpath, mkpath(path, dents[r].name, newpath, PATH_MAX))) + goto nochange; + + snprintf(newpath, PATH_MAX, "%d files copied", copyendid - copystartid + 1); + printmsg(newpath); } } + + if (copybufpos) { /* File path(s) written to the buffer */ + if (cfg.noxdisplay) + writecp(pcopybuf, copybufpos - 1); /* Truncate NULL from end */ + else + spawn(copier, pcopybuf, NULL, NULL, F_NOTRACE); + + if (ncp) { /* Some files cherry picked */ + snprintf(newpath, PATH_MAX, "%d files copied", ncp); + printmsg(newpath); + } + } else + printmsg("multi-copy off"); goto nochange; case SEL_QUOTE: cfg.quote ^= 1; @@ -3074,10 +3078,14 @@ printmsg("quotes off"); goto nochange; case SEL_OPEN: // fallthrough - case SEL_ARCHIVE: // fallthrough + case SEL_ARCHIVE: + if (ndents <= 0) + break; // fallthrough case SEL_NEW: if (sel == SEL_OPEN) tmp = xreadline(NULL, "open with: "); + else if (sel == SEL_ARCHIVE) + tmp = xreadline(dents[cur].name, "name: "); else tmp = xreadline(NULL, "name: "); @@ -3085,7 +3093,7 @@ break; /* Allow only relative, same dir paths */ - if (tmp[0] == '/' || xstrcmp(xbasename(tmp), tmp) != 0) { + if (tmp[0] == '/' || strcmp(xbasename(tmp), tmp) != 0) { printmsg(messages[STR_INPUT_ID]); goto nochange; } @@ -3169,13 +3177,13 @@ break; /* Allow only relative, same dir paths */ - if (tmp[0] == '/' || xstrcmp(xbasename(tmp), tmp) != 0) { + if (tmp[0] == '/' || strcmp(xbasename(tmp), tmp) != 0) { printmsg(messages[STR_INPUT_ID]); goto nochange; } /* Skip renaming to same name */ - if (xstrcmp(tmp, dents[cur].name) == 0) + if (strcmp(tmp, dents[cur].name) == 0) break; /* Open the descriptor to currently open directory */ @@ -3233,8 +3241,24 @@ if (sel == SEL_RUNSCRIPT) { tmp = getenv("NNN_SCRIPT"); - if (tmp) - spawn(run, tmp, NULL, path, F_NORMAL | F_SIGINT); + if (tmp) { + if (getenv("NNN_MULTISCRIPT")) { + size_t _len = xstrlcpy(newpath, tmp, PATH_MAX); + + tmp = xreadline(NULL, "script suffix: "); + if (tmp && tmp[0]) + xstrlcpy(newpath + _len - 1, tmp, PATH_MAX - _len); + + tmp = newpath; + } + + char *curfile = NULL; + + if (ndents > 0) + curfile = dents[cur].name; + + spawn(run, tmp, curfile, path, F_NORMAL | F_SIGINT); + } } else { spawn(run, NULL, NULL, path, F_NORMAL | F_MARKER); @@ -3251,7 +3275,7 @@ goto begin; case SEL_RUNARG: run = xgetenv(env, run); - if ((!run || !run[0]) && (xstrcmp("VISUAL", env) == 0)) + if ((!run || !run[0]) && (strcmp("VISUAL", env) == 0)) run = editor ? editor : xgetenv("EDITOR", "vi"); spawn(run, dents[cur].name, NULL, path, F_NORMAL); break; @@ -3293,22 +3317,22 @@ static void usage(void) { - printf("usage: nnn [-b key] [-c N] [-e] [-i] [-l]\n\ - [-p nlay] [-S] [-v] [-h] [PATH]\n\n\ -The missing terminal file browser for X.\n\n\ -positional arguments:\n\ - PATH start dir [default: current dir]\n\n\ -optional arguments:\n\ - -b key specify bookmark key to open\n\ - -c N specify dir color, disables if N>7\n\ - -e use exiftool instead of mediainfo\n\ - -i start in navigate-as-you-type mode\n\ - -l start in light mode (fewer details)\n\ - -p nlay path to custom nlay\n\ - -S start in disk usage analyzer mode\n\ - -v show program version and exit\n\ - -h show this help and exit\n\n\ -Version: %s\n%s\n", VERSION, GENERAL_INFO); + printf("usage: nnn [-b key] [-c N] [-e] [-i] [-l]\n" + " [-p nlay] [-S] [-v] [-h] [PATH]\n\n" + "The missing terminal file manager for X.\n\n" + "positional arguments:\n" + " PATH start dir [default: current dir]\n\n" + "optional arguments:\n" + " -b key specify bookmark key to open\n" + " -c N specify dir color, disables if N>7\n" + " -e use exiftool instead of mediainfo\n" + " -i start in navigate-as-you-type mode\n" + " -l start in light mode (fewer details)\n" + " -p nlay path to custom nlay\n" + " -S start in disk usage analyser mode\n" + " -v show program version and exit\n" + " -h show this help and exit\n\n" + "Version: %s\n%s\n", VERSION, GENERAL_INFO); exit(0); } @@ -3422,7 +3446,7 @@ if (!player) player = utils[NLAY]; - /* Get the desktop file browser, if set */ + /* Get the desktop file manager, if set */ desktop_manager = getenv("NNN_DE_FILE_MANAGER"); /* Get screensaver wait time, if set; copier used as tmp var */ @@ -3442,6 +3466,7 @@ cfg.noxdisplay = 1; struct passwd *pass = getpwuid(getuid()); + xstrlcpy(g_cppath, "/tmp/nnncp", 11); xstrlcpy(g_cppath + 10, pass->pw_name, 33); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/nnn.h new/nnn-1.9/nnn.h --- old/nnn-1.8/nnn.h 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/nnn.h 2018-08-10 04:51:49.000000000 +0200 @@ -156,6 +156,7 @@ { KEY_F(5), SEL_REDRAW, "", "" }, /* Undocumented */ /* Copy currently selected file path */ { CONTROL('K'), SEL_COPY, "", "" }, + { ' ', SEL_COPY, "", "" }, /* Toggle copy multiple file paths */ { CONTROL('Y'), SEL_COPYMUL, "", "" }, /* Toggle quote on while copy */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nnn-1.8/packagecore.yaml new/nnn-1.9/packagecore.yaml --- old/nnn-1.8/packagecore.yaml 2018-05-01 23:53:38.000000000 +0200 +++ new/nnn-1.9/packagecore.yaml 2018-08-10 04:51:49.000000000 +0200 @@ -1,7 +1,7 @@ name: nnn maintainer: Arun Prakash Jana <engineera...@gmail.com> license: BSD 2-Clause -summary: The missing terminal file browser for X. +summary: The missing terminal file manager for X. homepage: https://github.com/jarun/nnn commands: install: @@ -95,16 +95,6 @@ builddeps: - make - gcc - - pkg-config - - libncursesw5-dev - - libreadline6-dev - deps: - - libncursesw5 - - libreadline6 - ubuntu17.10: - builddeps: - - make - - gcc - pkg-config - libncursesw5-dev - libreadline6-dev