NANO editor, how to get all the juice from it (mouse, syntax highlight and more)

In a few threads, people are writing in this forum about the need for a user friendly editor. GNU Nano should be that one, but not in its default state. A lot of people, including myself, are not used to the vi or emacs editor framework. And nano, using the default settings, is not quite friendly as the keybindings are not familiar to most.
A few weeks ago I opened an issue asking for nanorc configuration support. @hnyman closed it with the release of the nano-plus package.

However, despite the description, nano-plus comes without any familiar keybinding and shares the same problem with nano, at least out of the box. Some people in this forum have mentioned micro editor, but it is a 10MB monster written in golang. A lot of people used to modern GUI keybindings (Ctrl+C, Ctrl+V, Ctrl+X, Shift+arrow block selection, etc) have installed micro in their linux distros, mostly because they don't know that nano can provide the same functionality with a footprint of 170KB when all its features are activated.

The 120KB nano-plus package can do great things too, as it supports customization through nanorc. So, nano-plus can be transformed using ~/.nanorc or /etc/nanorc configuration files. Just copy this content below into one of those two configuration files and open nano to experience it:

## Sample initialization file for GNU nano.
##
## For the options that take parameters, the default value is shown.
## Other options are unset by default.  To make sure that an option
## is disabled, you can use "unset <option>".
##
## Characters that are special in a shell should not be escaped here.
## Inside string parameters, quotes should not be escaped -- the last
## double quote on the line will be seen as the closing quote.

## Make 'nextword' (Ctrl+Right) and 'chopwordright' (Ctrl+Delete)
## stop at word ends instead of at beginnings.
# set afterends

## When soft line wrapping is enabled, make it wrap lines at blanks
## (tabs and spaces) instead of always at the edge of the screen.
set atblanks

## Automatically indent a newly created line to the same number of
## tabs and/or spaces as the preceding line -- or as the next line
## if the preceding line is the beginning of a paragraph.
set autoindent

## Back up files to the current filename plus a tilde.
# set backup

## The directory to put unique backup files in.
set backupdir "/tmp"

## Use bold text instead of reverse video text.
# set boldtext

## Treat any line with leading whitespace as the beginning of a paragraph.
# set bookstyle

## The characters treated as closing brackets when justifying paragraphs.
## This may not include any blank characters.  Only closing punctuation,
## optionally followed by these closing brackets, can end sentences.
# set brackets ""')>]}"

## Automatically hard-wrap the current line when it becomes overlong.
# set breaklonglines

## Do case-sensitive searches by default.
unset casesensitive

## Constantly display the cursor position in the status bar or minibar.
set constantshow

## Use cut-from-cursor-to-end-of-line by default.
# set cutfromcursor

## Do not use the line below the title bar, leaving it entirely blank.
# set emptyline

## Set the target width for automatic hard-wrapping and for justifying
## paragraphs.  If the specified value is 0 or less, the wrapping point
## will be the terminal's width minus this number.
# set fill -8

## Draw a vertical stripe at the given column, to help judge text width.
## (This option does not have a default value.)
# set guidestripe 75

## Remember the used search/replace strings for the next session.
set historylog

## Display a "scrollbar" on the righthand side of the edit window.
set indicator

## Scroll the buffer contents per half-screen instead of per line.
# set jumpyscrolling

## Display line numbers to the left (and any anchors in the margin).
set linenumbers

## Enable vim-style lock-files.  This is just to let a vim user know you
## are editing a file [s]he is trying to edit and vice versa.  There are
## no plans to implement vim-style undo state in these files.
# set locking

## Fall back to slow libmagic to try and determine an applicable syntax.
# set magic

## The opening and closing brackets that are found by a matching-bracket
## search.  This may not contain blank characters.  The opening brackets
## must come before the closing ones, and they must be in the same order.
# set matchbrackets "(<[{)>]}"

## Suppress the title bar and show the filename plus a cursor-position
## percentage in the space of the status bar.
set minibar

## Enable mouse support, if available for your system.  When enabled,
## mouse clicks can be used to place the cursor, set the mark (with a
## double click), and execute shortcuts.  The mouse will work in the
## X Window System, and on the console when gpm is running.
set mouse

## Switch on multiple file buffers (inserting a file will put it into
## a separate buffer).
set multibuffer

## Don't convert files from DOS/Mac format.
# set noconvert

## Don't display the shortcut lists at the bottom of the screen.
set nohelp

## Don't automatically add a newline when a file does not end with one.
set nonewlines

## Set operating directory.  nano will not read or write files outside
## this directory and its subdirectories.  Also, the current directory
## is changed to here, so any files are inserted from this dir.  A blank
## string means the operating-directory feature is turned off.
# set operatingdir ""

## Remember the cursor position in each file for the next editing session.
set positionlog

## Preserve the XON and XOFF keys (^Q and ^S).
# set preserve

## The characters treated as closing punctuation when justifying paragraphs.
## This may not contain blank characters.  Only these closing punctuations,
## optionally followed by closing brackets, can end sentences.
# set punct "!.?"

## Make status-bar messages disappear after 1 keystroke instead of after 20.
# set quickblank

## The regular expression that matches quoting characters in email
## or line-comment introducers in source code.  The default is:
# set quotestr "^([ 	]*([!#%:;>|}]|//))+"

## Try to work around a mismatching terminfo terminal description.
# set rawsequences

## Fix Backspace/Delete confusion problem.
# set rebinddelete

## Do regular-expression searches by default.
## Regular expressions are of the extended type (ERE).
# set regexp

## Save a changed buffer automatically on exit; don't prompt.
# set saveonexit
## (The old form of this option, 'set tempfile', is deprecated.)

## Put the cursor on the highlighted item in the file browser, and
## show the cursor in the help viewer; useful for people who use a
## braille display and people with poor vision.
# set showcursor

## Make the Home key smarter: when Home is pressed anywhere but at the
## very beginning of non-whitespace characters on a line, the cursor
## will jump to that beginning (either forwards or backwards).  If the
## cursor is already at that position, it will jump to the true start
## of the line (the left edge).
set smarthome

## Spread overlong lines over multiple screen lines.
set softwrap

## Use this spelling checker instead of the internal one.  This option
## does not have a default value.
# set speller "aspell -x -c"

## Use the end of the title bar for some state flags: I = auto-indenting,
## M = mark, L = hard-wrapping long lines, R = recording, S = soft-wrapping.
set stateflags

## Use this tab size instead of the default; it must be greater than 0.
set tabsize 4

## Convert each typed tab to the fitting number of spaces.
set tabstospaces

## Snip whitespace at the end of lines when justifying or hard-wrapping.
# set trimblanks

## Save files by default in Unix format (also when they were DOS or Mac).
# set unix

## The two single-column characters used to display the first characters
## of tabs and spaces.  187 in ISO 8859-1 (0000BB in Unicode) and 183 in
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.
## The default when in a UTF-8 locale:
# set whitespace "»·"
## The default otherwise:
# set whitespace ">."

## Detect word boundaries differently by treating punctuation
## characters as parts of words.
# set wordbounds

## The characters (besides alphanumeric ones) that should be considered
## as parts of words.  This option does not have a default value.  When
## set, it overrides option 'set wordbounds'.
# set wordchars "<_>."

## Let an unmodified Backspace or Delete erase the marked region (instead
## of a single character, and without affecting the cutbuffer).
set zap

## Hide the bars plus help lines and use the whole terminal as edit area.
# set zero


## Paint the interface elements of nano.  These are examples; there are
## no colors by default, except for errorcolor and spotlightcolor.
set titlecolor bold,white,blue
set promptcolor black,yellow
set statuscolor brightwhite,orange
set errorcolor brightwhite,red
set spotlightcolor black,orange
set selectedcolor black,white
set stripecolor ,yellow
set scrollercolor grey
set numbercolor grey
set keycolor black,white
set functioncolor cyan

## In root's .nanorc you might want to use:
# set titlecolor bold,white,magenta
# set promptcolor black,yellow
# set statuscolor bold,white,magenta
# set errorcolor bold,white,red
# set spotlightcolor black,orange
# set selectedcolor lightwhite,cyan
# set stripecolor ,yellow
# set scrollercolor magenta
# set numbercolor magenta
# set keycolor lightmagenta
# set functioncolor magenta


## === Syntax coloring ===
## For all details, see https://www.nano-editor.org/

## To include most of the existing syntax definitions, you can do:
include "/usr/share/nano/*.nanorc"

## Or you can select just the ones you need.  For example:
# include "/usr/share/nano/html.nanorc"
# include "/usr/share/nano/python.nanorc"
# include "/usr/share/nano/sh.nanorc"

## In @PKGDATADIR@/extra/ you can find some syntaxes that are
## specific for certain distros or for some less common languages.
include "/usr/share/nano/extra/*.nanorc"


## If <Tab> should always produce four spaces when editing a Python file,
## independent of the settings of 'tabsize' and 'tabstospaces':
# extendsyntax python tabgives "    "

## If <Tab> should always produce an actual TAB when editing a Makefile:
# extendsyntax makefile tabgives "	"


## === Key bindings ===
## For all details, see https://www.nano-editor.org/

## If you want to suspend nano with one keystroke (instead of with ^T^Z):
# bind ^Z suspend main

## The <Ctrl+Delete> keystroke deletes the word to the right of the cursor.
## On some terminals the <Ctrl+Backspace> keystroke produces ^H, which is
## the ASCII character for backspace, so it is bound by default to the
## backspace function.  The <Backspace> key itself produces a different
## keycode, which is hard-bound to the backspace function.  So, if you
## normally use <Backspace> for backspacing and not ^H, you can make
## <Ctrl+Backspace> delete the word to the left of the cursor with:
# bind ^H chopwordleft main

## For a more mnemonic Comment keystroke (overriding Cut-from-cursor):
# bind M-K comment main

## If you want ^L to just refresh the screen and not center the cursor:
# bind ^L refresh main

## When you sometimes type M-J instead of M-K, or M-T instead of M-R:
# unbind M-J main
# unbind M-T main
## (Those functions are still accessible through ^T^J and ^T^V.)

## For quickly uppercasing or lowercasing the word under the cursor.
## (These effectively do a Ctrl+Right followed by a Shift+Ctrl+Left,
## and then pipe the selected text through a sed command.)
# bind Sh-M-U "eOce[1;6D|sed 's/.*/\U&/'" main
# bind Sh-M-L "eOce[1;6D|sed 's/.*/\L&/'" main

## If you would like nano to have keybindings that are more "usual",
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
## then uncomment these:
bind ^X cut main        # CTRL+X - Cut
bind ^C copy main       # CTRC+C - Copy
bind ^V paste all       # CTRL+V - Paste from GUI
bind ^B paste all       # CTRL+B - Paste fron nano
bind ^Q exit all        # CTRL+Q - Quit nano
bind ^O insert main     # CTRL+O - Open...  Ctrl+T to open browser
bind ^S savefile main   # CTRL+S - Save
bind ^W writeout main   # CTRL+W - Save as...
bind ^Z undo all        # CTRL+Z - Undo
bind ^Y redo all        # CTRL+Y - Redo
bind ^H replace main    # CTRL+H - Replace
bind ^F whereis all     # CTRL+F - Find
bind F1 help all        # Show help
bind F1 exit help       # Exit from help
bind F3 findnext main   # F3     - Find next
bind F13 findprevious main   # Shift-F3 - Find previous
bind F15 findprevious main   # Shift-F3 - Find previous
bind F5 refresh all     # F5     - refresh screen
bind ^/ comment main    # CTRL+/ - Comment lines#bind ^X cut main
bind ^P location main
bind ^L linter execute
bind ^E execute main

## Predefined keys:
# Alt+N toggle numbers
# Alt+M toggle mouse
# Alt+S toggle softwrap
# Alt+L toggle hard wrap

With this self illustrating keybindings you can exit with Ctrl-Q, use your basic edit keys, F1 for help, line numbers, and a smaller bottom bar with useful information with a vertical scroll bar among other nice features. But, you still lack block comments, color, position history, infinite undo/redo, custom spell checker, mouse support, integrated file browser, etc.

The same way we have the tiny wpad-basic-wolfssl package, the full wpad-openssl and some other trims in between, nano-full, or something better than nano-plus could be available too, at least I hope so.

In the meantime, since we have the sources, we can build our own nano-full package with the full set of features. The size varies depending on the target architecture. For instance, the ipk for aarch64 is about 172KB, while the version for arm is about 156KB, and even smaller for mips. The result is glorious, this is how it looks using SSH:

And this is using the integrated TTY:

The full nano-plus supports dozens of file formats, and with a few hundred of bytes you can add support for more of them. It supports mouse, has the integrated browser for easier multi document edit, block comments, infinite undo/redu, position history and many more small details that makes GNU nano in some aspects even better than micro editor.

The only way so far of getting nano-full is by building from sources, imagebuilder is not capable of building it. The process is quite easy assuming you have your OS ready for building code. Execute:

git clone -b master https://github.com/openwrt/openwrt
cd openwrt
SAFEPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PATH=$SAFEPATH ./scripts/feeds update -a
PATH=$SAFEPATH ./scripts/feeds install -a
echo "CONFIG_PACKAGE_nano-full=y" > .config
mkdir -p feeds/packages/utils/nano/files
tee feeds/packages/util/nano/files/nanorc <<EOF
## Nano editor configuration file - This version requires all the features

## Settings ##
set multibuffer         # Open multiple files
set indicator           # show vertical scroll bar
set minibar             # show the info bar
set linenumbers         # show line numbers Alt+N to toggle
set mouse               # enable mouse support Alt+M to toggle
set autoindent          # auto indent
set nonewlines          # don't insert newline at the end of the file
set softwrap            # wrap lines
set atblanks            # wrap lines at word boundaries
unset casesensitive     # non case sensitive search
set nohelp              # don't display help footer (F1) to display help
set suspend             # Allow nano to be suspended
set tabsize 4           # tab stops every 4 spaces
set tabstospaces        # don't convert tabs to spaces
set constantshow        # show cursor position and its unicode
set zap                 # Allows you to highlight text (CTRL+SHIFT+ARROW) and delete it with backspace.
set positionlog         # Remembers position between sessions
#set backup             # make backups
set backupdir "/tmp"    # where to put the backups
#set speller "aspell -x -c"  # Sets what spelling utility to use.

## Keybindings ##
bind ^X cut main        # CTRL+X - Cut
bind ^C copy main       # CTRC+C - Copy
bind ^V paste all       # CTRL+V - Paste from GUI
bind ^B paste all       # CTRL+B - Paste fron nano
bind ^Q exit all        # CTRL+Q - Quit program
bind ^O insert all      # CTRL+O - Open new file
bind ^S savefile main   # CTRL+S - Save
bind ^Z undo all        # CTRL+Z - Undo
bind ^Y redo all        # CTRL+Y - Redo
bind ^H replace main    # CTRL+H - Replace
bind ^F whereis main    # CTRL+F - Find
bind F3 findnext main   # F3     - Find next
bind F5 refresh all     # F5     - refresh screen
bind ^/ comment main    # CTRL+/ - Comment lines

## Syntax highlighting ##
include /usr/share/nano/*.nanorc
include /usr/share/nano/extra/*.nanorc

EOF
rm  feeds/packages/utils/nano/Makefile
nano feeds/packages/utils/nano/Makefile

and paste this:

#
# Copyright (C) 2007-2016 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=nano
PKG_VERSION:=6.2
PKG_RELEASE:=$(AUTORELEASE)

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/nano
PKG_HASH:=2bca1804bead6aaf4ad791f756e4749bb55ed860eec105a97fba864bc6a77cb3

PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=COPYING
PKG_MAINTAINER:=Hannu Nyman <hannu.nyman@iki.fi>
PKG_CPE_ID:=cpe:/a:gnu:nano

PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1

include $(INCLUDE_DIR)/package.mk

define Package/nano/Default
  SUBMENU:=Editors
  SECTION:=utils
  CATEGORY:=Utilities
  URL:=https://www.nano-editor.org/
  DEPENDS:=+libncurses
endef

define Package/nano
  $(call Package/nano/Default)
  TITLE:=GNU nano text editor (minimal features)
  VARIANT:=tiny
  DEFAULT_VARIANT:=1
endef

define Package/nano-plus
  $(call Package/nano/Default)
  TITLE:=GNU nano text editor (more features, Unicode)
  VARIANT:=plus
endef

define Package/nano-full
  $(call Package/nano/Default)
  TITLE:=GNU nano text editor (all features, Unicode)
  VARIANT:=full
  DEPENDS:=+libncurses +zlib
endef

define Package/nano/description
  Nano is a small and simple text editor for use on the terminal.

  Nano started as an enhanced clone of the Pico text editor.
  Nowadays Nano wants to be a generally useful editor with sensible
  defaults (linewise scrolling, no automatic line breaking).

  Nano is an official GNU package.
endef

define Package/nano-plus/description
  nano-plus - Additional features enabled, larger size than default nano.
  (multibuffer, Unicode/UTF-8, help, justify, nanorc)

  $(call Package/nano/description)
endef

define Package/nano-full/description
  nano-full - all features enabled, including syntax highlighting,
  multibuffer, Unicode/UTF-8, help, justify, nanorc, some key bindings)

  $(call Package/nano/description)
endef

ifeq ($(BUILD_VARIANT),full)
# full variant with all features included
  CONFIGURE_ARGS += \
	--enable-all \
	--enable-utf8
else ifeq ($(BUILD_VARIANT),plus)
# plus variant with more features included
  CONFIGURE_ARGS += \
	--enable-help \
	--enable-justify \
	--enable-linenumbers \
	--enable-multibuffer \
	--enable-nanorc \
	--enable-utf8 \
	--disable-browser \
	--disable-color \
	--disable-comment \
	--disable-extra \
	--disable-histories \
	--disable-libmagic \
	--disable-mouse \
	--disable-operatingdir \
	--disable-speller \
	--disable-tabcomp \
	--disable-wordcomp
else
# default tiny variant
  CONFIGURE_ARGS += \
	--enable-tiny \
	--enable-linenumbers \
	--disable-color \
	--disable-utf8
endif

CONFIGURE_VARS += \
	ac_cv_header_regex_h=no \

define Package/nano/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(CP) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) $(1)/usr/bin/
endef

define Package/nano-plus/install
	$(call Package/nano/install,$1)
endef

define Package/nano-full/install
	$(call Package/nano/install,$1)
	$(INSTALL_DIR) $(1)/etc $(1)/usr/share/nano
	$(INSTALL_CONF) ./files/nanorc $(1)/etc/nanorc
	$(CP) $(PKG_INSTALL_DIR)/usr/share/nano/* $(1)/usr/share/nano
endef

$(eval $(call BuildPackage,nano))
$(eval $(call BuildPackage,nano-plus))
$(eval $(call BuildPackage,nano-full))

Save and exit Nano (the default keys for that are Ctrl+S then Ctrl+X).

Now it is time to customize your device and the rest of packages you want by running:

make menuconfig

You are ready to bake your baby, so just do a:

make defconfig && make -j$(( $(nproc)*2+1))

You are done. Your sysupgrade image will be as always in bin/targets/*/*/. And the nano-full ipk for your architecture is waiting in bin/packages/*/packages/. Install the image or the package and you will enjoy the nano editor you always wanted.

2 Likes

I am going to share here one of the most useful nanorc files. This conf.nano will provide syntax highlighting for many configuration files including conf, .config, cfg and many standard configuration files such as crontab mirrorlist group hosts passwd rpc netconfig shadow fstab inittab inputrc protocols and sudoers.

Copy and paste the text below in /usr/share/nano/config.nanorc and enjoy highlighted configuration with nano. I use it in my PC too.

syntax "\conf$" "conf" "bash_profile" "bash_history" "\rc$" "(\.|/|)control$" "(\.(repo|conf|config|cfg|cnf|rc|lst|list|defs|ini|desktop|mime|types|preset|cache|seat|service|htaccess)$|(^|/)(\w*crontab|mirrorlist|group|hosts|passwd|rpc|netconfig|shadow|fstab|inittab|inputrc|protocols|sudoers)$|conf.d/|.config/|config/)"


# default text
color white "^.*$"

# special values
icolor brightblue "(^|\s|=)(default|true|false|on|off|yes|no)(\s|$)"

# keys
icolor cyan "^\s*(set\s+)?[A-Z0-9_\/\.\%\@+-]+\s*([:]|\>)"

# commands
color blue "^\s*set\s+\<"

# punctuation
color blue "[.]"

# numbers
color red "(^|\s|[[/:|<>(){}=,]|\])[-+]?[0-9](\.?[0-9])*%?($|\>)"

# keys
icolor cyan "^\s*(\$if )?([A-Z0-9_\/\.\%\@+-]|\s)+="

# punctuation
color blue "/"
color brightwhite "(\]|[()<>[{},;:=])"
color brightwhite "(^|\[|\{|\:)\s*-(\s|$)"

# section headings
icolor brightyellow "^\s*(\[([A-Z0-9_\.-]|\s)+\])+\s*$"
color brightcyan "^\s*((Sub)?Section\s*(=|\>)|End(Sub)?Section\s*$)"
color brightcyan "^\s*\$(end)?if(\s|$)"

# URLs
icolor green "\b(([A-Z]+://|www[.])[A-Z0-9/:#?&$=_\.\-]+)(\b|$| )"

# XML-like tags
icolor brightcyan "</?\w+((\s*\w+\s*=)?\s*("[^"]*"|'[^']*'|!?[A-Z0-9_:/]))*(\s*/)?>"

color green "\<(break|case|continue|do|done|elif|else|esac|exit|fi|for|function|if|in|read|return|select|shift|then|time|until|while)\>"
color green "\<(declare|eval|exec|export|let|local)\>"
color green "[{}():;|`$<>!=&\\]" "(\]|\[)"
color green "-[Ldefgruwx]\>"
color green "-(eq|ne|gt|lt|ge|le|s|n|z)\>"
color brightblue "\<(awk|cat|cd|ch(grp|mod|own)|cp|echo|env|grep|install|ln|make|mkdir|mv|popd|printf|pushd|rm|rmdir|sed|set|tar|touch|umask|unset)\>"

# Basic variable names (no braces).
color brightred "\$[-0-9@*#?$!]" "\$[[:alpha:]_][[:alnum:]_]*"
# More complicated variable names; handles braces and replacements and arrays.
color brightred "\$\{[#!]?([-@*#?$!]|[0-9]+|[[:alpha:]_][[:alnum:]_]*)(\[([[:space:]]*[[:alnum:]_]+[[:space:]]*|@)\])?(([#%/]|:?[-=?+])[^}]*\}|\[|\})"

# Comments.
color brightblack "(^|[[:space:]])#.*$"

# Strings.
color brightyellow ""(\\.|[^"])*"" "'(\\.|[^'])*'"

# Trailing whitespace.
color ,green "[[:space:]]+$"

From now on, when you edit any config file you will clearly see possible errors:

You can find plenty of additional nanorc files nere: https://github.com/scopatz/nanorc
They are very small, but makes life a lot easier.

1 Like

Yahoo! we now have nano-full as a package! which means you can add it not only when using the OpenWrt full kitchen, but also when using the imagebuilder. Or right now, by using the software management page of your router.

Thanks @hnyman

2 Likes

... or at least once the buildbot has built it for your target...

Ps. Right now only master has been changed. Possibly I will backport it to 22.03 and 21.02

2 Likes

It is available for use in the OpenWrt kitchen and using imagebuilder with the snapshot. So far it has not been backported to any official release.

2 Likes

Now backported (cherry-picked) to 19.07, 21.02 and 22.03 :wink:

2 Likes