{"id":15287028,"url":"https://github.com/kristofer/kg","last_synced_at":"2025-05-07T04:25:02.047Z","repository":{"id":45336380,"uuid":"159192717","full_name":"kristofer/kg","owner":"kristofer","description":"kg is a very small Emacs clone in Go (golang.org)","archived":false,"fork":false,"pushed_at":"2021-12-21T16:20:06.000Z","size":8177,"stargazers_count":16,"open_issues_count":13,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-19T18:31:03.595Z","etag":null,"topics":["emacs","gap-buffer","golang","microemacs","small"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kristofer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-26T15:39:37.000Z","updated_at":"2024-02-29T23:32:17.000Z","dependencies_parsed_at":"2022-08-25T11:00:35.613Z","dependency_job_id":null,"html_url":"https://github.com/kristofer/kg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kristofer%2Fkg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kristofer%2Fkg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kristofer%2Fkg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kristofer%2Fkg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kristofer","download_url":"https://codeload.github.com/kristofer/kg/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252811651,"owners_count":21807987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","gap-buffer","golang","microemacs","small"],"created_at":"2024-09-30T15:23:56.077Z","updated_at":"2025-05-07T04:25:02.011Z","avatar_url":"https://github.com/kristofer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kg Emacs\n\nA small functional Emacs written in Go changed in time for the vault  \n\nby Kristofer\n\nkg Emacs is inspired by Atto Emacs (by Hugh Barney), MicroEmacs, Nano, Pico and his earlier project known as Perfect Emacs [1]. Also by JOE, uEmacs, MicroEmacs, mg, zile and of course, GNU Emacs. I learnt Emacs on a Sun 2/120 a long time ago in a galaxy far, far, away.\n\n\n\u003e A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.\n\u003e -- \u003ccite\u003eAntoine de Saint-Exupery\u003c/cite\u003e\n\n\u003e If you want to build a ship, don't drum up people to collect wood and don't assign them tasks and work, but rather teach them to long for the endless immensity of the sea.\n\u003e -- \u003ccite\u003eAntoine de Saint-Exupery\u003c/cite\u003e\n\n## Goals of kg Emacs\n\n* Mine own, finally, in Go.\n* uses an array of Rune to handle Unicode codepoints.\n* no damn Overwrite mode. Too bad.\n* pure Go implementation\n* removal of the C-based hilite stuff\n* add go routines for some operations.\n* ...\n* Be easy to understand without extensive study (to encourage further experimentation).\n\nUsing Atto as the lowest functional Emacs, Hugh had to consider the essential feature set that makes Emacs, 'Emacs'.  From his Readme: _I have defined this point as a basic Emacs command set and key bindings; the ability to edit multiple files (buffers), and switch between them; edit the buffers in mutliple windows, cut, copy and paste; forward and reverse searching, a replace function, basic syntax hilighting and UTF8 support. The proviso being that all this will fit in less than 2000 lines of C._\n\n\n## Derivation\n\nkg is based on the design of _Atto Emacs which is based on the public domain code of Anthony Howe's editor (commonly known as Anthony's Editor or AE, [2]).  Rather than representing a file as a linked list of lines, the AE Editor uses the concept of a Buffer-Gap [4,5,6].  A Buffer-Gap editor stores the file in a single piece of contiguous memory with some extra unused space known as the buffer gap.  On character insertion and deletion the gap is first moved to the current point.  A character deletion then extends the gap by moving the gap pointer back by 1 OR the gap is reduced by 1 when a character is inserted.  The Buffer-Gap technique is elegant and significantly reduces the amount of code required to load a file, modify it and redraw the display.  The proof of this is seen when you consider that Atto supports almost the same command set that Pico supports,  but Pico requires almost 17 times the amount of code._\n\n## Comparisons with Other Emacs Implementations\n\n    Editor         Binary   BinSize     KLOC  Files\n\n    atto           atto       33002     1.9k     10\n    pEmacs         pe         59465     5.7K     16\n    Esatz-Emacs    ee         59050     5.7K     14\n    GNOME          GNOME      55922     9.8k     13\n    Zile           zile      257360    11.7k     48\n    Mg             mg        585313    16.5K     50\n    uEmacs/Pk      em        147546    17.5K     34\n    Pico           pico      438534    24.0k     29\n    Nano           nano      192008    24.8K     17\n    jove           jove      248824    34.7k     94\n    Qemacs         qe        379968    36.9k     59\n    ue3.10         uemacs    171664    52.4K     16\n    GNUEmacs       emacs   14632920   358.0k    186\n\n    kg             kg       2719864     1.9k      8\n\n* _Due to Go's single-binary, 2.7mb is pretty normal for a go binary size. It uses NO shared libraries, etc. The code itself though, is more like 720496, since that's (kg - HelloWorld) (2719864 - 1999368)._\n* _While I did not aim for less than 2000 LOC, surprisingly, it is. And no, I did not count test LOC._ \n\n## kg Key Bindings\n\n    C-A   begining-of-line\n    C-B   backward-character\n    C-D   delete-char\n    C-E   end-of-line\n    C-F   forward Character\n    C-G\t  Abort (at prompts)\n    C-H   backspace\n    C-I   handle-tab\n    C-J   newline\n    C-K   kill-to-eol\n    C-L   refresh display\n    C-M   Carrage Return\n    C-N   next line\n    C-P   previous line\n    C-R   search-backwards\n    C-S\t  search-forwards\n    C-U   Undo\n    C-V   Page Down\n    C-W   Kill Region (Cut)\n    C-X   CTRL-X command prefix\n    C-Y   Yank (Paste)\n\n    M-\u003c   Start of file\n    M-\u003e   End of file\n    M-v   Page Up\n    M-f   Forward Word\n    M-b   Backwards Word\n    M-g   goto-line\n    M-r   Search and Replace\n    M-w   copy-region\n\n    C-\u003cspacebar\u003e Set mark at current position.\n\n    ^X^C  Exit. Any unsaved files will require confirmation.\n    ^X^F  Find file; read into a new buffer created from filename.\n    ^X^S  Save current buffer to disk, using the buffer's filename as the name of\n    ^X^W  Write current buffer to disk. Type in a new filename at the prompt to\n    ^Xi   Insert file at point\n    ^X=   Show Character at position\n    ^X^N  next-buffer\n    ^Xn   next-buffer\n    ^Xk   kill-buffer\n    ^X1   delete-other-windows\n    ^X2   split-window\n    ^Xo   other-window\n\n    Home  Beginning-of-line\n    End   End-of-line\n    Del   Delete character under cursor\n    Ins   Toggle Overwrite Mode\n    Left  Move left\n    Right Move point right\n    Up    Move to the previous line\n    Down  Move to the next line\n    Backspace delete caharacter on the left\n    Ctrl+Up      beginning of file\n    Ctrl+Down    end of file\n    Ctrk+Left    Page Down\n    Ctrl+Right   Page Up\n\n### Copying and moving\n\n    C-\u003cspacebar\u003e Set mark at current position\n    ^W   Delete region\n    ^Y   Yank back kill buffer at cursor\n    M-w  Copy Region\n\nA region is defined as the area between this mark and the current cursor position. The kill buffer is the text which has been most recently deleted or copied.\n\nGenerally, the procedure for copying or moving text is:\n1. Mark out region using M-\u003cspacebar\u003e at the beginning and move the cursor to the end.\n2. Delete it (with ^W) or copy it (with M-W) into the kill buffer.\n3. Move the cursor to the desired location and yank it back (with ^Y).\n\n### Searching\n\n    C-S or C-R enters the search prompt, where you type the search string\n    BACKSPACE - will reduce the search string, any other character will extend it\n    C-S at the search prompt will search forward, will wrap at end of the buffer\n    C-R at the search prompt will search backwards, will wrap at start of the buffer\n    ESC will escape from the search prompt and return to the point of the match\n    C-G abort the search and return to point before the search started\n\n## Building on Linux/MacOS\n\nWhen building on Linux/MacOS you will need to install Go v1.11 or greater.\nYou will also need the `github.com/nsf/termbox-go`\n\n    $ go get github.com/kristofer/kg\n    $ go get github.com/nsf/termbox-go\n\ncd to the kg source directory...\n\n    $ cd cmd\n    $ go build -o kg main.go\n\nand then move into your binary PATH\n\n## Future Enhancements\n\nMaybe a piece-table or piece-chain implementation? Maybe a different key mapping set to make it more mac-like.\n\n## Multiple Windows or Not?\n\nKg supports multiple windows.\n\n## Known Issues\n\n* Goto-line will fail to go to the very last line.  This is a special case that could easily be fixed.\n\n## Copying\n\n  Kg code is released to the public domain.\n  kryounger AT gmail.com - 2018\n\n## Acknowledgements\n\n    Hugh Barney for Atto (and his other work).\n    Ed Davies for bringing Athony's Editor to my attention\n    Anthony Howe for his original codebase\n    Matt Fielding (Magnetic Realms) for providing fixes for multi-byte / wide characters, delete, backspace and cursor position\n    The Infinnovation team for bug fixes to complete.c\n    James Gosling for telling me long ago that to build an Emacs just something you did.\n\n## References\n\n    [1] Perfect Emacs - https://github.com/hughbarney/pEmacs\n    [2] Anthony's Editor - https://github.com/hughbarney/Anthony-s-Editor\n    [3] MG - https://github.com/rzalamena/mg\n    [4] Jonathan Payne, Buffer-Gap: http://ned.rubyforge.org/doc/buffer-gap.txt\n    [5] Anthony Howe,  http://ned.rubyforge.org/doc/editor-101.txt\n    [6] Hugh Barney, https://github.com/hughbarney/atto\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkristofer%2Fkg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkristofer%2Fkg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkristofer%2Fkg/lists"}