Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
OpenVi: Portable OpenBSD vi for Unix systems (github.com/johnsonjh)
109 points by rdpintqogeogsaa on Feb 19, 2022 | hide | past | favorite | 66 comments


Last time I checked OpenBSD's vi didn't support utf8 - this is a show stopper in 2022.


Vis looks like a very minimal but thoroughly modern alternative.

https://github.com/martanne/vis


Indeed. Nvi, which was recommended elsewhere in the thread, supports UTF-8 and is my preferred vi clone. (Actually, OpenBSD vi is an old version of nvi without UTF-8 support.)


I plan to eventually support multibyte in a way I can contribute upstream to OpenBSD.

The 1.8 branch of the Nvi editor, as well as the Nvi2 fork have mulitbyte support.

I could be mistaken but I believe both of these multibyte implementations descend from the late itojun's (http://www.itojun.org/itojun.html) Nvi-m17n project (archived at https://cgit.freebsd.org/ports/tree/editors/nvi-m17n/files). A paper was presented at USENIX99 (http://www.usenix.org/events/usenix99/full_papers/hagino/hag...) describing the work, which was actually developed as part of the KAME project.


It isn't for everyone. I have never come across a real need for more than standard ASCII in any of my work. It absolutely isn't needed for managing unix config files, which is the primary use case for "lightweight" editors like this.


Congratulations on English being the one and only language you use to make quick notes, then. I personally mix in words from my native language wherever I need an extra bit of semantic precision, and I'd rather not have to switch between editors to do so.


> Congratulations on English being the one and only language you use to make quick notes, then

It is. If it weren't, I would not use this editor.


Not to sound dismissive, but that is a rather niche use case


For multilinguals (which is over half of the world's population), throwing in terms from another language or entirely switching to a different language mid-sentence during a conversation is entirely normal. I can't imagine it being that rare in personal notes.


Sure, but how many of that number are keeping personal notes in vi?


Presumably, any number that prefer a terminal based workflow, or have the Vi key scheme burned into muscle memory. Or those that prefer an ultra-minimalist text editor for writing.

Just a decade ago, it was almost a meme that the Emacs and Vi factions fought over which editor is better. I imagine that those that truly bought into the Vi ecosystem/fandom use it in preference to other available options.


You're speaking to a veteran of said editor wars (vi won, naturally) and I still think the number of folks you describe is small these days. I imagine most have switched to a more GUI-friendly editor.


I dogfood OpenVi and use it for OpenVi development, however, 99% of my normal programming workflow is (terminal-based) NeoVim.

The other 1% is Eclipse or VSCode ... and I have VSCode setup to use the embedding functionality of NeoVim.


I wonder if they could merge back utf8 patches from FreeBSD.


This is something that I plan to tackle eventually, and in such as way the work can be contributed back to OpenBSD.


Is it not a feature given how many security issues come out of parsing? There is virtue in the thing you’ll edit files with as root being as simple as you can make it.


You have nvi2 in ports.


Yes, and also vim and other vi clones. But what is the point of having a secure and integrated OS if you have to pull software from ports (which are not so thoroughly audited and tested as the main OS)?

One point of using BSD is (so the BSD people say) to have an operating system where everything comes from the same team - kernel and userland, unlike Linux where kernel and userland comes from dozens if not hundreds of different origins. But if you start to use arbitrary ports in BSD your OS is not much better than Linux in that regard


Historically, this is why basic vi (of whatever flavor) was so popular. I could hop on any Unix and it was there OOB. I dealt with some mixed set of Solaris, BSD, HP-UX, Irix, Tru64, AIX, and Linux for so long.

For a host I did primary development on, I’d install vim (visual mode and then syntax highlighting was so nice).

But we managed config centrally with idempotent scripts that handled the differences (like no getent on HP-UX). We did have to install ksh88 or a clone everywhere to get a stable consistent shell. GNU was flaky on so many platforms then.

Vi was always there for those WTF scenarios, less as a primary programming editor. And it is so nice on slow connections, where repainting the whole screen for every keystroke sucked.

It really annoyed me when Linuxes dropped the basic vi everywhere in favor of nano. I’d be fine with nano as a default for accessibility, but at least have some vi in my path.

Our standard images include it, but I always forget when I’m testing/debugging locally with Vagrant or a Docker image.

Vi is always a little weird. I don’t think any 2 people use it the same. Everyone has their own go-to set of commands. Pairing with grey beards influenced me so much.

I actually started with emacs in college, but real life with 1,000s of servers forced the change. I don’t have the muscle memory for it anymore and have no desire to go back.

Nowadays my local neovim config is almost VSCode. But I still like VSCode-ish in vi more than vi-ish in VSCode. I tried, but inevitably do something that VSCode’s vim plug-in doesn’t support.

I do use go more and more for complex stuff, but often am forced back to shell due to old kernels still out there which hurts my soul.


> It really annoyed me when Linuxes dropped the basic vi everywhere in favor of nano. I’d be fine with nano as a default for accessibility, but at least have some vi in my path.

Don’t nearly all distros still have something (usually nvi or vim) in /usr/bin/vi out of the box?


The behavior of the traditional vi is much different than vim and other clones. Nvi was a actually a re-implementation of the traditional vi for 4BSD (to be clean of AT&T code) and thus was originally intended to be bug-for-bug compatible, but breaking away where the original vi behavior was nonsensical or terrible.

For vim, `set compatible` or `set cp` is close, but still not traditional vi by any means.

A multibyte variant of the traditional vi is maintained at https://github.com/n-t-roff/heirloom-ex-vi/.

Nvi (now on version 1.8x) is also maintained - https://repo.or.cz/nvi.git

Nvi2 is yet another fork of Nvi, https://github.com/lichray/nvi2

Despite the very similar names, all of these editors have a variety of different features, and are structured very differently.

Nvi has a concept of a front-end and a back-end (which uses the BDB database). OpenVi uses the OpenBSD version of Berkeley DB which derives from 1.85. Nvi (1.8x) provides a minimal version of code also derived from that release intended from use with Nvi, and (IIRC) also provides support for using Db3/4/5. Similar situation for Nvi2.

Nvi 1.8 has been structured where a third library layer has been added, which doesn't exist in OpenBSD's vi or OpenVi. There is scripting support (Tcl, Perl, etc.) and GUI code in the other various forks ... all of these support various different options as well.

I should probably make a matrix of these, but you can get an idea by looking at the settable options implemented in each of the variants (as they historically include a comment to document from where the option originated):

OpenVi: https://github.com/johnsonjh/OpenVi/blob/22c2a7022e31d91e09e...

OpenBSD vi: https://github.com/openbsd/src/blob/master/usr.bin/vi/common...

Nvi2: https://github.com/lichray/nvi2/blob/5fcdc13656500a8c5b4c073...

Nvi1: https://repo.or.cz/nvi.git/blob/HEAD:/common/options.c#l52


I look forward to config files in right to left Hebrew

Or maybe Arabic so the characters flow into each other


No need to wait, I'm sure many people have written their name in their native RTL script for git's "user.name" configuration key.


For that level of UTF-8 editing, a non-mulitbyte version of the editor suffices. In fact, you can insert and modify multibyte signatures and names using the map facility, however the glyphs are not rendered on screen but are shown at the byte-level.

Improvements are in order, and should be made, but the mere inability to visually render multibyte characters is not always a showstopper.


Do they right-align their command lines and files?

Or once the Arabic exceeds 50% the alignment of the buffer flips? :)


Or it could be just as simple as me jotting down some notes in my native language, which includes such exotic characters as ę and ą. You know, so I don't have to go back to using a code page like back in good old DOS days, that I'm actually too young to have lived through.


It isn't really an "old" version of Nvi by any means - the development went in a different direction. OpenBSD's vi has been developed mostly independently since being imported back in 1997.

The documentation has been updated to explain the rationale - see https://github.com/johnsonjh/OpenVi#why

In the 25 years since the "fork", OpenBSD vi has diverged significantly from Nvi1 (as Nvi2 has diverged from Nvi1 as well).

It has grown much smaller and more compact - one might argue more focused.

Much of the code has been simplified and many features removed, rather than added. Still, it has adopted features and taken some fixes back from Nvi1/Nvi2 versions and other variants, such as adopting support for expandtab from NetBSD's variant.

You can get a good idea of the history of this particular fork by reviewing the ChangeLog at https://raw.githubusercontent.com/johnsonjh/OpenVi/master/Ch... where the OpenBSD changes begin in 1997.


Hi, I'm the "perpetrator" responsible for OpenVi. Apologies to everyone! /s

I've added details to the README to hopefully explain why it exists: https://github.com/johnsonjh/OpenVi#why

The OpenVi ChangeLog at https://raw.githubusercontent.com/johnsonjh/OpenVi/master/Ch... includes all the history going back to 1993's Nvi 0.93. Nvi 1.79 was released in 1996, which is the version OpenBSD's vi was derived from.

The ChangeLog entries are only a summary of the full commit messages - the complete details are in OpenBSD's CVS tree, and viewable a bit easier via GitHub (https://github.com/openbsd/src/commits/master/usr.bin/vi)

Changes to the (OpenVi bundled) OpenBSD regular expression engine are not included in the legacy ChangeLog, but you can see that development in the CVS tree or via GitHub as well (https://github.com/openbsd/src/commits/master/lib/libc/regex).

OpenVi also utilizes the OpenBSD version of Berkely DB (https://github.com/openbsd/src/commits/master/lib/libc/db).



The NeoVim people are now spamming HN with ads?


20% discount with coupon code #NEWERVIMIER2022


If you want to go ultimately minimalist http://ex-vi.sourceforge.net/ builds and runs on most modern systems just fine.

Having learned vi across eight-ish different unices at once my muscle memory is very minimalist so I tend to use ex-vi preferentially, simply because everything else adds features I don't use that I can accidentally activate with a typo and break myself out of flow figuring out wtf just happened.

I can absolutely imagine that for somebody who tends to use OpenBSD on their own machines, being able to have the exact same editor elsewhere could be really quite handy for much the same reasons.


Using Carsten Kunze's actively maintained continuation of Gunnar Ritter's (outstanding) traditional ex/vi project is highly recommended. See https://github.com/n-t-roff/heirloom-ex-vi/.

The parent project on SourceForge hasn't had any activity for 15 years, nor a release in 17+ years, and contains various known bugs, all of which are fixed in Carsten Kunze's project.


That sounds like a better idea for everybody who isn't me.

Naturally I've accumulated a few local patches over the years so I'll have to figure out which of them are obsoleted by the improvements in that version and which of them I want to port first ;)

(thanks very much for sharing that this exists though, I shall be digging in when I have available tuits)


It should be simple, mostly fixes and no major features or refactoring.


I also ported it to use malloc instead of treating the heap as a single giant array, though a quick look suggests they did it rather more competently (though admittedly given my C code that's really not a high bar to clear).

I suspect that once I untangle my somewhat hacky version of that the remainder of my patches will apply just fine but there'll still be at least a bit of mental effort involved.


Do you have a summary of those changes or a repo up anywhere? If they are general-purpose you might consider sending a PR upstream to n-t-roff


A little late replying here, sorry.

Probably nothing that interesting - the malloc stuff was the big change and n-t-roff already did a much better job of it than I did.

But if there's anything in the remaining stack once I've backed it out that seems useful I'll be sure to PR it - even if it doesn't make it in to mainline it seems as good a way to memorialise the patch for other people's use as anything else.

(the repo is currently private because gritter had politely requested nobody make it work on windows and one of my patches worked around a cygwin bug - given the advent of WSL I doubt anybody would want that one anyway so I expect to let it be lost to time along with the half-arsed malloc code)


It will be nice to see your efforts publicly.


OpenBSD also includes mg, which is a "minimalist emacs" for people who don't want to install the full emacs port but who have emacs muscle memory.


pEmacs is "even better" for minimalists.

https://github.com/hughbarney/pEmacs

Stripped -Os build using link-time GC on Linux x86_64 glibc:

     30 KB  pe*
Compare to portable mg:

    132 KB  mg*
OpenVi is ...

    278 KB  bin/vi*
An even smaller vi implementation is Xvi.

     56 KB  src/xvi*
This would be an 'ersatz' vi since it is not built on top of a real ex-mode.

Even tinier ersatz-vi clones exist (`levee`, `s`, `VIrus`) but these are not complete implementations.


I've been using busybox vi as my root editor but it doesn't have secure mode which disables shell access within vi. It looks like OpenVi and nvi2 have them. Are they preferable to busybox vi if I want better security as a root editor?


If you’re that paranoid, isn’t it better to run the editor on some other machine? E.g vim with scp support? Then there’s no editor to infect/replace/screw with on the Important Server.


Secure mode doesn't really make anything more secure if you're the one using it. It just lets you add it to the list of allowed commands in the sudoers file without giving someone a root shell. We used to do that all the time at one job that didn't let you log in as root and wanted you to do everything through sudo. You'd just sudo vi /some/random/file and then :! and have a root shell.


OpenVi uses only secure functions (snprintf, strlcpy, etc.) as a matter of policy.

This may lead to a more secure editor for untrusted files, but it depends on how careful the other editors are. (I haven't examined them at that level.)


Why would somebody want to use this over nvi, elvis, or the original BSD vi?

(I assume that people who are interested in features already know where to find (Neo)Vim.)


That "nvi" is nvi2 at OpenBSD ports.

On features, most people would be fine with a vi clone with utf8 support.


To give a quick overview of ':set'-able options (`:set all` output) of the various editors that derive from 'nvi' ... [no Nvi2 here ... yet] ...

Nv1 [nvi-1.81.6-45-g864873d3 (2022-02-21)]:

    noaltwerase     nocomment       noignorecase    nomodeline      noreadonly      noshowmode      nottywerase
    noautoindent    noedcompatible  keytime=6       msgcat="./"     noredraw        sidescroll=16   noverbose
    autoprint       escapetime=1    noleftright     noprint=""      remap           noslowopen      warn
    noautowrite     noerrorbells    lines=24        nonumber        report=5        nosourceany     window=23
    backup=""       noexrc          nolisp          nooctal         noruler         tabstop=8       nowindowname
    nobeautify      noextended      nolist          open            scroll=11       taglength=0     wraplen=0
    cdpath=":"      filec=""        lock            optimize        nosearchincr    tags="tags"     wrapmargin=0
    cedit=""        flash           magic           path=""         nosecure        noterse         wrapscan
    columns=117     hardtabs=0      matchtime=7     print=""        shiftwidth=8    notildeop       nowriteany
    nocombined      noiclower       mesg            prompt          noshowmatch     timeout
    directory="/tmp"
    fileencoding="UTF-8"
    inputencoding="UTF-8"
    paragraphs="IPLPPPQPP LIpplpipbp"
    recdir="/var/tmp/vi.recover"
    sections="NHSHH HUnhsh"
    shell="/bin/zsh"
    shellmeta="~{[*?$`'"\"
    term="screen-256color"
OpenVi [7.0.13-dev (OpenVi) 02/20/2022]:

    noaltwerase     nocomment       noiclower       mesg            report=5        taglength=0     nowindowname
    noautoindent    noedcompatible  noignorecase    noprint=""      noruler         tags="tags"     wraplen=0
    autoprint       escapetime=2    noimctrl        nonumber        scroll=11       noterse         wrapmargin=0
    noautowrite     noerrorbells    keytime=6       nooctal         nosearchincr    notildeop       wrapscan
    backup=""       noexpandtab     noleftright     open            nosecure        timeout         nowriteany
    nobeautify      noexrc          lines=23        path=""         shiftwidth=8    nottywerase
    nobserase       noextended      nolist          print=""        noshowmatch     noverbose
    cdpath=":"      filec=" "       lock            prompt          noshowmode      novisibletab
    cedit=""        noflash         magic           noreadonly      sidescroll=16   warn
    columns=117     hardtabs=0      matchtime=7     remap           tabstop=8       window=22
    imkey="/?aioAIO"
    paragraphs="IPLPPPQPP LIpplpipbpBlBdPpLpIt"
    recdir="/var/tmp/vi.recover"
    sections="NHSHH HUnhshShSs"
    shell="/bin/zsh"
    shellmeta="~{[*?$`'"\"
    term="screen-256color"
OpenBSD vi [7.0-current]:

    noaltwerase     escapetime=1    noleftright     path=""         noshowmatch     warn
    noautoindent    noerrorbells    lines=36        print=""        noshowmode      window=35
    autoprint       noexpandtab     nolist          prompt          sidescroll=16   nowindowname
    noautowrite     noexrc          lock            noreadonly      tabstop=8       wraplen=0
    backup=""       noextended      magic           remap           taglength=0     wrapmargin=0
    nobeautify      filec=" "       matchtime=7     report=5        tags="tags"     wrapscan
    cdpath=":"      noflash         mesg            noruler         noterse         nowriteany
    cedit=""        hardtabs=0      noprint=""      scroll=17       notildeop
    columns=108     noiclower       nonumber        nosearchincr    timeout
    nocomment       noignorecase    nooctal         nosecure        nottywerase
    noedcompatible  keytime=6       open            shiftwidth=8    noverbose
    paragraphs="IPLPPPQPP LIpplpipbpBlBdPpLpIt"
    recdir="/tmp/vi.recover"
    sections="NHSHH HUnhshShSs"
    shell="/usr/local/bin/zsh"
    shellmeta="~{[\*?$`'"\"
    term="screen-256color"
Traditional vi [n-t-roff Heirloom vi (01/14/2017)]:

    noautoindent            nomodelines                     noshowmode
    autoprint               nonumber                        noslowopen
    noautowrite             open                            nosourceany
    nobeautify              nooptimize                      tabstop=8
    directory=/var/tmp      paragraphs=IPLPPPQPP LIpplpipbp taglength=0
    noedcompatible          prompt                          tags=tags /usr/lib/tags
    noerrorbells            noreadonly                      term=screen-256color
    noexrc                  redraw                          noterse
    flash                   remap                           timeout
    hardtabs=8              report=5                        ttytype=screen-256color
    noignorecase            scroll=17                       warn
    nolisp                  sections=NHSHH HUnhsh           window=35
    nolist                  shell=/usr/bin/zsh              wrapscan
    magic                   shiftwidth=8                    wrapmargin=0
    mesg                    noshowmatch                     nowriteany


Of particular note, the lack of `expandtab` in Nvi and Traditional vi may be more of a showstopper than lack of multibyte glyph rendering for many.


>Why would somebody want to use this over nvi

This basically is nvi, unless I'm very wrong.


It's nvi plus some OpenBSD patches. Nvi it self has a series of different patches. The question remains valid. Why would you specifically want the nvi from OpenBSD, when you already have nvi?

The assumption has to be that OpenBSD added something to their version of nvi, which would "justify" porting it back to non-OpenBSD systems. What those feature are I don't know. It might just be a fun exercise adding the portability back.


I have some comments here that address this, but, there are in fact many significant differences.

The OpenBSD version forked at Nvi 1.79 around 1996-1997 and has been developed in the OpenBSD base system for 25 years now, and has diverged greatly from Nvi. Nvi2 has also diverged significantly from both "upstream" Nvi and OpenBSD vi.

The OpenBSD release has significantly trimmed features and maintains a different structure than the others as the philosophy completely different. There is no Perl / Tcl / pluggable scripting engine support or alternate graphical user interfaces or similar.

There are significant differences in the lower level code for signal handling, options, etc.

While the core functionality of these editors are all largely the same, and they all share common heritage from Bostic's Nvi, there are trivial and non-trivial differences between all of these editors that are almost too numerous to summarize.

Reviewing the ChangeLog (https://raw.githubusercontent.com/johnsonjh/OpenVi/master/Ch...) since Nvi 1.79 to present should give you an idea of what's going on with this particular version.


Don't confuse OpenVi/OpenBSD-vi, nvi1, and nvi2. These are all different programs that share the same heritage.

OpenVi is derived from OpenBSD vi, which derives from nvi version 1.79, released in 1996. There has been 25+ years of independent development as part of the OpenBSD base system and has diverged greatly in that time, with the development going in a different direction.

Nvi1, currently on version 1.8x, is maintained at https://repo.or.cz/nvi.git - I believe the latest version of this editor does have multibyte support, but this is not the OpenVi/OpenBSD version of the editor.

Nvi2 shares heritage as well but also, quite far removed from the original code, is actively maintained at https://github.com/lichray/nvi2 and also includes multibyte support.

(IIRC) the multibyte support in both Nvi1 and Nvi2 derives from nvi-m17n, developed as part of the KAME project by the late itojun - http://www.itojun.org/itojun.html ... the last update to nvi-m17n was about 3 years ago, and is available at https://cgit.freebsd.org/ports/tree/editors/nvi-m17n/files

Currently, optimizing for size using link-time garbage collection with GCC 11.2 on an x86_64 glibc Linux system gives a good idea of the changes over time and the different direction these editors have taken. OpenVi is also simplified in structure and does not have the three levels of abstraction of Nvi 1.8x - there is no library interface layer.

For OpenVi, the compiled binary is 280K, and for Nvi1 (nvi-1.81.6-45-g864873d3) the compiled binary is 528K (36K for vi, 528K for libvi).

OpenVi has a single configuration standard with no dependencies beyond curses.

Nvi1 has many options beyond trace/debug ("widechar" "gtk" "motif" "threads" "perl" "tcl" "db3/4" "internal-re") - so at least 255 different build variations are possible.

(I've not yet built Nvi2 myself on Linux so I can't provide an really fair comparison yet, but I will, and I'll summarize the data in an FAQ section of the README)

Nvi1 (https://repo.or.cz/nvi.git) looks like:

    36K    vi
    24K    vi-ipc
    108K   vi-motif
    492K   libvi.so.0.0.0
    660K   total
OpenVi does not - it's a single monolithic binary:

    280K   bin/vi
(Note that I was using the defaults here, I'm sure that it's possible to trim down Nvi 1.8x further, but I'm comparing the default compilations, optimized for size (GCC, -Os, -fdata-sections, -ffunction-sections, link-time GC enabled), but Nvi 1.8x is a much more complicated program, and has a different feature set, and different supported options.

But, these are all different editors at this point. A lot happens in 25 years.


Cleanly doing UTF-8 support (the "right" way) is planned but is certainly non-trivial ... for example, see:

https://www.openbsd.org/papers/eurobsdcon2016-utf8.pdf and http://www.usenix.org/events/usenix99/full_papers/hagino/hag...

Nvi2 (and Nvi1) are excellent editors, but I wouldn't want to copy the Nvi2 implementation directly. This has been talked about elsewhere*

* https://misc.openbsd.narkive.com/9NHoQv8L/nvi-and-unicode#po...


Isn’t vi already in POSIX? What’s the advantage over what OpenBSD should include already?


It's the other way around. It's the OpenBSD vi (which is a fork of nvi) ported back to other Unix(-like) systems.

Still it's unclear why.


I have updated the documentation/README to provide background and rationale, and elaborated a bit on other comments.

OpenBSD's vi (and OpenVi) differ distinctly from both Nvi (https://repo.or.cz/nvi.git) and Nvi2 (https://github.com/lichray/nvi2) in terms of features and support, having diverged 25 years previously, where the OpenBSD/OpenVi branch has embraced minimalism and simplicity.

For a quick and non-scientific comparison, C source lines of code (as counted by tokei) for the various distributions of the Nvi-derived editors:

Nvi - 62,315 SLOC

Nvi2 - 32,408 SLOC

OpenVi - 40,065 SLOC

And looking ONLY at the core editor functionality and bundled regular expression engines:

Nvi - 35,874 SLOC

Nvi2 - 32,019 SLOC

OpenVi - 31,678 SLOC


nvi is very fast.


I've found vile a good option as I'm addicted to syntax highlighting: similar speed to nvi, much faster than vis and vim.

https://invisible-island.net/vile/


I will confirm that Vile is an excellent editor. I don't know if I'd consider it a vi-clone, because the vi-ness is kind of skin-deep, but it's performant and works well.

(In school, early 90's, there was a large vile following on VMS, which is where I mostly used it. I don't recall why it was preferred to Vim on VMS, however. Perhaps we didn't have Vim easily available or installed. But I digress.)



Agreed; it's been my vi of choice for many, many years.


Its really pity that you can not disable wrapping in nvi(1) ...


:set [no]leftright


Thank You!

I have searched for this some time ago but all 'hints' guided me towards vim(1) :set nowrap option.

I checked now the vi(1) [nvi] man page on FreeBSD and it indeed has leftright option.

    % man vi | grep -A 1 leftright
        leftright [off]
            vi only.  Do left-right scrolling.
But I never interpreted that as 'nowrap' equivalent.

Thanks again and have a great life.


Cheers. Edit in good health.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: