-
Z: "Reverse-polish" editor-function execution mode wherein the user creates an editor-function argument ("xARG") using various selection or data-entry modes or argtypes, prior to invoking the editor-function; the editor-function’s execution behavior adapts to the actual argtype it receives.
-
This allows each editor-function (one bound to each key) to potentially perform related but different operations depending on argument-type, minimizing consumption of the "keyboard namespace". EX:
setfile
(described below).
-
-
Z: Can switch between line and box (column) selection mode simply by varying the shape of the selection.
-
M: No installation: copy and run, delete when done. Run from removable storage.
-
M: Easily accessible history of recent files visited, strings searched for and replaced, stored in files in user’s homedir.
-
M: Edit undo/redo limited only by available memory (effectively infinite).
-
M: Default automatic backup of previous versions of all files edited. Every time a dirty file is saved to disk, the previous incarnation of the file (being overwritten) is moved to
.kbackup\filename.yyyymmdd_hhmmss
where.kbackup
is a directory created by K in the directory containingfilename
, andyyyymmdd_hhmmss
is the mtime of the instancefilename
being saved. This feature was a lifesaver in the "dark decades" preceding the availability of free, multi-platform DVCS (git, Mercurial), and is much less important when DVCS is used; use DVCS! -
K: Powerful file/source-code navigation
-
K comprehends Universal Ctags tagfile format, and provides a hyperlinking experience navigating amongst tagged items in your programming project.
-
K can perform multi-file-greps/-replaces targeting sets of files enumerated in any editor buffer.
-
K supports powerful recursive (tree) directory scanning with output to an editor buffer, so, when combined with file-filtering editor-functions such as grep, strip, etc. it’s easy to quickly construct a buffer containing the names of all of the files of interest to you, and have the multi-file-aware editor-functions use this buffer as its source of names of files to examine. And since this is based on current filesystem content, it’s more likely to be complete and correct than a "project file" which must be independently maintained (and thus can easily fall out of sync with workspace reality).
-
-
K: highlighting
-
comments
-
literal strings/characters
-
conditional regions: C/C++ preprocessor, GNU make
K itself is released under the GPLv3 license. See file COPYING.
The K source code distro contains, and K incorporates, by building and static linking, modified versions of the following open source libraries:
-
Lua 5.1 from 2005, licensed under the MIT License
-
James S. Plank’s Red-Black Tree C library from 2000 (substantially modified), licensed under LGPL
-
K is a Win32 Console or Linux ncurses app with no mouse support (aside from (trackpad gestures which mimic) "scroll wheel" behaviors). The UI is fairly minimal: there are no "pulldown menus" though primitive "pop-up menus" are used on a per-editor-function basis.
-
Update 2016/09: the "Windows 10 Anniversary Update" broke the "scroll wheel" functionality, apparently by changing the default value of the console properties "Use legacy console (requires relaunch)" setting from disabled/unchecked (K scroll-wheel feature works) to enabled/checked (K scroll-wheel feature disabled/broken).
-
to access this setting (which may be host-global!): right click on the icon in the console window title bar and select Properties, then the Options tab
-
"relaunch" seems to mean closing and reopening the console window (not rebooting the OS).
-
-
-
K has no "virtual memory" mechanism (as M did); files are loaded in toto into RAM; K WILL CRASH if you attempt to open a file that is larger than the biggest malloc’able block available to the K process (now that all OS’s default-deploy their x64 variant (and K is buildable as an x64 app) this is practically never a concern).
-
K operates on ASCII files; it has no support for Unicode/UTF-8/MBCS/etc. content (it’s a text-editor, not a word processor). I am increasingly entertaining the possibility of adding UTF-8 support.
-
GCC
>= 11 -
Boost
>= 1.54 (2016/05: some major Linux distros do not meet this requirement by default; see below); used only for-
boost::filesystem
: a small subset only
-
-
PCRE2
Perl Compatible Regular Expressions are used in search/replace editor-functions and occasionally internally. -
Universal Ctags
is invoked to rebuild the "tags database" at the close of each successful build of K. -
Linux-only:
ncurses
,pthread
libraries -
Windows-only:
7zip.exe
is used to create release files when building themake rls
target (in the same circumstance, the Linux build creates.tgz
files using standard utilities).
-
The nuwen.net distribution of MinGW provides all of the Windows External Build Dependencies except
ctags.exe
. The MinGW downloads are self-extracting-GUI 7zip archives which contain bat files (I useset_distro_paths.bat
below) which add the appropriate environment variable values sufficient to use gcc from the cmdline. I use the following 1-line bat files (stored outside the K repo because their content is dependent on where the MinGW packages are extracted) to setup MinGW for building K (or any other C/C++ project):-
mingw.bat
(x64):c:\_tools\mingw\64\mingw\set_distro_paths.bat
-
-
ctags.exe
from Universal Ctags must be deployed inPATH
; Chocolatey closely tracks ctags-win32 releases). -
FYI: MinGW gcc non-optionally dyn-links to MSVCRT.DLL which it assumes is already present on any Windows PC (this seems akin to Linux’s glibc).
-
after cloning this repo, run
sudo ./install_build_tools_ubuntu.sh
to install the necessary packages. -
ensure that GCC >= 11 is available to provide for C++20 support; this requires additional installation steps on Ubuntu 20.04.
make
targets:
-
all
: (default) build everything; the build is parallel-make-safe -
clean
: clean K-core C++ build outputs only -
zap
: clean K-core C++ build outputs plus all Lua related
To perform a clean-slate (re)build:
make zap make -j
Use of release files is optional: intended to be used K needs to be run on a host lacking build tools or access to e.g. github.
A release file is a Windows=7z/Linux=tgz archive containing the minimum fileset needed to use the editor. On Windows two (2) variants of the release file are created by make rls
: k_rls.7z
and k_rls.exe
(a self-extracting-console archive).
Use: decompress the release file in an empty directory and run k.exe
(Linux: k
). K was designed to be "copy and run" (a "release") anywhere. I have successfully run it from network/NFS shares and "thumb drives".
The default (Windows-originated) K key mappings make extensive use of ctrl+
and alt+
modulated function and keypad keys. Getting such key combinations to decode correctly on Linux/ncurses has been by far the most time-consuming and code-churning part of the port to Ubuntu Linux 14.04+ (see file conin_ncurses.md for the current state of this activity). The status quo:
-
Ubuntu 14.04+ Desktop
-
common: with
TERM=xterm
, after you disable various terminal-menu/-command key-modulation (e.g.alt+
) hooks, default terminfo for xterm correctly decodes a substantial proportion of the Windows-supported key combinations that K uses. -
Lubuntu/LXDE Desktop (
lxterminal
neex-terminal-emulator
) running as VirtualBox guest: mouse scroll wheel does work. -
I think I’ve exhausted the possibilities here
-
-
Windows openssh client (built into Git for Windows bash) to ubuntu 20.04+.
-
mostly works; exceptions:
ctrl+4
(exit)
-
-
Windows client running PuTTY 0.67 (released 2016-03-05) to Lubuntu 14.04+.
-
Be sure to use the most recent release of PuTTY.
-
To set PuTTY’s
-
keyboard setting: PuTTY
Menu
/Change Settings
/Terminal
/Keyboard
/the function keys and keypad
: <choose one radio-button> -
export
TERM
value: PuTTYMenu
/Change Settings
/Connection
/Data
/Terminal details
/terminal-type string
: <enter the desired TERM value here>-
this menu is only available if PuTTY is not connected to a remote server.
-
to support alternative
TERM
on Debian-based (i.e. *ubuntu) Linux, packagencurses-term
may need to be installed.
-
-
keypad cursor keys: PuTTY
Menu
/Change Settings
/Terminal
/Keyboard
/Application keypad settings:
/Initial state of cursor keys:
: <choose>Normal or Application -
keypad numeric keypad: PuTTY
Menu
/Change Settings
/Terminal
/Keyboard
/Application keypad settings:
/Initial state of numeric keypad:
: <choose>Normal or Application
-
-
Recommendation
-
export
TERM=putty
orTERM=putty-256color
withkeyboard setting
=Xterm R6
and keypad cursor keys=Application and keypad numeric keypad=Application.-
unfortunately only unmodulated function keys are correctly decoded;
shift+
,ctrl+
,shift+ctrl+
, andalt+
-modulation of function keys is ignored.
-
-
Runner-up: export
TERM=putty-sco
withkeyboard setting
=SCO
and keypad cursor keys=Normal and keypad numeric keypad=Normal.-
adds support for
shift+
,ctrl+
, andshift+ctrl+
, but NOTalt+
, modulated function keys. -
unfortunately the
center
(arg) key collides withPgDn
, otherwise this setup would be amazingly close to "complete".
-
-
-
emacswiki/emacs/PuTTY seems a good resource regarding PuTTY keyboard peculiarities.
-
-
tmux (1.8 - 2.0) (
TERM=screen
)-
most
ctrl+
andalt+
function and keypad modulations do not work. -
I’ve not begun investigating the possibilities here.
-
K persists information between sessions in state files written to directory (K defines $K_STATEDIR)
-
Windows:
%APPDATA%\k_edit\*
-
K ignores the Windows Registry.
-
-
Linux:
${XDG_CACHE_HOME:-$HOME/.cache}/k_edit/$(hostname)/
-
$(hostname)
is added since it is not unusual for a user’s $HOME to be located on a shared filesystem (e.g. NFS).
-
Information stored in state files includes:
-
recent files edited (including window/cursor position)
-
recent search-key and replace-string values
-
editor-function invocation-count accumulators (to enable fact-based key assignments)
K loads (compiles and executes into its primary Lua environment) a Lua source code file named ${K_SITE_DIR}/k_edit_site.lua
. The user may define ${K_SITE_DIR}
directly; if not, locations
-
${XDG_CONFIG_HOME}${XDG_CONFIG_HOME:+/k_edit"}
-
${USERPROFILE}${USERPROFILE:+/k_edit"}
are tried. See variable sled_childenv
in k.luaedit
for a list of the Lua-code functions which are exported from that file to (Lua code in) ${K_SITE_DIR}/k_edit_site.lua
. There is a sample k_edit_site.lua
file to be found nearby…
Logfile $K_LOGFNM, having session-unique name is stored in $K_LOGDIR which == "$K_STATEDIR/log", contains output from DBG macros which are sprinkled liberally throughout the source code. I am grateful for GCC’s printf format-string+argument-type checking which makes saves a lot of crash-debugging.
The newest nuwen.net (64-bit-only) MinGW distros include gdb
, and I have used it a couple of times. I generally only use a debugger to debug crashes, so if gdb
is unavailable (e.g. when nuwen.net MinGW distros omitted gdb
) I use DrMinGW as a minimalist way of obtaining a useful stack-trace when a crash occurs. In order to use either DrMinGW or gdb
it is necessary to build K w/full debug information; open GNUmakefile, search for "DBG_BUILD" for instructions on how to modify that file to build K most suitably for DrMinGW and gdb
.
-
to edit the previously edited file, run
k
-
to edit file
filename
, runk filename
-
run
k -h
to display full cmdline invocation help.
Legend: function
is the editor-function (embodied in the editor C++ source code as ARG::function()
) consuming the xARG.
The following outline describes all possible argtypes. Different ARG::function()
s (and therefore function
s) are specified as accepting particular argtypes (one or more), and the editor command invocation processing code (see buildexecute.cpp
) which calls ARG::function()
s will present the user’s arg value to the invoked ARG::function()
differently depending on these specifications. The association of function
name to ARG::function()
, its acceptable argtypes, and its help-text is sourced from cmdtbl.dat
which is preprocessed by cmdtbl.lua
into cmdtbl.h
at build time:
-
NOARG
: iffunction
is invoked with no arg prefix active. Only the cursor position is passed toARG::function()
. -
NULLARG
: iffunction
is invoked with anarg
prefix active but without intervening cursor movement or entry of literal characters. The actual argtype received byARG::function()
can vary, but always includes the cursor position and cArg, containing a count, the number of timesarg
was invoked prior:-
if the
function
s argtype is qualified byNULLEOW
orNULLEOL
(these can only apply toNULLARG
),ARG::function()
receives aTEXTARG
(string value) containing a string value read from buffer text content:-
NULLEOL
: from cursor to end of the line.-
EX:
arg setfile
opens (switches to) the file or URL beginning at the cursor position. Note thatARG::setfile()
contains code which further parses theTEXTARG
string value, truncating it at the first whitespace character or in other "magical" ways (seeFBOP::GetLineIsolateFilename()
).
-
-
NULLEOW
: from cursor and including all contiguous "word characters" through end of line (if the cursor is positioned in the middle of a word,NULLEOW
passes only the trailing substring of the word toARG::function()
).-
EX:
arg psearch
(likewisemsearch
,grep
,mfgrep
) searches for the word beginning at the cursor position.
-
-
-
-
TEXTARG
: when a string value is passed toARG::anyfunction()
. Generated when:-
a literal string arg entered:
arg
<user types characters to create the string text>anyfunction
-
arg
<horizontal cursor movement selecting a segment of the current line>anyfunction
. Internally, ifARG::anyfunction()
is specified as consumingTEXTARG
qualified withBOXSTR
, this selected text is transformed into aTEXTARG
(string value) which is passed toARG::anyfunction()
. TheTEXTARG
+BOXSTR
argtype + qualifier combination prevents single-lineBOXARG
s from being passed toARG::function()
(since these are transformed intoTEXTARG
). -
EX:
arg arg TEXTARG psearch
(likewisemsearch
,grep
,mfgrep
) searches for the regular expression TEXTARG.
-
-
BOXARG
: ifARG::anyfunction()
is specified as acceptingBOXARG
, the user (with the editor in boxmode, the default), to provide this arg type, invokesarg
, moves the cursor to a different column, either on the same (noteBOXSTR
caveat above) or a different line. A pair of Point coordinates (ulc, lrc) are passed toARG::function()
. -
LINEARG
: iffunction
is specified as acceptingLINEARG
the user (with the editor in boxmode, the default), the user invokesarg
, moves the cursor to a different line (while not moving the cursor to a different column) and invokesfunction
. A pair line numbers (yMin, yMax) are passed toARG::function()
. -
STREAMARG
: this argtype is seldom used and should be considered "under development."
K implements a large number of editor-functions, all of which the user can invoke by name using the execute
or selcmd
functions, or bind to any key. Every key has one function bound to it (and the user is completely free to change these bindings). The current key bindings can be viewed by executing function newhelp
bound to alt+h
. Functions can also be invoked by/within macros. Following are some of the most commonly used functions:
-
exit
(ctrl+4
,alt+F4
) exits the editor; the user is prompted to save any dirty files (one by one, or all remaining). -
undo
(ctrl+e
,alt+backspace
) undo the most recent editing operation. Repeatedly invokingundo
will successively undo all editing operations. -
redo
(ctrl+r
,ctrl+backspace
) redo the most recentlyundo
ne editing operation. Repeatedly invokingredo
will successively redo allundo
ne editing operations. -
arg
(center
: numeric keypad 5 key with numlock off (the state I always use)). Used to introduce arguments to other editor functions.arg
can be invoked multiple times prior to invokinganyfunction
; this may (depending on the editor function implementation) serve to modify the behavior ofanyfunction
(seesetfile
) -
alt+h
opens a buffer named <CMD-SWI-Keys> containing the runtime settings of the editor:-
switches with current values (and comments regarding effect).
-
functions with current key assignment (and comments regarding effect).
-
macros with current definition
-
-
setfile
(F2
) is very powerful:-
setfile
(w/oarg
) switches between two most recently viewed files/buffers. -
arg setfile
opens the "openable thing" (see below) whose name starts at the cursor. -
arg arg setfile
saves the current buffer (if dirty) to its corresponding disk file (if one exists) -
arg arg arg setfile
saves all dirty buffers to disk -
arg
"name of thing to open"setfile
opens the "thing"; an "openable thing" is either a filename, a pseudofile name (pseudofile is another name for temporary editor buffer; these typically have <names> containing characters which cannot legally be present in filenames), or a URL (latter is opened in dflt browser). -
arg
"text containing wildcard"setfile
will open a new "wildcard buffer" containing the names of all files matching the wildcard pattern. If the "text containing wildcard" ends with a '|' character, the wildcard expansion is recursive. EX:arg "*.cpp|" setfile
opens a new buffer containing the names of all the .cpp files found in the cwd and its child trees. -
arg arg
"name of file"setfile
saves the current buffer to the file named "name of file" (and gives the buffer this name henceforth). -
SPECIAL FEATURE: if the file to be opened is a URI, it is passed to the ShellExecute Win32API or Linux
xdg-open
program for opening in an external program (almost always: web browser).
-
-
ctrl+c
andctrl+v
xfr text between the Win32 (Windows) or X (Linux) Clipboard and the editor’s <clipboard> buffer in (hopefully) intuitive ways.-
The Linux implementation depends on
xclip
being installed;sudo apt-get install xclip
FTW!
-
-
ctrl+q
,alt+F2
opens visited-file history buffer; from most- to least-recently visited. Use cursor movement functions andarg setfile
to switch among them. -
num+` (copy selection into <clipboard>), `num-
(cut selection into <clipboard>) andins
(paste text from <clipboard>) keys on the numpad are used to move text between locations in buffers via <clipboard>. -
execute
(ctrl+x
):-
arg
"editor command string"execute
executes an editor function sequence (a.k.a. macro) string. -
arg arg
"OS shell command string"execute
executes "OS shell command string" in an operating system shell (Windows:CMD.exe
(a.k.a. DOS) shell; Linux: system() → bash) with stdout and stderr captured to an editor buffer. Note that in Windows, data files such as .pdf are "executable" (executing them opens their default app (e.g. PDF Reader GUI App).
-
-
tags
(alt+u
): looks up the identifier under the cursor (or arg-provided if any) in the current "tags database" and "hyperlinks" to it. If >1 definition is found, a menu of the available choices is offered.-
Aside: at the end of each successful build of K, to facilitate development of K,
ctags
is invoked to rebuild the "K tags database". -
the set of tags navigated to are added to a linklist which is traversed via
alt+left
andalt+right
. Locations hyperlinked from are also added to this list, allowing easy return. -
those functions appearing in the "Intrinsic Functions" section of <CMD-SWI-Keys> are methods of
ARG::
and can be tags-looked up (providing the best possible documentation to the user: the source code!).
-
-
PCRE2 Regular-expression (regex) search & replace: all search and replace functions, when prefixed with
arg arg
(2-arg), operate in regex mode. -
psearch
(F3
) /msearch
(F4
) (referred to asxsearch
in the following text) search forward / backward from the cursor position.-
alt+F3
opens a buffer containing previous search keys. -
xsearch
(w/o arg) searches for the next match of the current search key. -
arg xsearch
changes the current search key to the word in the buffer starting at the cursor and searches for the next match. -
arg
"searchkey"xsearch
changes the current search key to "searchkey" and searches for the next match. -
grep
(ctrl+F3
) creates a new buffer containing one line for each line matching the search key.gotofileline
(alt+g
) comprehends this file format, allowing you to hyperlink back to the match in the grepped file. -
mfgrep
(shift+F4
) creates a new buffer containing one line for each line, from a set of files, matching the search key. The "set of files" is initialized the first time the user invokes the tags function (there are other ways of course). -
In regex mode (when prefixed with
arg arg
) the search string is treated as a PCRE2 regular expression.
-
-
text-replace functions (note: these functions take three arguments: region to perform the replace, search-key, replace string, and the latter two arguments are required to be entered interactively by the user)
-
noarg
replace
(ctrl+L
) performs a unconditional (noninteractive) replace from the cursor position to the bottom of the buffer (or throughout a BOX/LINE/STREAMARG selection). -
noarg
qreplace
(ctrl+5
) performs a query-driven (i.e. interactive) replace from the cursor position to the bottom of the buffer (or throughout a BOX/LINE/STREAMARG selection). -
if a selection arg (line, box, stream) is prefixed to
replace
orqreplace
, only the content of that selection region is subject to the replace operation. -
mfreplace
(F11
) performs a query-driven (i.e. interactive) replace operation across multiple entire files. -
Regular-expression (PCRE2) replace is supported: in regex mode (when prefixed with
arg arg
) the search string is treated as a regular expression, and replace functions support the replacement string ; insertion of regex captures in the replacement string via\n
wheren
is the capture number. -
In regex mode (when prefixed with
arg arg
) the search string is treated as a PCRE2 regular expression, and the replacement string may reference regex captures in the replacement string via\n
wheren
is the (single-digit) capture number.
-
-
the cursor keys (alone and chorded with shift, ctrl and alt keys) should all work as expected, and serve to move the cursor (and extend the arg selection if one is active).
-
sort
(alt+9
) sort contiguous range of lines. Sort key is either BOXARG-selected substring of each line, or (if LINEARG) each entire line. Aftersort
is invoked, a series of menu prompts allow the user to choose ascending/descending, case (in)sensitive, keep/discard duplicates. -
websearch
(alt+6
): perform web search on string (opens in default browser)-
arg
"search string"websearch
: perform Google web search for "search string" -
arg arg
"search string"websearch
: display menu of all configured search engines (seeuser.lua
) and perform a web search for "search string" using the chosen search engine. -
The Linux implementation depends on
xdg-open
being installed; this seems to be part of any "Linux Desktop" OS install.
-
K has a rudimentary TUI "pop-up menu system" (written largely in Lua), and a number of editor functions which generate a list of choices to a menu, allowing the user to pick one. These functions are given short mnemonic names as the intended invocation is via arg
"fxnm" ctrl+x
-
mom
"menu of menus": menu of Lua-based editor menu functions -
mvf
"most visited files": menu of files sorted upon # of visits this session -
ff
"favorite files": menu of favorite files or websites (local or on www) -
sb
"system buffers" -
dp
"dirs of parent" all parent dirs -
dc
"dirs child" all child dirs -
gm
"grep-related commands" -
cur
"inert menu displaying dynamic macro definitions"
K is heavily based upon Microsoft’s M editor (a.k.a. "Microsoft Editor", released as M.EXE
for DOS, and MEP.EXE
for OS/2 and Windows NT), which was first released, and which I first started using, in 1988. According to Larry Osterman, a member of the 1990 Windows "NT OS/2" development team:
K development started (in spirit) in 1988 when I started writing (in C) loadable extension modules (the immediate forerunner of DLL’s) for the DOS version of the Microsoft M editor which was included with Microsoft (not Visual) C 5.1 for DOS & OS/2. In the next Microsoft C releases (6.0, 6.0a, 7.x) for DOS and OS/2, Microsoft bloated-up M into PWB (v1.0, 1.1, 2.0; see MSDN News article from 2001) then replaced it with the GUI "Visual Studio" IDE when Windows replaced DOS. I preferred the simpler yet tremendously powerful M, so starting in 1991 I wrote my own version, K. True to its DOS heritage, K is a Win32 Console App (with no mouse support aside from the scroll-wheel) because I have no interest in mice or GUIs. The current (since 2005) extension language is Lua 5.1. A full source distro of Lua, plus a few of its key modules, is included herein, and lua.exe
, built herein, is used in an early build step.
2014/10: an employment transition into an (effectively) Linux-only environment (willingly) forced me to port K to (x64) Linux; I had wanted to do this for years, but lacked the motivation: the prospect of working daily on a platform w/o K provided the needed motivation!
2014/11: I just discovered "Q" Text Editor, another (Win32+x64) re-implementation of the "M" Editor, written in FORTRAN using the QuickWin framework! As of 22.01 this has disappeared.
2017/09: See Musings
Until 2012/06, I compiled K using the free, copy and run (no installer needed) "Microsoft Visual C++ Toolkit 2003" containing MSVC++ 7.1 32-bit command line build tools (since withdrawn, replaced by Visual Studio Express Edition). During the time when I used these MS build tools, I used WinDbg to debug crashes.
I have no fondness for massive IDE’s (e.g. Visual Studio), nor for installers, so when I finally found a reliable way to obtain MinGW
and didn’t have to pay a significant code-size price for doing so (updt: K.exe’s disk footprint has grown significantly since then, mostly at the hands of GCC, though adopting std::string
and other STL bits has doubtless contributed greatly…), I was thrilled! Since then I have extensively modified the K code to take great
advantage of the major generic features of C++11 (and beyond); consequently K no longer compiles with MSVC++ 7.1.
Per Visual-Studio-Why-is-there-No-64-bit-Version the 32-bit version of K may be the better (more efficient) one (unless your use case includes editing > 2GB files), but since STL (creator of Nuwen MinGW distro) no longer provides 32-bit versions Nuwen MinGW, we will "follow suit." And of course, Linux in 2014+ is almost universally 64-bit (and 64-bit Linux K has no known anomalies).