{"id":17182859,"url":"https://github.com/rgburke/wed","last_synced_at":"2025-10-16T11:40:23.945Z","repository":{"id":144238626,"uuid":"51696246","full_name":"rgburke/wed","owner":"rgburke","description":"wed is a terminal text editor with key bindings commonly used in Windows based editors","archived":false,"fork":false,"pushed_at":"2018-02-10T22:18:20.000Z","size":1621,"stargazers_count":80,"open_issues_count":3,"forks_count":1,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-13T16:49:50.013Z","etag":null,"topics":["c","terminal-based","text-editor"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rgburke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-02-14T13:43:30.000Z","updated_at":"2025-04-06T18:17:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"f229f00a-2a6c-4387-a845-5280833a4c14","html_url":"https://github.com/rgburke/wed","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/rgburke/wed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rgburke%2Fwed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rgburke%2Fwed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rgburke%2Fwed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rgburke%2Fwed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rgburke","download_url":"https://codeload.github.com/rgburke/wed/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rgburke%2Fwed/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262632322,"owners_count":23340213,"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":["c","terminal-based","text-editor"],"created_at":"2024-10-15T00:38:22.563Z","updated_at":"2025-10-16T11:40:18.899Z","avatar_url":"https://github.com/rgburke.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wed - Windows terminal EDitor [![Build Status](https://travis-ci.org/rgburke/wed.svg?branch=master)](https://travis-ci.org/rgburke/wed)\n\n## Introduction\n\nWed is a terminal text editor with key bindings commonly used in Windows based\neditors. It aims for ease of use and to be a good starting editor for those new\nto a Unix terminal environment. Using standard Windows editor key bindings\n(e.g. `\u003cC-c\u003e` is copy, `\u003cC-s\u003e` is save) avoids the need to learn a new set\nof key bindings whilst also takes advantage of existing muscle memory. For the\nmost basic tasks reading wed documentation should be unnecessary.\n\n## Summary Of Core Features\n\n - Multiple files open in tabbed layout\n - Find \u0026 Replace (using PCRE and back references)\n - Text selection, copy/cut \u0026 paste\n - Syntax Highlighting\n - Themes to customise display colours\n - Supports Unix and Windows line endings\n - Unlimited undo \u0026 redo\n - Configurable using config files and runtime config commands\n - Gap buffer used as underlying storage structure\n - Mouse support\n - File Explorer\n\n## Demo (v0.1)\n\n![weddemo](doc/wed-demo-v0.1.gif)\n\n## Screenshot (v0.2)\n\n![wedscreenshot](doc/wed-screenshot-v0.2.png)\n\n## Quick Start\n\n### Linux Binary\n\nA prebuilt static Linux binary is available [here](https://github.com/rgburke/wed/releases/download/v0.2/wed-v0.2-linux-x86_64.tar.gz).\nTo install this binary run:\n\n```\ntar -xzf wed-v0.2-linux-x86_64.tar.gz\ncd wed-v0.2\nsudo make install\n```\n\nTo uninstall wed run `sudo make uninstall`.\n\n### Build From Source\n\nThe following libraries and tools are required to build wed:\n\n  - ncursesw\n  - PCRE\n  - Flex\n  - Bison\n  - GNU make\n  - realpath (for running tests)\n\nUsing Scintillua for syntax highlighting (enabled by default) also requires\nthe following libraries:\n\n  - Lua\n  - Lua LPeg\n\nUsing GNU Source-highlight for syntax highlighting (disabled by default) also\nrequires the following libraries:\n\n  - GNU Source-highlight\n  - Boost Regex\n\nTo build and install wed (defaults to `/usr/local/`) simply run:\n\n```\n./configure\nmake\nsudo make install\n```\n\nTo customise the build and installation edit `config.mk` (after running\n`./configure`) or pass in the relevant arguments to the `configure` script.\nFor example to build wed using clang with Scintillua syntax highlighting\ndisabled and then subsequently installed to `/opt` run:\n\n```\n./configure --disable-lua CC=clang PREFIX=/opt\nmake\nsudo make install\n```\n\nRun `./configure --help` to view all options.\n\nTo uninstall wed run `sudo make uninstall`.\n\nAs of 24/May/2016 wed builds successfully using the latest packages available\non the following systems:\n\n - Ubuntu 16.10 and 12.04.5 LTS\n - FreeBSD 10.3\n - Cygwin 2.5.1\n - Arch Linux\n - OSX\n\nWed should build and run on any \\*nix system, although changes may be required\nto `config.mk` in order to do so.\n\nWed is also available as a package on the following systems:\n\n - [Arch Linux](https://aur.archlinux.org/packages/wed-git)\n\nFor a quick overview of functionality read the [Key Bindings](#key-bindings)\nand [Config Variables](#config-variables) sections below.\n\n### Motivation\n\nThe inspiration for wed came from watching a colleague attempt to use vim.\nThis person was quite competent when using a Windows based editor or IDE and\nrarely needed to use the mouse. However they had only occasional need to use a\nterminal environment and thus had a rudimentary understanding of vim. Watching\nthem delete 5 lines by pressing d 10 times or moving to the end of a line by\nholding down the right directional key was enough to convince me they would be\nmuch better suited by another editor.\n\nHad this person been using a terminal editor with Windows like key bindings\nthey would have been quite proficient. It seemed clear then that an editor\nwith a display, feature set and key bindings similar to notepad++ for example,\nwould provide a way for many people unfamiliar with Unix editing tools to be\nproficient very quickly.\n\nThus the idea for wed was born.\n\n## Features\n\nThe main features of wed are detailed below.\n\n### Key Bindings\n\nThe current wed key bindings are listed below. Vim key notation is used i.e.\nthe Control, Meta and Shift modifiers are represented by C, M and S\nrespectively. For example `\u003cC-a\u003e` is Ctrl-a and `\u003cM-C-s\u003e` on a PC is\nAlt-Ctrl-s.\n\nAlthough efforts have been taken to match the key bindings commonly used in\nsoftware such as notepad++, it has not been possible in all cases.\nThe default GNOME Terminal that ships with Ubuntu 15.10 has been used for\ntesting which key bindings can be detected by wed. Consequently certain key\ncombinations such as `C-Tab` and `\u003cS-C-s\u003e` cannot be detected in this\nenvironment (and this is true for Xterm as well). Therefore in some cases the\nkey bindings wed uses differ from what would be expected.\n\nFurther to this some actions listed below can be achieved with multiple key\ncombinations for convenience and to avoid conflicting with other programs such\nas window managers.\n\n#### Movement\n\n```\n\u003cUp\u003e                        Move up a (screen) line\n\u003cDown\u003e                      Move down a (screen) line\n\u003cRight\u003e                     Move right one character\n\u003cLeft\u003e                      Move left one character\n\u003cHome\u003e                      Move to start of (screen) line\n\u003cM-Home\u003e                    Move to start of line\n\u003cEnd\u003e                       Move to end of (screen) line\n\u003cM-End\u003e                     Move to end of line\n\u003cC-Right\u003e                   Move to next word\n\u003cC-Left\u003e                    Move to previous word\n\u003cC-Up\u003e                      Move to previous paragraph\n\u003cC-Down\u003e                    Move to next paragraph\n\u003cPageUp\u003e                    Move up a page\n\u003cPageDown\u003e                  Move down a page\n\u003cC-Home\u003e                    Move to start of file\n\u003cC-End\u003e                     Move to end of file\n\u003cC-g\u003e                       Goto line\n\u003cC-b\u003e                       Move to matching bracket\n```\n\nAll movement keys apart from `\u003cC-g\u003e` and `\u003cC-b\u003e` can be combined with the\nshift key to select text.\n\nWhen line wrap is enabled (it is by default) a single line can wrap and take\nup several lines on the screen, which are called screen lines. Some \nkey bindings, those with \"(screen)\", operate on either lines or screen lines\ndepending on whether line wrap is disabled or enabled.\n\n#### Text Manipulation\n\n```\n\u003cTab\u003e                       Indent selected text\n\u003cS-Tab\u003e                     Unindent selected text\n\u003cC-Delete\u003e                  Delete next word\n\u003cM-Backspace\u003e               Delete previous word\n\u003cC-a\u003e                       Select all text\n\u003cC-c\u003e                       Copy selected text\n\u003cC-x\u003e                       Cut selected text\n\u003cC-v\u003e                       Paste text\n\u003cC-z\u003e                       Undo\n\u003cC-y\u003e                       Redo\n\u003cM-C-Up\u003e                    Move current line (or selected lines) up\n\u003cM-C-Down\u003e                  Move current line (or selected lines) down\n\u003cC-d\u003e                       Duplicate current line (or selected lines)\n\u003cC-j\u003e                       Join (selected) lines\n```\n\n#### General\n\n```\n\u003cC-s\u003e                       Save\n\u003cM-C-s\u003e                     Save as\n\u003cC-^\u003e                       Save all\n\u003cC-f\u003e                       Find\n\u003cC-h\u003e or \u003cC-r\u003e              Replace\n\u003cC-o\u003e                       Open file\n\u003cC-n\u003e                       New\n\u003cC-w\u003e                       Close file\n\u003cM-C-Right\u003e or \u003cM-Right\u003e    Next tab\n\u003cM-C-Left\u003e or \u003cM-Left\u003e      Previous tab\n\u003cC-_\u003e                       Change file\n\u003cC-t\u003e                       Switch to/from File Explorer\n\u003cC-e\u003e or \u003cC-\\\u003e              Run wed command\n\u003cM-z\u003e                       Suspend\n\u003cEscape\u003e or \u003cM-c\u003e           Exit\n```\n\n#### Prompt\n\nSome of the above key combinations such as \"Find\" or \"Open file\" will open a\nprompt for input. The following key bindings can be used in any prompt.\n\n```\n\u003cUp\u003e                        Previous prompt entry\n\u003cDown\u003e                      Subsequent prompt entry\n\u003cEscape\u003e                    Quit prompt\n```\n\nThe \"Open file\", \"Save\", \"Save as\" and \"Change file\" prompts all support\ncompletion. For example, in the \"Open file\" prompt entering /o and then\n`\u003cTab\u003e` will complete the prompt text to /opt/. If there are multiple matching\ndirectories/files they can be cycled through by entering `\u003cTab\u003e` again.\n\n```\n\u003cTab\u003e                       Complete entered text, then cycle through\n                            suggestions on subsequent presses.\n\u003cS-Tab\u003e                     Complete entered text, then cycle through\n                            suggestions in reverse on subsequent presses.\n```\n\nSearch options in wed can be configured in the find prompt by using the\nkey bindings below. The prompt text will list any options that deviate from\ntheir default values.\n\n```\n\u003cC-t\u003e                       Toggle search type between Text and Regex\n\u003cC-s\u003e                       Toggle case sensitivity\n\u003cC-d\u003e                       Toggle search direction\n```\n\n### Syntax Highlighting\n\nWed currently supports three types of syntax definitions:\n\n  - [Scintillua](http://foicica.com/scintillua/) - Lua LPeg lexers with\n    support for over 90 languages. Support for this syntax definition type is\n    enabled by default.\n  - [GNU Source-highlight](https://www.gnu.org/software/src-highlite/) - C++\n    library with support for over 80 languages. Support for this syntax\n    definition type is disabled by default, as it introduces a C++ dependency\n    and increases the memory footprint of wed. Support can be enabled by\n    running the configure script with the `--enable-gnu-source-highlight` flag\n    when building wed.\n  - Wed - Syntax definitions can be specified in wed config as examined in the\n    [Syntax Definition](#syntax-definition) section below. Support for this\n    syntax definition type is always available.\n\nOnly one syntax definition type can be active at a time. The default syntax\ndefinition type wed uses is determined by the `configure` script. The syntax\ndefinition type used can be changed at runtime using the `syntaxdeftype` config\nvariable.\n\n### Config\n\nVarious aspects of wed's behaviour and appearance can be customised through\nconfig specified in files or at runtime in the command prompt.\n\n#### Config Variables\n\nConfig variables are used to enable, disable and configure features in wed.\nDuring initialisation wed will attempt to load `/etc/wedrc` followed by \n`~/.wedrc`. Variables can be specified in either file with those in the former\napplying to all users and those in the latter to the user running wed.\n\nAny variables specified in these files act on a Global level. That is, they\nwill apply to all files opened by wed. File specific config can be applied\nat run time by opening the \"wed command\" prompt and entering in a variable\nassignment expression.\n\nVariable assignment is done using the syntax `variable=value;` with any\nwhite space ignored. The semicolon is optional if each assignment is done on a\nsingle separate line. All text after a `#` is ignored as a comment. The\ndifferent type's are:\n\n```\nType          | Pattern\n--------------|-------------------------\nbool          | true|false|1|0\nint           | (-|\\+)?\\d+\nstring        | \"(\\\\.|[^\\\\\"])+\"\nregex         | \\/(\\\\\\/|[^\\/])*\\/[imsx]*\nshell command | !.+$\n```\n\nIf a string contains no spaces, reserved characters or escaped characters\n(e.g. `\\n`), i.e. it matches the pattern `[^=;{}[:space:][:^print:]]+`, then\nit can be specified without quotes. For example:\n\n```\nfiletype = \"perl\"\n```\n\nand\n\n```\nfiletype = perl\n```\nare equivalent.\n\nThe table below lists the variables available in wed and their properties:\n\n```\nName                 | Short | Level       | Type   | Default Val | Description\n---------------------|-------|-------------|--------|-------------|---------------------------------------------------------\nlinewrap             | lw    | Global/File | bool   | true        | Enables/Disables line wrap\nlineno               | ln    | Global/File | bool   | true        | Enables/Disables line numbers\ntabwidth             | tw    | Global/File | int    | 8           | Sets tab character screen width (allowed 1 - 8)\nexpandtab            | et    | Global/File | bool   | false       | Enables/Disables expanding tab characters into spaces\nautoindent           | ai    | Global/File | bool   | true        | Enables/Disables autoindent\ncolorcolumn          | cc    | Global/File | int    | 0           | Sets column number to be highlighted\nbufferend            | be    | Global/File | string | \"~\"         | Text to display on each line in the region after the end of a buffer\nwedruntime           | wrt   | Global      | string | WEDRUNTIME  | Config definition location directory (set in config.mk)\nsyntax               | sy    | Global      | bool   | true        | Enables/Disables syntax highlighting\nsyntaxhorizon        | sh    | Global      | int    | 20          | Number of lines above the visible view to tokenize from\ntheme                | th    | Global      | string | \"default\"   | Set the active theme\nsyntaxdeftype        | sdt   | Global      | string | \"sl\"        | Syntax definition type to use (allowed \"sl\", \"sh\" or \"wed\")\nshdatadir            | shdd  | Global      | string | \"\"          | Directory path containing language definition files\nmouse                | mo    | Global      | bool   | true        | Enables/Disables mouse support\nfileexplorer         | fe    | Global      | bool   | true        | Enables/Disables file explorer visibility\nfileexplorerwidth    | few   | Global      | int    | 30          | Sets the file explorer width in columns\nfileexplorerposition | fep   | Global      | String | left        | Sets the file explorer position (allowed \"left\" or \"right\")\nfiletype             | ft    | File        | string | \"\"          | Sets the type of the current file (drives syntaxtype)\nsyntaxtype           | st    | File        | string | \"\"          | Set the syntax definition to use for highlighting\nfileformat           | ff    | File        | string | \"unix\"      | Sets line endings used by file (allowed \"dos\" or \"unix\")\n```\n\nAn example of a `~/.wedrc` could be:\n\n```\nwedruntime = /opt/share/wed    # wed shared files were moved to /opt\ntabwidth = 4                   # Tabs use 4 spaces when displayed\nexpandtab = true               # Tabs are expanded to spaces\nautoindent = true              # New lines are indented based off previous line\n```\n\nOr equivalently: `wrt=/opt/share/wed;tw=4;et=1;ai=1;`.\n\nTo enable tabs again in only the current buffer enter `\u003cC-\\\u003eet=0;\u003cEnter\u003e`\ni.e. open up the wed command prompt and set `expandtab=false;`. This is\npossible as `expandtab` applies at both the Global and File levels. Adding\n`ff=\"dos\";` to `~/.wedrc` for example would result in an error, as the\n`fileformat` variable is only available at the File level and not the Global\nlevel.\n\nGlobal only variables can be set in the wed command prompt (e.g. theme) as\nthere is no ambiguity regarding the level they apply at.\n\n#### Config Commands\n\nConfig commands also allow the behaviour of wed to be customised but with\ngreater flexibility than config variables. Commands are invoked using the\nsyntax:\n\n```\ncmd arg1 arg2 ...\n```\n\nThe table below lists the commands currently available in wed and their\nproperties:\n\n```\nCommand | Arguments                        | Description\n--------|--------------------------------- |----------------------------------------------------\necho    | variable                         | Displays arguments in the status bar\nmap     | string KEYS, string KEYS         | Maps a sequence of keys to another sequence of keys\nunmap   | string KEYS                      | Unmaps a previously created key mapping\nhelp    | none                             | Display basic help information\nfilter  | shell command CMD                | Filter buffer through shell command\nread    | shell command CMD or string FILE | Read command output or file content into buffer\nwrite   | shell command CMD or string FILE | Write buffer content to command or file\nexec    | shell command CMD                | Run shell command\n```\n\n##### echo\n\nThe `echo` command displays any arguments in the status bar. For example,\nrunning `echo \"Hello\"` will display the text `Hello` in the status bar. Config\nvariables can be interpolated by `echo`, so running `echo ln tw` will print\n`lineno=true. tabwidth=4`.\n\n##### map\n\nThe `map` command allows custom keybindings to be created. For example the\nfollowing command maps the key sequence `\u003cC-p\u003eh` to the key sequence `hello`:\n\n```\nmap \u003cC-p\u003eh hello\n```\n\nWhen the sequence `\u003cC-p\u003eh` is entered the text `hello` will be entered into\nthe buffer. A more advanced example is the following map:\n\n```\nmap \u003cC-p\u003ef \u003cC-f\u003e\u003cC-v\u003e\u003cEnter\u003e\u003cEscape\u003e\n```\n\nWhen the sequence `\u003cC-p\u003ef` is entered the text currently in the clipboard is\nsearched for and selected if found. Key mappings are recursive so the following\nmaps:\n\n```\nmap a b; map b c\n```\n\nwill cause a `c` to be entered whenever an `a` is pressed. The shortest key\nsequence is matched so a mapping will only work if a substring mapping doesn't\nalready exist:\n\n```\nmap \u003cC-p\u003ea \u003cHome\u003e\nMap \u003cC-p\u003eaa \u003cEnd\u003e  # This mapping will never run as \u003cC-p\u003ea will be matched first\n```\n\n##### unmap\n\nKey mappings created with the `map` can be undone using the `unmap` command:\n\n```\nmap x y  # Pressing x will enter a y\nunmap x  # Pressing x will enter an x again\n```\n\n##### help\n\nThe help command displays generated information on key bindings, commands and\nconfig variables.\n\n##### filter\n\nThe filter command allows the content of a buffer to be filtered through an\nexternal shell command. For example:\n\n```\nfilter !sort\n```\n\nwill filter the content of the buffer through the sort command, which will\nsort each line in the buffer. Another example is to delete all lines\ncontaining the word test:\n\n```\nfilter !sed /test/d\n```\n\nThe filter command makes the power of the Unix shell commands available in wed\nallowing many complex operations to be performed on a buffer.\n\n##### read\n\nFile content or command output can be read into the active buffer at the\ncurrent cursor position. For example, to read the file `buffer.c` into the\ncurrent buffer run:\n\n```\nread buffer.c\n```\n\nTo read command output into the buffer supply a shell command. For example,\nto read the current Unix timestamp into the buffer run:\n\n```\nread !date +%s\n```\n\n##### write\n\nThe write command allows buffer content to be written to the stdin of a shell\ncommand or to a file. For example to write the current buffer to a file named\n`test.txt` run:\n\n```\nwrite test.txt\n```\n\nTo determine the number of lines, words and characters in a buffer the `wc`\ncommand can be used:\n\n```\nwrite !wc\n```\n\n##### exec\n\nThe exec command allows a shell command to be executed with its output\ndisplayed in weds controlling shell. For example to run the `ls` command:\n\n```\nexec !ls\n```\n\nTo start a bash shell run:\n\n```\nexec !bash\n```\n\n#### Config Definitions\n\nConfig definitions allow objects to be defined which can be referenced by\nconfig variables. There are currently three types of objects which can be\ndefined: `filetype`, `syntax` and `theme` all of which are examined in more\ndetail in the following sections.\n\nThese definitions are stored in the `WEDRUNTIME` directory, but can be\noverwritten by placing config under `~/.wed/`.\n\n##### Filetype Definition\n\nA filetype defines a type of file and supplies a file path pattern that can\nbe used to identify files of its type. An example of a filetype is shown below:\n\n```\nfiletype {\n    name = \"c\";\n    display_name = \"C Source\";\n    file_pattern = /\\.(c|h)$/;\n}\n```\n\nWhere `name` is the unique id of the filetype, `display_name` is a human\nreadable filetype name and `file_pattern` is a regex which can be applied to\na file path (absolute path or file name depending if the file exists) to\ndetermine if a file matches this filetype.\n\nWhen wed load's a file, it loops through each filetype and applies the\n`file_pattern` regex to the files path allowing it to determine if the loaded\nfile matches any known filetype.\nFiletypes are used to attempt to determine the `syntaxtype` variable for a\nfile, as syntax definitions use the same id as their relevant filetype. They\nare loaded from the `WEDRUNTIME/filetypes.wed` directory on start up and can\noptionally be added to or overwritten by placing definitions in\n`~/.wed/filetypes.wed`.\n\nA future enhancement to the filetype definition will be to add a `file_content`\nregex variable. This pattern would be run on (limited) file content in order to\nestablish if a file matches the filetype, allowing files without extensions to\nbe identified e.g. any file beginning with `#!/bin/sh` is a Bourne shell\nscript.\n\n##### Syntax Definition\n\nA syntax definition defines a set of regex patterns and associated token types\nthat wed can use to highlight file content. A partial but sufficient example\nof a syntax definition is given below:\n\n```\nsyntax {\n    name = \"c\";\n\n    # Single line comments\n    pattern {\n        regex = /\\/\\/.*/;\n        type = \"comment\";\n    }\n\n    # Characters\n    pattern {\n        regex = /'(\\\\.|[^\\\\'\\r\\n])+'/;\n        type = \"constant\";\n    }\n\n    # Numbers\n    pattern {\n        regex = /\\b(\n                    [0-9]+(u|l)*?|\n                    0x[0-9a-f]+(u|l)*?|\n                    ([0-9]*\\.[0-9]+|[0-9]+\\.?[0-9]*)(e[-+]?[0-9]+)?(f|l)? \n                )\\b/ix;\n        type = \"constant\";\n    }\n\n    ...\n}\n```\n\nEach syntax definition supplies a `name` declaration which should match any\nassociated filetype e.g. the C filetype and syntax definitions both have\n`name = \"c\";`. A set of `pattern` blocks then follow each of which provides\na `regex` variable whose regex matches the relevant tokens in the file content,\nand a `type` variable which specifies the token type from one of the following\nvalues:\n\n```\nToken type     | Example\n---------------|-------------------------------------------\nnormal         | Normal text that doesn't match any token\ncomment        | /* */ or // in the C family\nconstant       | String, character, number...\nspecial        | C Preprocessor\nidentifier     | Variable and function names\nstatement      | Keywords - if, else, while, for etc...\ntype           | int, char, bool...\nerror          | Invalid syntax e.g. missing matching brace\ntodo           | TODO messages\n```\n\nEach syntax definition is placed in it's own file using the format `$name.wed`\ne.g. `c.wed` or `java.wed`. These definitions are located in the\n`WEDRUNTIME/syntax` directory and can be added to or overridden by placing\ndefinitions in the `~/.wed/syntax` directory.\nGiving each syntax definition a name and file name matching that of an\nassociated filetype allows wed to dynamically load syntax definitions based\non the filetype of a file. However it is still possible to directly set\nthe syntax definition for a file to use with the `syntaxtype` variable.\n\n##### Theme Definition\n\nA theme definition specifies a colour scheme by providing colouring config\nfor each of the various visual components of wed. A snippet of a theme\ndefinition is shown below:\n\n```\ntheme {\n    name = \"minimalred\";\n\n    group {\n        name = \"lineno\";\n        fgcolor = \"red\";\n        bgcolor = \"none\";\n    }\n\n    group {\n        name = \"buffertabbar\";\n        fgcolor = \"red\";\n        bgcolor = \"none\";\n    }\n\n    ...\n}\n```\n\nEach theme definition supplies a `name` which identifies the theme and is used\nby the `theme` variable to set the active theme e.g. `theme=\"minimalred\";`. A\nset of `group` blocks are defined each of which provides colouring config for a\nscreen component or token. Each `group` block provides a `name` which specifies\nthe screen component or token this `group` applies to. The `fgcolor` and\n`bgcolor` variables specify the colours that should be applied to this `group`.\nFor example, this `group` sets the line number text in wed to display in red\nwith a transparent background:\n\n```\ngroup {\n    name = \"lineno\";\n    fgcolor = \"red\";\n    bgcolor = \"none\";\n}\n```\n\nA list of the different screen components and tokens that can be specified by\na group block is provided below:\n\n```\nTokens (same descriptions from above apply)\n-------------------------------------------\nnormal\ncomment\nconstant\nspecial\nidentifier\nstatement\ntype\nerror\ntodo\n\nScreen Component           | Description\n---------------------------|--------------------------------------------------------\nlineno                     | Line numbers that appear on the left side of the screen\nbuffertabbar               | Tab bar at the top of the screen that lists buffers\nactivebuffertabbar         | Active buffer in the tab bar\nstatusbar                  | Bar at the bottom of the screen showing position info\nerrormessage               | Error messages that display on error\nbufferend                  | The strings that appear on each line below the end of a buffer\ncolorcolumn                | The column which is highlighted\nsearchmatch                | Text that matches the current search term\nprimarysearchmatch         | The currently selected search match\nfileexplorertitle          | The current working directory\nfileexplorerfileentry      | A file entry in the file explorer\nfileexplorerdirectoryentry | A directory entry in the file explorer\n```\n\nThe colors available to `fgcolor` and `bgcolor` in wed are:\n\n```\nnone\nblack\nred\ngreen\nyellow\nblue\nmagenta\ncyan\nwhite\n```\n\nEach theme definition is placed in its own file of the format `$name.wed`.\nTheme definitions are placed in the `WEDRUNTIME/theme` directory and can be\nadded to or overridden with definitions placed in `~/.wed/theme`.\nBy default wed uses the \"default\" theme i.e. `theme=\"default\";`. This theme\nis not present in config but compiled into wed and cannot be overriden, to\nguarantee it is always available. Any groups not specified in a custom theme\ndefinition will default to using the same values as in the default theme.\n\n### Find \u0026 Replace\n\nThere are two search types available in wed:\n\n#### Text Search\n\nThis is the default search type in wed when opening up the find prompt. It uses\nthe Boyer–Moore–Horspool algorithm to search a file which is both simple and\nefficient. The implementation in wed takes into account that text is stored in\na gap buffer allowing a search to be performed without moving the gap. \nAlltogether these characteristics make the text search very performant.\n\nThe following escape sequences can be used in both the find and replace\nprompts:\n\n```\nEscape sequence   | Description\n------------------|----------------------------------------------------------------------\n\\n                | Converted to new line either LF or CRLF depending on file fileformat.\n\\t                | Converted to tab character\n\\\\                | Converted to single backslash character\n\\xnn              | Converted to byte where nn is hex number (i.e. 0 \u003c= n \u003c= F)\n```\n\nThere are a few caveats with this search type however. It performs a byte by\nbyte comparison and therefore as wed doesn't yet normalise UTF-8 text there is\nno guarantee of a match for UTF-8 sequences unless they match byte for byte.\nThe case insensitive functionality of this search currently only works for\nASCII Alphabetic Characters e.g. [a-zA-Z].\n\n#### Regex Search\n\nThis search type can be selected by toggling the search type in the find prompt\nusing the key combo `\u003cC-t\u003e`. The PCRE library is used for regex searches which\nprovides a flexible and powerful set of features and syntax. See\n`man pcrepattern` for an indepth description of the PCRE syntax.\nThe case sensitivity of the search can be toggled using `\u003cC-s\u003e` however it is\nnot yet possible to specify search flags. All searches are performed with the \nmultiline flag enabled which is equivalent to Perl's /m option.\n\nFurther to the escape sequences described in the [Text Search](#text-search)\nsection, it is also possible to specify back references in the replace text\nfor a regex search. The syntax for specifying a back reference is:\n\n```\n\\n or \\{n} where n is in [0-9] and n \u003e= 0\n```\n\nTo escape a back reference enter a backslash character before it:\n\n```\n\\\\n or \\\\{n} are inserted as \\n and \\{n} respectively\n```\n\nFor example, with the file content as `order Right`, the regex specifed as\n`(\\w+)\\s(\\w+)` and the replace text as `\\2 \\1` the end result will be \n`Right order`.\n\n## Current State and Future Development\n\nThe basic elements of a text editor have been implemented and wed can\nbe used for general editing tasks. It is not ready for use in production or\non data which isn't backed up or retrievable.\nThere is still a great deal of new functionality to be added and much\nexisting functionality to be refined. Below are various areas that could be\nlooked at:\n\n### Immediate Tasks\n\nThese tasks are ideas that can be implemented without major architectural\nchanges. Some may still involve a fair amount of work, but none\nfundamentally change the way wed works. They should ideally be targeted first\nbefore looking at the [Future Tasks](#future-tasks) section.\n\n  - Add text and code tests for remaining untested features.\n  - Highlight line or line number cursor is on.\n  - Set session or buffer level variable using \":\" syntax. i.e. `s:ln=0;` to\n    turn off line numbers at global level.\n  - Write unsaved changes to swap file. Swap files can then be used to\n    recover lost changes or warn user file is open in another instance of wed.\n  - Check if file has changed before writing and prompt user for action i.e.\n    either overwrite file on disk, load changes or cancel write action. A\n    more advanced implementation is to listen for file events (e.g. using\n    inotify) and alert the user as soon as a change from another source is\n    detected.\n  - Enhance wed syntax definitions:\n    - Specify different token types for each capture group.\n      e.g. For `^\\s*(#include)\\s+(\u003c\\w+\u003e)` the token types are\n      `\\1 = \"special\"; \\2 = \"constant\";`.\n    - Allow nested groups e.g. A c string can contain format specifiers, which\n      could be assigned a different token type for contrasting colouring.\n  - Create directory hierarchy for files which don't exist when writing them to\n    disk e.g. for `wed /my/made/up/path.txt` running `\u003cC-s\u003e` should work.\n  - Add add context aware info bar under command prompt in a similar fashion \n    to the helpful functionality nano offers. For example, when opening a\n    find prompt the search option key bindings can be shown.\n  - Add jump list functionality to allow jumping back to previous positions.\n    This is particularly useful for moving around a file or set of files.\n  - Add ctags support. The jump list functionaity described above would need\n    to be implemented first.\n\n### Future Tasks\n\nThese tasks represent big changes that could be applied to wed in the future.\nMost would require a large amount of work to implement. Some of the tasks\noutlined below are still in the design phase and somewhat high level. Ideally\nthe [Immediate Tasks](#immediate-tasks) should be tackled first, as they will\nbring the most benefit for end users and can be done relatively quickly.\n\n#### Plugin Architecture\n\nThere a many ways a plugin architecture could be implemented. Below is a rather\nhigh level overview of two common ways.\n\nOne option is to provide support for a specific language and provide the means\nto manipulate the editor and its state through a library or other constructs\navailable in the language. An advantage of this approach is that one\nlanguage is supported very well. Interpreting functionality can be included\ninto the editor allowing plugins to be run in separate threads rather than\nexecuted as separate processes.\nThe strength of this approch is also a downside. Only a single language can\nbe used, and the editor also has a dependency on libraries used to interpret\nthat language. Any changes in the language and its eco system also have to be\nsupported.\n\nAnother option is to expose an interface through which a plugin written in\nany language can communicate. One method is to use a Unix domain socket\nthrough which plugins can connect and communicate with the editor. Events\ncan be relayed to plugins by the editor, while plugins can send back commands\nto perform to the editor.\nThe disadvantge of this approach is that extra work is required of the plugins\nto communicate with the editor e.g. dealing with sockets, object serialization,\netc... Each plugin running as a separate process also has an overhead. \n\nWhether either method presented above will be used in wed is undecided, a\ncompletely different option may be selected. At this point its up for\ndiscussion.\n\nIn either case a fundamental aspect of the plugin architecture is that\nplugins will register to recieve certain events and implement event handlers.\nFor example, plugins could register to recieve an onInsert, onDelete or\nonBeforeInsert event allowing them to react to events or pre processes input.\nSome events can be handled asynchonously (e.g. onInsert) as they are reactive\nwhilst other events will handled before the editor can continue as they affect\nthe outcome of the event (e.g. onBeforeInsert can change or block the inserted\ntext). This is also discussed in the \n[Multi-threaded architecture](#multi-threaded-architecture) section below.\n\n#### Block Selection and Multiple Cursors\n\nIdeally both Block selection and multiple cursors could be implemented, as\nthey both serve useful purposes. Block selection for acting on columns spanning\nmultiple lines that don't necessarily match a shared pattern. Multiple cursors\nfor acting on patterns in any position over the entire buffer.\n\nBlock selection would require relatively small changes to wed in order to\nimplement currently. Although if multiple cursors were to be later implemented,\nthe functionality would have to be updated. One consideration is to allow\nblock selection for each cursor, allowing in effect multiple block selections.\n\nMultiple cursors would require a greater change to wed. Currently there\nis only single position and selection position structure attached to a buffer,\nwhich is used to track the cursor position and any selected text. There is no\nactual cursor object in wed. To implement this functionality one idea is to\nintroduce a `Cursor` structure which could be used to represent each cursor:\n\n```\ntypedef struct Cursor Cursor;\nstruct Cursor {\n    BufferPos pos;\n    BufferPos select_pos;\n    Cursor *prev;\n    Cursor *next;\n};\n```\n\nCursor's could be stored in a doubly linked list allowing for quick insertion\nand deletion of any cursor. Each `Cursor` has a `select_pos` member so that\neach cursor tracks its own selection. Existing operations could be modified to\nloop through each cursor and then perform their action. For example, the\nbf\\_insert function would now simply loop through each cursor and perform the\ninsertion.\n\nFurther key bindings would need to be introduced to allow the creation and\ndeletion of Cursors. For example, a key combination to create cursors on each\nword matching the word currently under the cursor.\n\nThis functionality would allow many nice features seen in other editors. \nReplacing text and seeing the change take place in all locations simultaneously\nis a good example.\n\n#### Multi-threaded architecture\n\nWed has been written as a single threaded application so far. One of the key\nreasons for this was to keep the code simple. Another key aspect was that\nideally operations should run very quickly i.e. the user shouldn't have to wait\nmore than a few hundred milliseconds for any operation to complete. The result\nis that it shouldn't be necessary to kick off an operation asynchronously, as\nit will complete from a user perspective almost instantaneously.\nOf course this is not possible in all cases as some operations don't have\nconstant time complexity and thus take much longer to complete as the size of\nthe file increases. For example, calculating column numbers for very long lines\n(think single 500MB line) or writing a large file to disk have linear time\ncomplexity.\n\nWhile keeping wed single threaded has proved useful in keeping the code simple\nand has motivated efficiency and speed of operation, making aspects of wed\nmulti-threaded will be necessary in order to advance functionality in some\nareas.\nThe introduction of plugins is a key area, as they are additional input and\noutput streams for wed. They can potentially run more involved tasks and may\nneed to kick off child processes of their own. Due to this they will need\nto be run asynchronously in some cases.\n\nThe following architecture is proposed, which assumes the Unix domain socket\nplugin architecture described above is used (although another could be\nsimilarly used):\n\n##### Queues\n - **Input Queue** - This single queue contains all pending input to be\n   processed. When a user presses a key the corresponding command gets added to\n   the input queue. When a plugin sends a command this also gets added to the\n   input queue.\n - **Output Queue** - This queue contains the results of commands wed has run\n   for plugins i.e. this queue is used for plugin output only. It also contains\n   any events that plugins have registered to receive.\n\nEach queue will have access protected by a mutex ensuring that only one thread\ncan access the queue at a time. As each thread will simply be appending or\npopping entries off the queue, the time each thread blocks for should be\nfairly small, at least relative to the length of other operations.\n\n##### Threads\n - **User Input thread**: Waits (blocks) for user input, maps the input to a\n   command and then adds this command to the Input Queue.\n - **Plugin IO thread**: Waits (for a short time) for input from plugins, maps\n   input to commands then adds the commands to the Input Queue.\n   This thread also periodically checks the Output Queue to see if there is\n   any pending command output or events to send to plugins, and if so sends\n   the data.\n - **Worker Thread**: Waits (blocks) for entries in the Input Queue to exist,\n   pops them off when available and executes their actions and updates the\n   screen. This thread also will add any command output for plugins to the\n   Output Queue as well as events that may have been raised due to the previous\n   command.\n\nWith this architecture all input is unified into a single queue which a single\nthread processes. In effect the core part of wed remains single threaded, but\nlonger operations can be run by plugins (which are separate processes)\nasynchronously by passing them event data.\n\nIn the above setup all plugin functionality is running asynchronously, however\nin some cases it would be required to block until a response from a plugin is\nreceived. For example, consider the onBeforeInsert event. Ideally a plugin\nwould be able to process and change or even reject any text about to be\ninserted into the buffer when handling this event. However this requires\nwaiting for the plugin response before continuing to process input. To deal\nwith this the worker thread will apply a mask for a limited time to the Input\nQueue so that only responses to the last blocking event can be processed. After\nthe time has expired the mask is removed and processing carries on as usual.\nAny late event handler responses or commands from plugins are then discarded.\nThis can be achieved by giving each event a unique id with which all subsequent\ninput and output is associated.\n\n##### Operation Callback Functions\n\nThis idea doesn't require a multi-threaded architecture and could actually be\nimplemented now in wed. This is pertinent because the core worker process\ndescribed above still executes commands sequentially in a single thread.\n\nIn effect long operations are provided a callback function which they would\ncall after a certain percentage of work had been done or time had passed. This\ncallback would then be able to update the screen with the latest progress or\ncheck if the user had issued a cancellation request (like SIGINT) to the\noperation. This works best with operations whose work can be clearly\nquantified so that the tasks progress can be calculated.\n\nFor example, consider the operation of writing a large file to disk, which for\nvarious reasons can be slow. This is a well defined operation. It is\ncurrently implemented by copying 1KB of data at a time from the underlying gap\nbuffer into a temporary buffer and writing that temporary buffer to an output\nfile. Therefore the task is broken up into discrete units of work allowing easy\ncalculation of progress after a number of units have been completed.\nWhilst the operation is in progress the time currently taken could be tracked\nby the bf\\_write\\_file function and after each full second has passed, the\nprogress could be calculated based on the written and remaining bytes and\npassed to the callback function. This callback function could then update\nthe screen with the current progress giving the user some indication of how\nlong the operation will take. An ETA could also be calculated.\nFor very small files the write operation should complete in well under a second\nso that the callback is never called.\n\nThis approach gives the illusion of parallelism whilst only using a single\nthread, which also helps keep code simple and avoids having to implement\ncontrol for multi-threaded access to the Session and Buffer structs.\n\n### Non Goals\n\n - Native Windows support. If you're using Windows then it's unlikely you\n   will be working in a terminal, in which case you can use one of the many\n   excellent existing editors such as notepad++, Sublime Text, etc.\n   If you do want to use wed on Windows then install Cygwin.\n   \n - IDE/Advanced features. Wed is designed to be a simple editor that can\n   be quickly picked up and offer standard editing functionality.\n   If more advanced features are required then it would make far more\n   sense to invest time into learning how to use editors such as vim or\n   emacs, which with plugins will almost certainly be able to perform\n   any task you want.\n\n## Contributing\n\nPlease feel free to contribute any fixes, improvements or new functionality.\nRead the [Immediate Tasks](#immediate-tasks) and [Future Tasks](#future-tasks)\nsections above for ideas. If you want to take on a large piece of work please\ncontact me beforehand just to discuss the idea and implementation.\n\nPlease try and keep any changes you make consistent with the existing style of\nthe code.\n\nTo build a development version of wed run `make dev`. This will build wed\nwith debugging information included whilst also running a series of tests using\nthe generated binary. Please ensure all tests pass before submitting a pull\nrequest.\n\n### Tests\n\nThere are two types of tests currently in wed under the tests directory.\n\n#### Code Tests\n\nThese are unit tests run as part of a TAP harness. Currently there is only\none such test for the gap buffer implementation. The TAP harness implementation\nis also extremely basic. There is a lot of scope for improvement in this area.\n\n#### Text Tests\n\nText tests simulate user interaction with wed. Each test consists of an input\nfile, a sequence of key press inputs and an expected output file. The sequence\nof keys is applied to the input file by wed and the result is compared against\nthe expected output. This is used assert that weds functionality is behaving\nas expected.\n\nEach test is given a name of using the format `\\d{3}-\\w+` e.g. `001-insert`.\nThe number used should increment the previous test number by 1 so that all\ntests have a unique number which can be used to order them. The most basic\ntests (e.g. `001-insert`, `002-delete`) are performed first so that subsequent\nmore advanced tests can use on the functionality they test.\n\nThe files that make up each text test are:\n - `input` - The input file wed loads\n - `cmd` - A sequence of key press inputs\n - `output` - The expected output of cmd acting on input\n - `config (optional)` - Config settings specific to this test\n - `test.output (generated)` - Output generated by wed when running the test\n\nThe bash script `tests/text/run_text_tests.sh` will run all text tests.\nThis script can also be invoked by running `make test` or `make dev` when\nchanges have been made.\n\n## Summary\n\nCongratulations if you've made it this far, or at least read some of the above\nsections. Hopefully the aim, state and direction are clear and you have a\nfairly good idea whether wed is suitable for you or not.\nWed was written with those new to editors such as vim or emacs in mind and not\nfor those already experienced with such tools. However that doesn't preclude\nanyone from using wed when appropriate or getting involved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frgburke%2Fwed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frgburke%2Fwed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frgburke%2Fwed/lists"}