.What is Clink? top
Clink combines the native Windows shell cmd.exe with the powerful command line editing features of the GNU Readline library, which provides rich completion, history, and line-editing capabilities. Readline is best known for its use in the Unix shell Bash, the standard shell for many Linux distributions.
.Feature Highlights up top
Auto-Suggestions
Clink offers suggestions as you type based on history, files, and completions.
C:\dir>findstr_/s needle haystack\*
Press Right or End to insert a suggestion (shown in a muted color).
See Auto-Suggest to learn more.
Completions
Clink can complete words when you press Tab or Ctrl-Space.
Built-in completions are available for executables, aliases, command names, directory commands, and environment variables. You can use Lua scripts to add custom completions.
See How Completion Works to learn more.
Persistent History
Clink stores persistent history between sessions.
- Up and Down cycle through history entries.
- PgUp and PgDn cycle through history entries matching the typed prefix.
- F7 or Ctrl-Alt-Up show a popup list of selectable history entries.
- Ctrl-R and Ctrl-S search history incrementally.
See Saved Command History to learn more.
Scriptable Prompt and Colored Input
You can customize the prompt dynamically with Lua scripts -- like in other shells -- but never before possible in cmd.exe!
C:\repos\clink git main->origin *3 !1
> git merge --help_
Your input is colored by context sensitive completion scripts.
See Popular Scripts and Colors and Customizing the Prompt to learn more.
Command Line Editing Improvements
Clink supercharges the command line with new input editing commands and configurable key bindings. For example,
- Alt-H to display all key bindings.
- Tab for completion.
- Ctrl-Space for an interactive completion list.
- Ctrl-Z to undo input.
- Shift-Arrows to select text, and type to replace selected text.
See Key Bindings to learn more.
Convenience
Optional auto-answering of the "Terminate batch job?" prompt.
Enhanced doskey expansion even after &
and |
.
dirname\
is a shortcut forcd /d
to that directory...
or...
are shortcuts forcd ..
orcd ..\..
(etc).-
orcd -
changes to the previous current working directory.
.Usage top
.Installation up top
You can install Clink by running the setup EXE file from the releases page.
Or by using winget and running winget install clink
.
Or by using scoop and running scoop install clink
.
Or by downloading the ZIP file from releases page, and extracting the files to a directory of your choosing.
.Using Clink up top
Once installed, there are several ways to start Clink.
- If Clink is configured for autorun, just start
cmd.exe
and Clink is automatically injected and ready to use.
The setup EXE has an option "Autorun when cmd.exe starts". If you didn't use the setup EXE, or if you want to enable or disable autorun later, you can run
clink autorun install
orclink autorun uninstall
to change the autorun configuration. Runclink autorun --help
for more info.
- To manually start, run the Clink shortcut from the Start menu (or the clink.bat located in the install directory).
- To establish Clink to an existing
cmd.exe
process, useclink inject
.
If the Clink install directory isn't in the PATH, then use
install_dir\clink
in place ofclink
to run Clink commands. Once Clink is injected into acmd.exe
process, then it automatically sets an alias so that you can simply useclink
.
Starting Clink injects it into a cmd.exe
process, where it intercepts a handful of Windows API functions so that it can replace the prompt and input line editing with its own Readline-powered enhancements.
.Getting Started top
You can use Clink right away without configuring anything:
- Searchable command history will be saved between sessions.
- Suggestions are automatically offered as you type; press Right or End to insert a suggestion.
- Tab and Ctrl-Space provide match completion two different ways.
- Press Alt-H to see a list of the current key bindings.
- Press Alt-Shift-/ followed by another key to see what command is bound to the key.
There are three main ways of customizing Clink to your preferences: the Readline init file (the .inputrc
file), the Clink settings (the clink set
command), and Lua scripts.
.How Completion Works up top
"Completion" is for the word at the cursor; when you press Tab Clink tries to complete the word from a list of possible completions. Press Alt-= to see the list of possible completions.
"Suggestions" are for the whole command line; Clink offers an automatic suggestion for the whole input line, which you can insert by pressing Right or End. There is never more than one automatic suggestion at a time.
Some examples of what completions can offer:
- File names,
- Directories,
- Environment variables,
- Commands,
- Command arguments and flags,
- You can provide custom completion generators using Lua scripts that execute inside Clink (see Extending Clink With Lua and Popular Scripts).
.Completion Keys up top
Tab completes the word at the cursor:
- If you installed Clink with "Use enhanced defaults" or if you set
clink.default_bindings
to use "windows" defaults, then Tab cycles through the possible completions, replacing the word with the next possible completion each time. - Otherwise, Tab performs completion the same way that bash does on Unix and Linux: When you press Tab, Clink finds matches for how to complete the word at the cursor. It automatically inserts the longest common prefix shared by the possible completions. If you press Tab again, it also lists the possible completions.
Ctrl-Space shows an interactive list of possible completions:
- You can use the arrow keys to choose which completion to insert, and you can type to filter the list.
- Pressing Enter in the list inserts the selected completion.
- Pressing Space in the list inserts the selected completion and makes sure a space follows it to allow typing a next argument.
See Completion Commands and Clink Commands for more available completion commands.
.Executable Completion up top
By default, Clink completes the first word of each command based on all executable programs on the system PATH and the current directory, but not non-executable files.
You can turn off the "executable completion" behavior by running clink set exec.enable false
, or you can adjust its behavior by changing the various exec.*
settings.
.Common Configuration up top
The following sections describe some ways to begin customizing Clink to your taste.
Enhanced default settings | Optionally use enhanced default settings. |
Create a .inputrc file | Create a .inputrc file where config variables and key bindings can be set. |
Bash vs Windows | Make Ctrl-F and Ctrl-M work like usual on Windows. |
Auto-suggest | How to enable and use automatic suggestions. |
Colors | Configure the colors. |
Key Bindings | Customize your key bindings. |
Mouse Input | Optionally enable mouse clicks in the input line, etc. |
Startup Message | Control whether the startup message is shown (copyright notice and version info). |
Startup Cmd Script | Optional automatic clink_start.cmd script. |
Custom Prompt | Customizing the command line prompt. |
Upgrading from Clink v0.4.9 | Notes on upgrading from a very old version of Clink. |
.Enhanced default settings up top
Clink can be installed with plain defaults, or it can be installed with enhanced default settings that enable more of Clink's enhancements by default.
If you install Clink with the setup program and "Use enhanced default settings" is checked, then the enhanced defaults are activated, and then in some places where this documentation refers to default settings the stated default may have been overridden.
If you install Clink from the .zip file then enhanced default settings are activated when the default_settings
and default_inputrc
files are present in the binaries directory or in the profile directory. The .zip file comes with the files, but their names have a _
prefix so that enhanced defaults won't automatically take effect. You can activate the enhanced default settings by renaming the files to remove the _
prefix.
Here are some of the enhanced defaults. Review the default_settings
and default_inputrc
files for the full list.
- Many color settings have colorful defaults.
- Uses Windows key bindings by default.
- The command history's default limit is increased to 25,000 entries.
- Completion expands environment variables (the
match.expand_envvars
setting). - If no completions are found with a prefix search, then a substring search is used (the
match.substring
setting). - Ctrl-D does not exit CMD (the
cmd.ctrld_exits
setting). - History saves and shows time stamps.
.Create a .inputrc file up top
First you'll want to create a .inputrc
file, and a good place is in your Windows user profile directory.
This file is used for some configuration, such as key bindings and colored completions.
Create the file by running this command at a CMD prompt:
notepad %userprofile%\.inputrc
You may want to copy/paste the following sample text into the file as a starting point, and then press Ctrl-S to save the file.
# Some common Readline config settings.
set colored-stats on # Turn on completion colors.
set colored-completion-prefix on # Color the typed completion prefix.
# Some config settings that only work in Clink.
$if clink
set search-ignore-case on # Case insensitive history searches.
set completion-auto-query-items on # Prompt before showing completions if they'll exceed half the screen.
$endif
# Add your keybindings here...
See Init File for more information on Readline init files.
.Bash vs Windows up top
The default Clink key bindings are the same as in the "bash" shell for Unix/Linux. That makes some keys like Ctrl-A, Ctrl-F, and Ctrl-M behave differently than you might be used to in CMD.
To instead use the familiar Windows default key bindings you can run clink set clink.default_bindings windows
.
Or, if you use the setup program with "Use enhanced default settings" checked then "windows" key bindings are the default, and you can run clink set clink.default_bindings bash
to use the bash default key bindings.
Clink comes with many default key bindings. Use Alt-H to see all of the active key bindings, or use Alt-Shift-? to check what is bound to a specific key. See Key Bindings to get started configuring your own key bindings.
Here are the differences between the Windows defaults and the bash defaults:
Key | Windows | Bash |
---|---|---|
Ctrl-A | Select All. | Go to beginning of line. |
Ctrl-B | (not bound) | Move backward one character. |
Ctrl-E | Expands doskey aliases, environment variables, and history expansions in the current line. | Go to end of line. |
Ctrl-F | Find text (in plain Conhost console windows). | Move forward one character. |
Ctrl-M | Mark text (in plain Conhost console windows). | Same as Enter. |
Tab | Cycle forward through available completions. | Bash style completion. |
Shift-Tab | Cycle backward through available completions. | (not bound) |
Right | Move forward one character, or at the end of the line insert the next character from the previous input line. | Move forward one character. |
.Auto-suggest up top
Clink can suggest command lines as you type, based on command history and completions.
You can turn off automatic suggestions with clink set autosuggest.enable false
, or turn them on with clink set autosuggest.enable true
.
When automatic suggestions are enabled and the cursor is at the end of the input line, a suggestion may appear in a muted color. If the suggestion isn't what you want, just ignore it. Or you can insert the whole suggestion with the Right arrow or End key, insert the next word of the suggestion with Ctrl-Right, or insert the next full word of the suggestion up to a space with Shift-Right.
Here's an example of how auto-suggestion works. Suppose you ran a command, so now it's in your command history:
C:\dir>findstr /s needle haystack\*
Later, you start to type a new command, and it matches the earlier command from the history:
C:\dir>findstr _/s needle haystack\*
The muted text shows a suggestion that might be what you intend to type. You can insert the muted text into the input line by pressing the Right key.
If you press Tab then that invokes completion instead. Completion is something you manually invoke to offer possible completions for a word or argument position. Auto-suggestion automatically offers a suggestion for a whole input line, and the suggestion can come from the saved command history or from the list of possible completions. There can be many possible completions available, but there is never more than one auto-suggestion available.
The autosuggest.hint
setting controls whether to show the [Right]=Insert Suggestion
usage hint when a suggestion is available.
The autosuggest.strategy
setting determines how suggestions are chosen.
.Colors up top
Clink has many configurable colors for match completions, input line coloring, popup lists, and more.
If you use the setup program with "Use enhanced default settings" checked then many of the color settings have more colorful default values.
See below for information on customizing colors yourself, or see Color Themes for information on applying color theme files (whose names end with ".clinktheme"). Clink comes with a few color theme files, and users can also share color themes online (or convert color themes from other shells).
.For completion up top
When performing completion (e.g. Tab or Ctrl-Space) Clink can add color to the possible completions.
To turn on colored completions, put a line set colored-stats on
in the .inputrc file (if you copy/pasted the sample text, it's already there).
See the Completion Colors section for how to configure the colors for match completions.
.Other colors up top
Clink adds color to the input line by highlighting arguments, flags, doskey macros, and more. If you don't want input line colors, you can turn it off by running clink set clink.colorize_input false
.
Here are examples, using the colors from the Use enhanced defaults installation option:
c:\dir>clink set --help 'clink' has an argmatcher
c:\dir>attrib 'attrib' is a CMD command
c:\dir>myalias if 'myalias' is a doskey alias
c:\dir>control 'control' is an executable
c:\dir>xyzabc123 unrecognized
c:\dir>whatever if executable and unrecognized colors are not set
To configure a color, run clink set colorname colorvalue
. Match completions make it easy to change Clink settings: type clink set color.
and then use completion (e.g. Tab or Ctrl-Space) to see the available color settings, and to fill in a color value.
See the Coloring the Input Text and Color Settings sections for more information on Clink color settings.
.Key Bindings up top
You can customize your key bindings (keyboard shortcuts) by assigning key bindings in the .inputrc file. See Customizing Key Bindings for more information.
Clink comes with many pre-configured key bindings that invoke named commands. Here are a few that you might find especially handy:
Alt-H | This is clink-show-help , which lists the key bindings and commands. |
Tab | This is complete or old-menu-complete , depending on the clink.default_bindings Clink setting.complete performs completion by selecting from an interactive list of possible completions; if there is only one match, the match is inserted immediately.old-menu-complete cycles through inserting the possible completions. |
Ctrl-Space | This is clink-select-complete , which performs completion by selecting from an interactive list of possible completions; if there is only one match, the match is inserted immediately. |
Alt-= | This is possible-completions , which lists the available completions for the current word in the input line. |
Alt-. | This is yank-last-arg , which inserts the last argument from the previous line. You can use it repeatedly to cycle backwards through the history, inserting the last argument from each line. Learn more by reading about Killing and Yanking.
|
Ctrl-R | This is reverse-search-history , which incrementally searches the history. Press it, then type, and it does a reverse incremental search while you type. Press Ctrl-R again (and again, etc) to search for other matches of the search text. Learn more by reading about Searching for Commands in the History. |
Ctrl-Alt-D | This is remove-history , which deletes the currently selected history line after using any of the history search or navigation commands. |
Ctrl-Alt-K | This is add-history , which adds the current line to the history without executing it, and then clears the input line. |
Ctrl-Alt-N | This is clink-menu-complete-numbers , which grabs numbers with 3 or more digits from the current console screen and cycles through inserting them as completions (binary, octal, decimal, hexadecimal). Super handy for quickly inserting a commit hash that was printed as output from a preceding command. |
Alt-0 to Alt-9 | These are digit-argument , which let you enter a numeric value used by many commands. For example Ctrl-Alt-W copies the current word to the clipboard, but if you first type Alt-2 followed by Ctrl-Alt-W then it copies the 3rd word to the clipboard (the first word is 0, the second is 1, etc). Learn more by reading about Readline Arguments. |
For a full list of commands available for key bindings, see Bindable Commands.
.Mouse Input up top
Clink can optionally respond to mouse input, instead of letting the terminal respond to mouse input (e.g. to select text on the screen). When mouse input is enabled in Clink, you can click in the input line or in popup lists, and the mouse wheel scrolls popup lists.
Use clink set terminal.mouse_input mode
with one of the following modes to control whether Clink responds to mouse input:
Mode | Description |
---|---|
off |
Lets the terminal host handle mouse input. |
on |
Lets Clink handle mouse input. |
auto |
Lets Clink handle mouse input in ConEmu and in the default Conhost terminal when Quick Edit mode is unchecked in the console Properties dialog. |
Use clink set terminal.mouse_modifier modifiers
or set CLINK_MOUSE_MODIFIER=modifiers
to control which modifier keys must be held for Clink to respond to mouse input.
These select which modifier keys (Alt, Ctrl, Shift) must be held in order for Clink to respond to mouse input when mouse input is enabled by the terminal.mouse_input
setting. modifiers is a text string that can list one or more modifier keys: "alt", "ctrl", and "shift". For example, setting it to "alt shift" causes Clink to only respond to mouse input when both Alt and Shift are held (and not Ctrl). If the %CLINK_MOUSE_MODIFIER%
environment variable is set then its value supersedes the terminal.mouse_modifier
setting. In Windows Terminal many modifier keys do special things with mouse clicks, so the modifier key combination that interferes least with built in Windows Terminal behaviors is Ctrl-Alt.
When mouse input is enabled in Clink, then mouse input works a little differently:
- You can bypass Clink mouse input and use the normal terminal mouse input by holding a different combination of modifier keys than listed in
terminal.mouse_modifier
or%CLINK_MOUSE_MODIFIER%
. - Windows Terminal treats Shift-RightClick specially and turns off line ending detection when copying the selected text to the clipboard. Hold Ctrl or Alt when right clicking to do the normal copy with line ending detection.
- In ConEmu, the mouse wheel always scrolls the terminal; Clink cannot use it to scroll popup lists.
- In the default Conhost terminal when Quick Edit mode is turned off then Clink will also respond to mouse input when no modifier keys are held.
.Startup Message up top
By default, Clink prints a startup message containing a copyright notice and the program version. This is shown so it's easy to tell whether Clink is active and what version is being used.
You can make the startup message shorter by running clink set clink.logo short
.
You can remove the startup message by running clink set clink.logo none
.
.Startup Cmd Script up top
When Clink is injected, it looks for a clink_start.cmd
script in the binaries directory and profile directory. Clink automatically runs the script(s), if present, when the first CMD prompt is shown after Clink is injected and before any Lua scripts run. You can set the clink.autostart
setting to run a different command, or set it to "nul" to run no command at all.
.Custom Prompt up top
If you want a customizable prompt with a bunch of styles and an easy-to-use configuration wizard, check out clink-flex-prompt. Also, if you've been disappointed by git making the prompt slow in other shells, try this prompt -- it makes the prompt appear instantly by running git commands in the background and refreshing the prompt once the background commands complete.
Other popular configurable prompts are oh-my-posh and starship.
See Customizing the Prompt for information on how to use Lua to customize the prompt.
.Upgrading from Clink v0.4.9 up top
The new Clink tries to be as backward compatible with Clink v0.4.9 as possible. However, in some cases upgrading may require a little bit of configuration work.
- Some key binding sequences have changed; see Customizing Key Bindings for more information.
- Match coloring works differently now and can do much more; see Completion Colors for more information.
- Old settings and history migrate automatically if you use the same profile directory when upgrading. If you use a different profile directory, then you can still migrate the old settings and history by copying certain files. See below for details.
- Script compatibility should be very good, but some scripts may still encounter problems. If you do encounter a compatibility problem you can look for an updated version of the script, update the script yourself, or visit the clink repo and open an issue describing details about the compatibility problem.
- Some match generator scripts might need adjustments to become fully compatible with the
autosuggest.enable
setting. - Some settings have changed slightly, and there are many new settings. See Configuring Clink for more information.
.Migrating between different profile directories up top
All versions of Clink use the same default profile directory location. If you haven't overridden the profile directory, then your settings and history will automatically migrate when upgrading to newer versions of Clink.
If you choose to use a different profile directory, then you can still make migration happen by copying certain files:
- When using Clink v0.4.9 you can use
clink set
to find the settings file path. - When using newer versions of Clink you can use
clink info
to find the profile directory. - Copy the
settings
and.history
files from the old directory into the new directory. - If you already have a
clink_settings
orclink_history
file in your new profile directory, then you'll need to rename them in order for migration to happen (e.g. add.txt
to the names). - Close the Clink session(s) and open new ones.
.Configuring Clink top
Clink has two configuration systems, which is a result of using the Readline library to provide command history and key bindings.
The following sections describe how to configure Clink itself. To learn about the Readline configuration and key bindings, instead see Configuring Readline.
Clink Settings | How to customize Clink's settings. |
Color Settings | Describes the syntax used by color settings. |
File Locations | Where Clink stores its history and settings files. |
Command Line Options | Describes the command line options for the Clink program. |
Portable Configuration | How to set up a "portable" installation of Clink, e.g. on a USB drive or network location. |
.Clink Settings up top
The easiest way to configure Clink is to use the clink set
command to list, query, and set Clink's settings.
Run clink set --help
from a Clink-installed cmd.exe process to learn more.
The following table describes the available Clink settings:
Name | Default * | Description |
---|---|---|
.argmatcher.show_hints |
True | When both the comment_row.show_hints and argmatcher.show_hints settings are enabled, argmatchers can show usage hints in the comment row (below the input line). |
.autosuggest.async |
True | When this is true matches are generated asynchronously for suggestions. This helps to keep typing responsive. |
.autosuggest.enable |
True | When this is true a suggested command may appear in color.suggestion color after the cursor. If the suggestion isn't what you want, just ignore it. Or insert the whole suggestion with the Right arrow or End key, insert the next word of the suggestion with Ctrl-Right, or insert the next full word of the suggestion up to a space with Shift-Right. The autosuggest.strategy setting determines how a suggestion is chosen. |
.autosuggest.hint |
True | The default is true . When this and autosuggest.enable are both true and a suggestion is available, show a usage hint [Right]=Insert Suggestion to help make the feature more discoverable and easy to use. Set this to false to hide the usage hint. |
.autosuggest.original_case |
True | When this is enabled (the default), inserting a suggestion uses the original capitalization from the suggestion. |
.autosuggest.strategy |
match_prev_cmd history completion |
This determines how suggestions are chosen. The suggestion generators are tried in the order listed, until one provides a suggestion. There are three built-in suggestion generators, and scripts can provide new ones. history chooses the most recent matching command from the history. completion chooses the first of the matching completions. match_prev_cmd chooses the most recent matching command whose preceding history entry matches the most recently invoked command, but only when the history.dupe_mode setting is add . |
.clink.autostart |
This command is automatically run when the first CMD prompt is shown after Clink is injected. If this is blank (the default), then Clink instead looks for clink_start.cmd in the binaries directory and profile directory and runs them. Set it to "nul" to not run any autostart command. |
|
.clink.autoupdate |
check |
Clink can periodically check for updates for the Clink program files (see Automatic Updates). |
.clink.colorize_input |
True | Enables context sensitive coloring for the input text (see Coloring the Input Text). |
.clink.customprompt |
*.clinkprompt files contain customizations for the prompt. Setting this to the name of a .clinkprompt file causes it to be loaded and used for displaying the prompt (see Customizing the Prompt). | |
.clink.default_bindings |
bash * |
Clink uses bash key bindings when this is set to bash (the default). When this is set to windows Clink overrides some of the bash defaults with familiar Windows key bindings for Tab, Ctrl-A, Ctrl-F, Ctrl-M, and Right. |
.clink.logo |
full |
Controls what startup logo to show when Clink is injected. full = show full copyright logo, short = show abbreviated version info, none = omit the logo. |
.clink.max_input_rows |
0 |
Limits how many rows the input line can use, up to the terminal height. When this is 0 (the default), the terminal height is the limit. |
.clink.paste_crlf |
crlf |
What to do with CR and LF characters on paste. Setting this to delete deletes them, space replaces them with spaces, ampersand replaces them with ampersands, and crlf pastes them as-is (executing commands that end with a newline). |
.clink.path |
A list of paths from which to load Lua scripts. Multiple paths can be delimited semicolons. | |
.clink.popup_search_mode |
find |
When this is find , typing in popup lists moves to the next matching item. When this is filter , typing in popup lists filters the list. |
.clink.promptfilter |
True | Enable prompt filtering by Lua scripts. |
.clink.update_interval |
5 |
The Clink autoupdater will wait this many days between update checks (see Automatic Updates). |
.cmd.admin_title_prefix |
When set, this replaces the "Administrator: " console title prefix. | |
.cmd.altf4_exits |
True | When set, pressing Alt-F4 exits the cmd.exe process. |
.cmd.auto_answer |
off |
Automatically answers cmd.exe's "Terminate batch job (Y/N)?" prompts. off = disabled, answer_yes = answer Y, answer_no = answer N. |
.cmd.ctrld_exits |
True * | Ctrl-D exits the cmd.exe process when it is pressed on an empty line. |
.cmd.get_errorlevel |
True | When this is enabled, Clink runs a hidden echo %errorlevel% command before each interactive input prompt to retrieve the last exit code for use by Lua scripts. If you experience problems, try turning this off. This is on by default. |
.color.arg |
The color for arguments in the input line when clink.colorize_input is enabled. |
|
.color.arginfo |
yellow * |
Argument info color. Some argmatchers may show that some flags or arguments accept additional arguments, when listing possible completions. This color is used for those additional arguments. (E.g. the "dir" in a "-x dir" listed completion.) |
.color.argmatcher |
* | The color for the command name in the input line when clink.colorize_input is enabled, if the command name has an argmatcher available. |
.color.cmd |
bold * |
Used when displaying shell (CMD.EXE) command completions, and in the input line when clink.colorize_input is enabled. |
.color.cmdredir |
bold * |
The color for redirection symbols (< , > , >& ) in the input line when clink.colorize_input is enabled. |
.color.cmdsep |
bold * |
The color for command separators (& , | ) in the input line when clink.colorize_input is enabled. |
.color.comment_row |
bright white on cyan * |
The color for the comment row. During clink-select-complete the comment row shows the "and N more matches" or "rows X to Y of Z" messages. It can also show how history expansion will be applied at the cursor. |
.color.common_match_prefix |
Used when displaying a prefix that all match completions have in common. This can be superseded by Completion Colors. | |
.color.description |
bright cyan * |
Used when displaying descriptions for match completions. |
.color.doskey |
bright cyan * |
Used when displaying doskey alias completions, and in the input line when clink.colorize_input is enabled. |
.color.executable |
* | When set, this is the color in the input line for a command word that is recognized as an executable file when clink.colorize_input is enabled. |
.color.filtered |
bold * |
The default color for filtered completions (see Filtering the Match Display). |
.color.flag |
default * |
The color for flags in the input line when clink.colorize_input is enabled. |
.color.hidden |
* | Used when displaying file completions with the "hidden" attribute. |
.color.histexpand |
* | The color for history expansions in the input line when clink.colorize_input is enabled. If this color is not set or history.auto_expand is disabled or history.expand_mode is off, then history expansions are not colored. |
.color.horizscroll |
* | The color for the < or > horizontal scroll indicators when Readline's horizontal-scroll-mode variable is set. |
.color.input |
* | The color for input line text. Note that when clink.colorize_input is disabled, the entire input line is displayed using color.input . |
.color.interact |
bold |
The color for prompts such as a pager's --More?-- prompt. |
.color.message |
default |
The color for the message area (e.g. the search prompt message, digit argument prompt message, etc). |
.color.popup |
When set, this is used as the color for popup lists and messages. If no color is set, then the console's popup colors are used (see the Properties dialog box for the console window). | |
.color.popup_border |
When set, this is used as the color popup list borders. If no color is set, then the color from color.popup is used. |
|
.color.popup_desc |
When set, this is used as the color for description column(s) in popup lists. If no color is set, then a color is chosen to complement the console's popup colors (see the Properties dialog box for the console window). | |
.color.popup_footer |
When set, this is used as the color for popup list footer message text. If no color is set, then the color from color.popup_border is used. |
|
.color.popup_header |
When set, this is used as the color for popup list title text. If no color is set, then the color from color.popup_border is used. |
|
.color.popup_select |
When set, this is used as the color for the selected popup list item. If no color is set, a color is chosen by swapping the foreground and background colors from color.popup . |
|
.color.popup_selectdesc |
When set, this is used as the color for the selected popup list item's description text. If no color is set, a color is chosen by swapping the foreground and background colors from color.popup . |
|
.color.prompt |
When set, this is used as the default color for the prompt. But it's overridden by any colors set by Customizing The Prompt. | |
.color.readonly |
* | Used when displaying file completions with the "readonly" attribute. |
.color.selected_completion |
* | The color for the selected completion with the clink-select-complete command. If no color is set, then bright reverse video is used. |
.color.selection |
* | The color for selected text in the input line (for example, when using Shift-Arrow keys). If no color is set, then reverse video is used. |
.color.suggestion |
bright black * |
The color for automatic suggestions when autosuggest.enable is enabled. |
.color.unexpected |
default |
The color for unexpected arguments in the input line when clink.colorize_input is enabled. |
.color.unrecognized |
* | When set, this is the color in the input line for a command word that is not recognized as a command, doskey macro, directory, argmatcher, or executable file. |
.comment_row.hint_delay |
500 |
Specifies a delay in milliseconds before showing input hints (see Showing Input Hints). The delay can be up to 3000 milliseconds, or 0 for no delay. |
.comment_row.show_hints |
False | Allow showing input hints in the comment row (see Showing Input Hints). |
.debug.log_output_callstacks |
False | Include callstack when logging output. This has no effect unless debug.log_terminal is enabled. This is intended for diagnostic purposes only, and can make the log file grow significantly. |
.debug.log_terminal |
False | Logs all terminal input and output to the clink.log file. This is intended for diagnostic purposes only, and can make the log file grow significantly. |
.directories.dupe_mode |
add |
Controls how the current directory history is updated. A value of add (the default) always adds the current directory to the directory history. A value of erase_prev will erase any previous entries for the current directory and then add it to the directory history. Note that directory history is not saved between sessions. |
.doskey.enhanced |
True | Enhanced Doskey adds the expansion of macros that follow | and & command separators and respects quotes around words when parsing $1 ...$9 tags. To suppress macro expansion for an individual command, prefix the command with a space or semicolon ( foo or ;foo ). Or following | or & , prefix with two spaces or a semicolon (foo| bar or foo|;bar ). |
.exec.aliases |
True | When matching executables as the first word (exec.enable ), include doskey aliases. |
.exec.associations |
False | When matching executables as the first word (exec.enable ), include files with a registered file association (e.g. launchable documents such as ".pdf" files). |
.exec.commands |
True | When matching executables as the first word (exec.enable ), include CMD commands (such as cd , copy , exit , for , if , etc). |
.exec.cwd |
True | When matching executables as the first word (exec.enable ), include executables in the current directory. (This is implicit if the word being completed is a relative path, or if exec.files is true.) |
.exec.dirs |
True | When matching executables as the first word (exec.enable ), also include directories relative to the current working directory as matches. |
.exec.enable |
True | Match executables when completing the first word of a line. Executables are determined by the extensions listed in the %PATHEXT% environment variable. |
.exec.files |
False | When matching executables as the first word (exec.enable ), include files in the current directory. |
.exec.path |
True | When matching executables as the first word (exec.enable ), include executables found in the directories specified in the %PATH% environment variable. |
.exec.space_prefix |
True | If the line begins with whitespace then Clink bypasses executable matching (exec.path ) and will do normal files matching instead. |
.files.hidden |
True | Includes or excludes files with the "hidden" attribute set when generating file lists. |
.files.system |
False | Includes or excludes files with the "system" attribute set when generating file lists. |
.history.auto_expand |
True | When enabled, history expansion is automatically performed when a command line is accepted (by pressing Enter). When disabled, history expansion is performed only when a corresponding expansion command is used (such as clink-expand-history Alt-^, or clink-expand-line Alt-Ctrl-E). |
.history.dont_add_to_history_cmds |
exit history |
List of commands that aren't automatically added to the history. Commands are separated by spaces, commas, or semicolons. Default is exit history , to exclude both of those commands. |
.history.dupe_mode |
erase_prev |
If a line is a duplicate of an existing history entry Clink will erase the duplicate when this is set to erase_prev . Setting it to ignore will not add duplicates to the history, and setting it to add will always add lines (except when overridden by history.sticky_search ). |
.history.expand_mode |
not_quoted |
The ! character in an entered line can be interpreted to introduce words from the history. This can be enabled and disable by setting this value to on or off . Values of not_squoted , not_dquoted , or not_quoted will skip any ! character quoted in single, double, or both quotes respectively. |
.history.ignore_space |
True | Ignore lines that begin with whitespace when adding lines in to the history. |
.history.max_lines |
10000 * | The number of history lines to save if history.save is enabled (or 0 for unlimited). |
.history.save |
True | Saves history between sessions. When disabled, history is neither read from nor written to a master history list; history for each session is written to a temporary file during the session, but is not added to the master history list. |
.history.shared |
False | When history is shared, all instances of Clink update the master history list after each command and reload the master history list on each prompt. When history is not shared, each instance updates the master history list on exit. |
.history.show_preview |
True | When enabled, if the text at the cursor is subject to history expansion, then this shows a preview of the expanded result below the input line using the color.comment_row setting. |
.history.sticky_search |
False | When enabled, reusing a history line does not add the reused line to the end of the history, and it leaves the history search position on the reused line so next/prev history can continue from there (e.g. replaying commands via Up several times then Enter, Down, Enter, etc). |
.history.time_format |
%F %T   |
This specifies a time format string for showing timestamps for history items. For a list of format specifiers see clink set history.time_format or History Timestamps. |
.history.time_stamp |
off |
The default is off . When this is save , timestamps are saved for each history item but are only shown when the --show-time flag is used with the history command. When this is show , timestamps are saved for each history item, and timestamps are shown in the history command unless the --bare or --no-show-time flag is used. |
.lua.break_on_error |
False | Breaks into Lua debugger on Lua errors. |
.lua.break_on_traceback |
False | Breaks into Lua debugger on traceback() . |
.lua.debug |
False | Loads a simple embedded command line debugger when enabled. Breakpoints can be added by calling pause(). |
.lua.path |
Value to append to the package.path Lua variable. Used to search for Lua scripts specified in require() statements. |
|
.lua.strict |
True | When enabled, argument errors cause Lua scripts to fail. This may expose bugs in some older scripts, causing them to fail where they used to succeed. In that case you can try turning this off, but please alert the script owner about the issue so they can fix the script. |
.lua.traceback_on_error |
False | Prints stack trace on Lua errors. |
.match.coloring_rules |
Provides a series of color definitions used when displaying match completions. See Completion Colors for details. | |
.match.expand_abbrev |
True | Expands an abbreviated path before performing completion. In an abbreviated path, directory names may be shortened to the minimum number of characters to unambiguously refer to a directory. For example, "c:\Users\chris\Documents" could be abbreviated as "c:\U\c\Do", depending on what directories exist in the file system. |
.match.expand_envvars |
False * | Expands environment variables in a word before performing completion. |
.match.fit_columns |
True | When displaying match completions, this calculates column widths to fit as many as possible on the screen. |
.match.ignore_accent |
True | Controls accent sensitivity when completing matches. For example, ä and a are considered equivalent with this enabled. |
.match.ignore_case |
relaxed |
Controls case sensitivity when completing matches. off = case sensitive, on = case insensitive, relaxed = case insensitive plus - and _ are considered equal. |
.match.limit_fitted_columns |
0 |
When the match.fit_columns setting is enabled, this disables calculating column widths when the number of matches exceeds this value. The default is 0 (unlimited). Depending on the screen width and CPU speed, setting a limit may avoid delays. |
.match.max_rows |
0 |
The maximum number of rows of items clink-select-complete can show. When this is 0, the limit is the terminal height. |
.match.preview_rows |
0 |
The number of rows to show as a preview when using the clink-select-complete command (bound by default to Ctrl-Space). When this is 0, all rows are shown and if there are too many matches it instead prompts first like the complete command does. Otherwise it shows the specified number of rows as a preview without prompting, and it expands to show the full set of matches when the selection is moved past the preview rows. |
.match.sort_dirs |
with |
How to sort matching directory names. before = before files, with = with files, after = after files. |
.match.substring |
False * | When set, if no completions are found with a prefix search, then a substring search is used. |
.match.translate_slashes |
auto |
File and directory completions can be translated to use consistent slashes. The default is auto which translates all slashes in the completed word to match the first kind of slash in the word (or the system path separator if the word didn't have any slashes before being completed). Use slash for forward slashes, backslash for backslashes, or system for the appropriate path separator for the OS host (backslashes on Windows). Use off to turn off translating slashes. |
.match.wild |
True | Matches ? and * wildcards and leading . when using any of the completion commands. Turn this off to behave how bash does, and not match wildcards or leading dots (but glob-complete-word always matches wildcards). |
.prompt.async |
True | Enables asynchronous prompt refresh. Turn this off if prompt filter refreshes are annoying or cause problems. |
.prompt.spacing |
normal |
The default is normal which never removes or adds blank lines. Set to compact to remove blank lines before the prompt, or set to sparse to remove blank lines and then add one blank line. |
.prompt.transient |
off |
Controls when past prompts are collapsed (transient prompts). off = never collapse past prompts, always = always collapse past prompts, same_dir = only collapse past prompts when the current working directory hasn't changed since the last prompt. |
.readline.hide_stderr |
False | Suppresses stderr from the Readline library. Enable this if Readline error messages are getting in the way. |
.terminal.adjust_cursor_style |
True | When enabled, Clink adjusts the cursor shape and visibility to show Insert Mode, produce the visible bell effect, avoid disorienting cursor flicker, and to support ANSI escape codes that adjust the cursor shape and visibility. But it interferes with the Windows 10 Cursor Shape console setting. You can make the Cursor Shape setting work by disabling this Clink setting (and the features this provides). |
.terminal.color_emoji |
auto |
Set this to indicate whether the terminal program draws emojis using colored double width characters. This needs to be set accurately in order for Clink to display the input line properly when it contains emoji characters. When set to off Clink assumes emojis are rendered using 1 character cell. When set to on Clink assumes emojis are rendered using 2 character cells. When set to auto (the default) Clink tries to predict how emojis will be rendered based on OS version and terminal program. |
.terminal.differentiate_keys |
False | When enabled, pressing Ctrl-H or I or M or [ generate special key sequences to enable binding them separately from Backspace or Tab or Enter or Esc. |
.terminal.east_asian_ambiguous |
auto |
There is a group of East Asian characters whose widths are ambiguous in the Unicode standard. This setting controls how to resolve the ambiguous widths. By default this is set to auto , but some terminal hosts may require setting this to a different value to work around limitations in the terminal hosts. Setting this to font measures the East Asian Ambiguous character widths using the current font. Setting it to one uses 1 as the width, or two uses 2 as the width. When this is 'auto' (the default) and the current code page is 932, 936, 949, or 950 then it tries to automatically measure the width based on which terminal host and font are used, or for any other code pages (including UTF8) it uses 1 as the width. The %CLINK_EAST_ASIAN_AMBIGUOUS% environment variable overrides this setting. |
.terminal.emulation |
auto |
Clink can either emulate a virtual terminal and handle ANSI escape codes itself, or let the console host natively handle ANSI escape codes. native = pass output directly to the console host process, emulate = clink handles ANSI escape codes itself, auto = emulate except when running in ConEmu, Windows Terminal, WezTerm, or Windows 10 new console. |
.terminal.mouse_input |
auto |
Clink can optionally respond to mouse input, instead of letting the terminal respond to mouse input (e.g. to select text on the screen). When mouse input is enabled in Clink, clicking in the input line sets the cursor position, and clicking in popup lists selects an item, etc. Setting this to off lets the terminal host handle mouse input, on lets Clink handle mouse input, and auto lets Clink handle mouse input in ConEmu and in the default Conhost terminal when Quick Edit mode is unchecked in the console Properties dialog. For more information see Mouse Input. |
.terminal.mouse_modifier |
This selects which modifier keys (Alt, Ctrl, Shift) must be held in order for Clink to respond to mouse input when mouse input is enabled by the terminal.mouse_input setting. This is a text string that can list one or more modifier keys: 'alt', 'ctrl', and 'shift'. For example, setting it to "alt shift" causes Clink to only respond to mouse input when both Alt and Shift are held (and not Ctrl). If the %CLINK_MOUSE_MODIFIER% environment variable is set then its value supersedes this setting. For more information see Mouse Input. |
|
.terminal.raw_esc |
False | When enabled, pressing Esc sends a literal escape character like in Unix or Linux terminals. This setting is disabled by default to provide a more predictable, reliable, and configurable input experience on Windows. Changing this only affects future Clink sessions, not the current session. |
.terminal.scrollbars |
True | When enabled, lists show scrollbars using extended Unicode box drawing characters. Some terminals or fonts may be incompatible with this. |
.terminal.use_altgr_substitute |
False | Support Windows' Ctrl-Alt substitute for AltGr. Turning this off may resolve collisions with Readline's key bindings. |
Note:
Some settings have alternative default values when Clink is installed with "Use enhanced default settings" checked in the setup program. This enables more of Clink's enhancements by default.
Compatibility Notes:
- The
esc_clears_line
setting has been replaced by aclink-reset-line
command that is by default bound to the Escape key. See Customizing Key Bindings for more information.- The
match_colour
setting has been removed, and Clink now supports Readline's completion coloring. See Completion Colors for more information.
.Color Settings up top
This section describes how to set a color.
For information on what color settings are available and how they're used, see the Coloring the Input Text section and the color.* settings.
.Friendly Color Names up top
The Clink color settings are the ones whose names begin with color.
. Color settings use the following syntax:
[attributes] [foreground_color] [on [background_color]]
Optional attributes (can be abbreviated to 3 letters):
bold
ornobold
adds or removes boldface (usually represented by forcing the color to use high intensity if it doesn't already; some terminal programs may also/instead use a bolder font weight).underline
adds an underline (some terminal programs cannot display underlines).italic
adds italics (some terminal programs cannot display italics). This keyword requires Clink v1.7.0 or newer; in older versions you can use thesgr
keyword with the corresponding escape code sequence such assgr 3
.reverse
swaps the foreground and background colors. This keyword requires Clink v1.7.0 or newer; in older versions you can use thesgr
keyword with the corresponding escape code sequence such assgr 7
.
Optional colors for foreground_color and background_color (can be abbreviated to 3 letters):
default
ornormal
uses the default color as defined by the current color theme in the console window.black
,red
,green
,yellow
,blue
,cyan
,magenta
,white
are the basic colors names.bright
can be combined with any of the other color names to make them bright (high intensity).#XXXXXX
specifies a color using 24-bit RGB hex format; the first two digits are the red value, the next two digits are the green value, and the last two digits are the blue value (some terminal programs cannot display 24-bit colors, and will try to instead use the closest supported color). Requires Clink v1.7.0 or newer; in older versions you can use thesgr
keyword with the corresponding escape code sequence such assgr 38;2;255;80;160
.#XXX
specifies a color using a short RGB hex format; each digit is doubled so#3fc
means#33ffcc
. Requires Clink v1.7.0 or newer; in older versions you can use thesgr
keyword with the corresponding escape code sequence such assgr 38;2;255;80;160
.
Examples (specific results may depend on the console host program):
bri yel
for bright yellow foreground on default background color.bold
for bright default foreground on default background color.underline bright black on white
for dark gray (bright black) foreground with underline on light gray (white) background.default on blue
for default foreground color on blue background.bold underline green on #222
for bright green with underline on a dark gray background.
.Alternative SGR Syntax up top
It's also possible to set any ANSI SGR escape code using sgr SGR_parameters
(for example sgr 7
is the code for reverse video, which swaps the foreground and background colors).
Be careful, since some escape code sequences might behave strangely.
.Color Themes up top
Clink has many color settings which can be set with clink set color.setting_name color_value
.
Predefined color setting values can be grouped into a .clinktheme file to make it easy to save, apply, and share different color themes for Clink. These color theme files require Clink v1.7.0 or newer.
Clink looks for color theme files in these directories:
- Any directories listed in the
%CLINK_THEMES_DIR%
environment variable (multiple directories may be separated by semicolons). - A
themes\
subdirectory under each scripts directory listed byclink info
(see Location of Lua Scripts). - A
themes\
subdirectory under the Clink program directory and the Clink profile directory. - Or you can provide a full path name to a file, such as
c:\mythemes\Colorful.clinktheme
.
To apply a color theme, run clink config theme use theme_name
which will apply the named theme and use it to replace color settings in the current Clink profile. Or set the CLINK_COLORTHEME
environment variable to the name or full path and filename of a .clinktheme file. The environment variable causes the named theme to override color settings from the profile's settings file, which allows multiple concurrent Clink sessions to use different color themes.
Note: The
clink config theme use
command first saves the current color theme as "Previous Theme" to help avoid accidentally losing color settings.
To list available color themes, run clink config theme list
. Clink includes a few theme files, and you can find more shared online by Clink users. One place to find more color themes for Clink is the clink-themes repo.
To show a demo of a what a color theme will look like, run clink config theme show theme_name
.
To save the current profile's color settings into a .clinktheme file, run clink config theme save theme_name
. The color settings are saved into a file named themes\theme_name.clinktheme
under the current Clink profile directory.
See Coloring the Input Text for information on specific color settings.
Note: The .clinktheme files are Clink color themes for Clink-specific color settings. They are not terminal color themes and don't affect other programs or the terminal in general. Consult your terminal program's documentation for how to set terminal color themes for it.
.Custom Prompts up top
You can choose a custom prompt to use, or you can make your own prompt.
A custom prompt can be packaged into a .clinkprompt file to make it easy to choose which prompt to use, and easy to share custom prompts with other users.
Clink looks for custom prompt files in these directories:
- Any directories listed in the
%CLINK_THEMES_DIR%
environment variable (multiple directories may be separated by semicolons). - A
themes\
subdirectory under each scripts directory listed byclink info
(see Location of Lua Scripts). - Or you can provide a full path name to a file, such as
c:\mythemes\Fancy Prompt.clinkprompt
.
To activate a custom prompt, run clink config prompt use prompt_name
which will load and use the named prompt, as well as update the settings accordingly in the current Clink profile. Or set the CLINK_CUSTOMPROMPT
environment variable to the name or full path and filename of a .clinkprompt file. The environment variable causes the named prompt to override the profile's settings file, and allows multiple concurrent Clink sessions to use different custom prompts.
To list available custom prompts, run clink config prompt list
. Clink includes a few custom prompt files, and you can find more shared online by Clink users. Some places you can find more custom prompts for Clink are clink-flex-prompt, clink-themes, and oh-my-posh. Check here for quick info on using oh-my-posh prompt themes with Clink.
To show a demo of what a custom prompt will look like, run clink config prompt show prompt_name
.
See Customizing the Prompt for information on writing your own custom prompts, and see Sharing Custom Prompts for information on optionally packaging them as "*.clinkprompt" files.
.Compatibility Between .clinkprompt Versus .lua Files up top
When you activate a .clinkprompt file via clink config prompt use
you might see a garbled prompt, or still see your old prompt.
That can happen because activating a .clinkprompt file deactivates other .clinkprompt files, but it doesn't deactivate prompt filters registered from .lua files (it could break other things if it did).
So, if you have a custom prompt in a .lua file then you may need to update the .lua file to disable itself while a .clinkprompt file is active.
For most .lua custom prompts, you can simply rename its file to change the file extension from ".lua" to ".clinkprompt", and then it won't interfere with other .clinkprompt files.
Or, you can modify any prompt filter to automatically disable itself like this:
local your_prompt_filter = clink.promptfilter()
function your_prompt_filter:filter()
-- Insert the following if..end line at the beginning of any .lua prompt filter to automatically
-- disable it while a .clinkprompt file is active (but don't insert it in a .clinkprompt file).
if clink.getclinkprompt and clink.getclinkprompt() then return end
-- The rest of your prompt filter goes here...
end
.File Locations up top
Settings and history are persisted to disk from session to session. By default Clink uses the current user's non-roaming application data directory. This user directory is usually found in one of the following locations;
- Windows XP:
c:\Documents and Settings\username\Local Settings\Application Data\clink
- Windows Vista onwards:
c:\Users\username\AppData\Local\clink
All of the above locations can be overridden using the --profile path
command line option which is specified when injecting Clink into cmd.exe using clink inject
. Or with the %CLINK_PROFILE%
environment variable if it is already present when Clink is injected (this envvar takes precedence over any other mechanism of specifying a profile directory, if more than one was used).
You can use clink info
to find the directories and configuration files for the current Clink session.
Also see Location of Lua Scripts for details on where Clink looks for Lua scripts, and Themes Directories for details on where Clink looks for color theme files (*.clinktheme) and custom prompt files (*.clinkprompt).
Notes:
- Clink performs tilde expansion on the
%CLINK_PROFILE%
environment variable value. If the path begins with~\
then it is replaced with the current user's home directory (%HOME%
or%HOMEDRIVE%%HOMEPATH%
or%USERPROFILE%
).- The
--profile
flag has a quirk for backward compatibility with older versions of Clink:~\
in--profile
is expanded to%LOCALAPPDATA%
instead.
.Overriding the profile directory when installed for Autorun up top
If you've installed Clink using the setup program with the "Autorun when cmd.exe starts" box checked, then the profile directory has been explicitly set to %LOCALAPPDATA%\clink
. That will take precedence over any other stored configuration.
You can override it via set CLINK_PROFILE=path
after starting cmd.exe.
Or you can use clink autorun install -- --profile path
to change which profile directory is specified (see clink autorun --help
and clink autorun show
).
Or if you want to use Autorun but also override the profile directory any of the usual ways, then run clink autorun uninstall
and then clink autorun install
. That will remove the explicit profile directory specification that was applied by the setup program.
.Files up top
The location of the clink_settings
file may also be overridden with the %CLINK_SETTINGS%
environment variable. This is not recommended because it can be confusing; if the environment variable gets cleared or isn't always set then a different settings file may get used sometimes. But, one reason to use it is to make your settings sync with other computers.
set CLINK_SETTINGS=%USERPROFILE%\OneDrive\clink
can let settings sync between computers through your OneDrive account.set CLINK_SETTINGS=%USERPROFILE%\AppData\Roaming
can let settings sync between computers in a work environment.
clink info
to find where it is located.
default_settings
file in either the profile directory or the binaries directory. Then it loads the clink_settings
file from the profile directory.
The default_settings
file can be useful for portable installations or when sharing your favorite Clink configuration with friends.
default_inputrc
file in either the profile directory or the binaries directory. Then it loads the .inputrc
file.
The default_inputrc
file can be useful for portable installations or when sharing your favorite Clink configuration with friends.
.Command Line Options up top
See
clink inject --help
for more information.Note: If the
--profile
path begins with~\
then it is replaced with the current user's home directory (%HOME%
or%HOMEDRIVE%%HOMEPATH%
or%USERPROFILE%
).
When Clink is installed for autorun, the automatic inject can be overridden by setting the
CLINK_NOAUTORUN
environment variable (to any value).See
clink autorun --help
for more information.clink set
by itself lists all settings and their values.clink set --describe
by itself lists all settings and their descriptions (instead of their values).clink set setting_name
describes the setting and shows its current value.clink set setting_name clear
resets the setting to its default value.clink set setting_name value
sets the setting to the specified value.
See
clink config prompt --help
or Custom Prompts for more information.
See
clink config theme --help
or Color Themes for more information.
The path is stored in the registry and applies to all installations of Clink, regardless where their config paths are, etc. This is intended to make it easy for package managers like Scoop to be able to install (and uninstall) scripts for use with Clink. See
clink installscripts --help
for more information.
clink installscripts
.
See clink uninstallscripts --help
for more information.
See
clink history --help
for more information.Also, Clink automatically defines
history
as an alias for clink history
.
Or
clink --version
shows just the version number.
.Automatic Updates up top
By default, Clink periodically and automatically checks for new versions. When an update is available, Clink prints a message on startup. To apply an update, run clink update
when convenient to do so.
The default interval between checks is 5 days, which means after Clink checks for an update it waits at least 5 days before checking again. You can control the frequency of update checks with clink set clink.update_interval days
, where days is the minimum number of days between checking for updates.
You can control what happens when an update is available by using clink set clink.autoupdate mode
, where mode is one of these:
Mode | Description |
---|---|
off |
Clink does not automatically check for updates, but you can use clink update or clink update --check to check for updates. |
check |
This is the default; Clink periodically checks for updates and prints a message when an update is available. |
prompt |
Clink periodically checks for updates and if one is available then it shows a window to prompt whether to install the update. |
auto |
Clink periodically checks for updates and also attempts to automatically install an update. If elevation is needed then it pops up a prompt window, otherwise it automatically installs the update. |
Notes:
- The auto-updater settings are stored in the profile, so different profiles can be configured differently for automatic updates.
- The updater does nothing if the Clink program files are readonly.
- The updater requires PowerShell, which is present by default in Windows 7 and higher.
- Clink v1.5.5 added
check
,prompt
, andauto
. Before that, onlyfalse
andtrue
were available (andtrue
behaved the same ascheck
).
.Portable Configuration up top
Sometimes it's useful to run Clink from a flash drive or from a network share, especially if you want to use Clink on someone else's computer.
Here's how you can set up a portable configuration for Clink:
- Put your Lua scripts and other tools in the same directory as the Clink executable files. For example fzf.exe, z.cmd, oh-my-posh.exe, starship.exe etc can all go in the same directory on a flash drive or network share.
- Make a batch file such as
portable.bat
that injects Clink using a specific profile directory.- On a flash drive, you can have a portable profile in a subdirectory under the Clink directory.
- On a network share, you'll want to copy some initial settings into a local profile directory (a profile directory on a network share will be slow).
- In any cmd.exe window on any computer, you can then run the
portable.bat
script to inject Clink and have all your favorite settings and key bindings work.
Here are some sample scripts:
.portable.bat (on a flash drive) up top
This sample script assumes the portable.bat script is in the Clink directory, and it uses a clink_portable
profile directory under the Clink directory.
@echo off
rem -- Do any other desired configuration here, such as loading a doskey macro file.
call "%~dp0clink.bat" inject --profile "%~dp0clink_portable" %1 %2 %3 %4 %5 %6 %7 %8 %9
.portable.bat (on a network share) up top
This sample script assumes the portable.bat script is in the Clink directory, and that there is a file portable_clink_settings
with the settings you want to copy to the local profile directory.
@echo off
if not exist "%TEMP%\clink_portable" md "%TEMP%\clink_portable" >nul
if not exist "%TEMP%\clink_portable\clink_settings" copy "%~dp0portable_clink_settings" "%TEMP%\clink_portable\clink_settings" >nul
rem -- Do any other desired configuration here, such as loading a doskey macro file.
call "%~dp0clink.bat" inject --profile "%TEMP%\clink_portable" %1 %2 %3 %4 %5 %6 %7 %8 %9
.Configuring Readline top
Clink uses the GNU Readline library to provide line editing functionality, which can be configured to add custom keybindings and macros by creating a Readline init file. The Clink documentation includes an updated and tailored copy of the Readline documentation, below.
The Basics | The basics of using the Readline input editor in Clink. |
Init File | About the .inputrc init file, configuration variables, and key bindings. |
Bindable Commands | The commands available for key bindings. |
Completion Colors | How to customize the completion colors. |
Popup Windows | Using the popup windows. |
.The Basics up top
.Bare Essentials up top
To enter characters into the line, simply type them. The typed character appears where the cursor was, and then the cursor moves one space to the right. If you mistype a character, you can use Backspace to back up and delete the mistyped character.
Sometimes you may mistype a character, and not notice the error until you have typed several other characters. In that case, you can type Left (the left arrow key) to move the cursor to the left, and then correct your mistake. Afterwards, you can move the cursor to the right with Right (the right arrow key).
When you add text in the middle of a line, you will notice that characters to the right of the cursor are "pushed over" to make room for the text that you have inserted. Likewise, when you delete text behind the cursor, characters to the right of the cursor are "pulled back" to fill in the blank space created by the removal of the text. A list of the bare essentials for editing the text of an input line follows.
Key | Description |
---|---|
Left | Move back one character. |
Right | Move forward one character. |
Backspace | Delete the character to the left of the cursor. |
Del | Delete the character underneath the cursor. |
A, a, 1, !, ", /, etc | Insert the typed character into the line at the cursor. |
Ctrl-z or Ctrl-x Ctrl-u |
Undo the last editing command. You can undo all the way back to an empty line. |
Home | Move to the start of the line. |
End | Move to the end of the line. |
Ctrl-Left | Move backward a word, where a word is composed of letters and digits. |
Ctrl-Right | Move forward a word. |
.Killing and Yanking up top
Killing text means to delete the text from the line, but to save it away for later use, usually by yanking (re-inserting) it back into the line. ("Cut" and "paste" are more recent jargon for "kill" and "yank", but killing and yanking do not affect the system's clipboard.)
If the description for a command says that it "kills" text, then you can be sure that you can get the text back in a different (or the same) place later.
When you use a kill command, the text is saved in a kill-ring. Any number of consecutive kills save all of the killed text together, so that when you yank it back, you get it all. The kill ring is not line specific; the text that you killed on a previously typed line is available to be yanked back later, when you are typing another line.
Here are some basic commands for killing text.
Key | Description |
---|---|
Ctrl-End | Kill the text from the current cursor position to the end of the line. |
Ctrl-Del | Kill from the cursor to the end of the current word, or, if between words, to the end of the next word. Word boundaries are the same as those used by Ctrl-Right. |
Ctrl-Backspace | Kill from the cursor the start of the current word, or, if between words, to the start of the previous word. Word boundaries are the same as those used by Ctrl-Left. |
Ctrl-w | Kill from the cursor to the previous whitespace. This is different than Ctrl-Backspace because the word boundaries differ. |
Here is how to yank the text back into the line. Yanking means to copy the most-recently-killed text from the kill buffer.
Key | Description |
---|---|
Ctrl-y | Yank the most recently killed text back into the buffer at the cursor. |
Alt-y | Rotate the kill-ring, and yank the new top. You can only do this if the prior command is Ctrl-y or Alt-y. |
.Readline Arguments up top
You can pass numeric arguments to Readline commands. Sometimes the argument acts as a repeat count, other times it is the sign of the argument that is significant. If you pass a negative argument to a command which normally acts in a forward direction, that command will act in a backward direction. For example, to kill text back to the start of the line, you might type Alt-- Ctrl-k.
The general way to pass numeric arguments to a command is to type meta digits before the command. If the first "digit" typed is a minus sign (-
), then the sign of the argument will be negative. Once you have typed one meta digit to get the argument started, you can type the remainder of the digits, and then the command. For example, to give the Del command an argument of 10, you could type Alt-1 0 Del, which will delete the next ten characters on the input line.
.Searching for Commands in the History up top
Readline provides commands for searching through the command history for lines containing a specified string. There are two search modes: incremental and non-incremental.
Incremental searches begin before the user has finished typing the search string. As each character of the search string is typed, Readline displays the next entry from the history matching the string typed so far. An incremental search requires only as many characters as needed to find the desired history entry. To search backward in the history for a particular string, type Ctrl-r. Typing Ctrl-s searches forward through the history. The characters present in the value of the isearch-terminators
variable are used to terminate an incremental search. If that variable has not been assigned a value, then Esc or Ctrl-j will terminate an incremental search. Ctrl-g will abort an incremental search and restore the original line. When the search is terminated, the history entry containing the search string becomes the current line.
To find other matching entries in the history list, type Ctrl-r or Ctrl-s as appropriate. This will search backward or forward in the history for the next entry matching the search string typed so far. Any other key sequence bound to a Readline command will terminate the search and execute that command. For instance, Enter will terminate the search and accept the line, thereby executing the command from the history list. A movement command will terminate the search, make the last line found the current line, and begin editing.
Readline remembers the last incremental search string. If two Ctrl-r's are typed without any intervening characters defining a new search string, any remembered search string is used.
Non-incremental searches read the entire search string before starting to search for matching history lines. The search string may be typed by the user or be part of the contents of the current line. Type Alt-p or Alt-n to start a non-incremental search backwards or forwards.
To search backward in the history for a line starting with the text before the cursor, type PgUp. Or search forward by typing PgDn.
See Saved Command History for more information on how history works.
.Init File up top
You can customize key bindings and configuration variables by using an init file.
"Configuration variables" are customized in the init file, but "Clink settings" are customized with the clink set
command.
.Init File Location up top
The Readline init file is named .inputrc
or _inputrc
. Clink searches the directories referenced by the following environment variables in the order listed here, and loads the first .inputrc
or _inputrc
file it finds:
%CLINK_INPUTRC%
- The Clink profile directory (see the "state" line from
clink info
; by default this is the same as%USERPROFILE%
but it can be overridden by theclink inject
command). %USERPROFILE%
%LOCALAPPDATA%
%APPDATA%
%HOME%
or%HOMEDRIVE%%HOMEPATH%
Other software that also uses the Readline library will also look for the .inputrc
file (and possibly the _inputrc
file too). To set macros and keybindings intended only for Clink, one can use the Readline init file conditional construct like this; $if clink [...] $endif
.
You can use clink info
to find the directories and configuration file for the current Clink session.
Compatibility Notes:
- The
clink_inputrc_base
file from v0.4.8 is no longer used.- For backward compatibility,
clink_inputrc
is also loaded from the above locations, but it has been deprecated and may be removed in the future.- Clink v1.0.0a0 through Clink v1.2.27 accidentally loaded up to one Readline init file from each of the searched directories. That was incorrect behavior for loading Readline init files and has been fixed. If similar behavior is still desired, consider using the
$include
directive in the Readline init file, to load additional files.
.Init File Syntax up top
There are only a few basic constructs allowed in the Readline init file:
- Blank lines are ignored.
- Lines beginning with a
#
are comments. - Lines beginning with a
$
indicate conditional init constructs. - Other lines denote Readline configuration variables and Readline key bindings.
.Readline configuration variables up top
You can modify the behavior of Readline by altering the values of configuration variables in Readline using the set
command within the init file. The syntax is simple:
set variable value
Here, for example, is how to change from the default Emacs-like key binding to use vi
line editing commands:
set editing-mode vi
Variable names and values, where appropriate, are recognized without regard to case. Unrecognized variable names are ignored.
Boolean variables (those that can be set to on or off) are set to on if the value is null or empty, on
(case-insensitive), or 1
. Any other value results in the variable being set to off.
Variable | Description |
---|---|
.active-region-end-color |
Not used or needed in Clink; exists only for compatibility when parsing the configuration file. |
.active-region-start-color |
A string variable that controls the text color and background when displaying the text in the active region (see enable-active-region below). This string must not take up any physical character positions on the display, so it should consist only of terminal escape sequences. It is output to the terminal before displaying the text in the active region. The default value is "\e[0;7m" (reverse video). |
.bell-style |
Controls what happens when Readline wants to ring the terminal bell. If set to "none", Readline never rings the bell. If set to "visible" (the default in Clink), Readline uses a visible bell if one is available. If set to "audible", Readline attempts to ring the terminal's bell. |
.blink-matching-paren |
If set to "on", Readline attempts to briefly move the cursor to an opening parenthesis when a closing parenthesis is inserted. The default is "off". |
.colored-completion-prefix |
If set to "on", when listing completions, Readline displays the common prefix of the set of possible completions using a different color. The color definitions are taken from the value of the %LS_COLORS% environment variable. The default is "off". |
.colored-stats |
If set to "on", Readline displays possible completions using different colors to indicate their file type. The color definitions are determined as described in Completion Colors. The default is "off", but is automatically overridden by the match.coloring_rules setting or the %CLINK_MATCH_COLORS environment variable. |
.comment-begin |
The string to insert at the beginning of the line when the insert-comment command is executed. The default value is "::". |
.completion-display-width |
The number of screen columns used to display possible matches when performing completion. The value is ignored if it is less than 0 or greater than the terminal screen width. A value of 0 will cause matches to be displayed one per line. The default value is -1. |
.completion-ignore-case |
If set to "on", Readline performs filename matching and completion in a case-insensitive fashion. The default value is "on". |
.completion-prefix-display-length |
The length in characters of the common prefix of a list of possible completions that is displayed without modification. When set to a value greater than zero, common prefixes longer than this value are replaced with an ellipsis when displaying possible completions. |
.completion-query-items |
The number of possible completions that determines when the user is asked whether the list of possibilities should be displayed. If the number of possible completions is greater than or equal to this value, Readline will ask whether or not the user wishes to view them; otherwise, they are simply listed. This variable must be set to an integer value greater than or equal to 0. A negative value means Readline should never ask. The default limit is 100. |
.echo-control-characters |
When set to "on", on operating systems that indicate they support it, readline echoes a character corresponding to a signal generated from the keyboard. The default is "on". |
.editing-mode |
This controls which Readline input mode is used by default. When set to "emacs" (the default), Readline starts up in Emacs editing mode, where keystrokes are most similar to Emacs. When set to "vi", then vi input mode is used. |
.emacs-mode-string |
If the show-mode-in-prompt variable is enabled, this string is displayed immediately before the last line of the primary prompt when emacs editing mode is active. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. Use the "\1" and "\2" escapes to begin and end sequences of non-printing characters, which can be used to embed a terminal control sequence into the mode string. The default is "@". |
.enable-active-region |
The point is the current cursor position, and mark refers to a saved cursor position (see Commands For Moving and Some Miscellaneous Commands). The text between the point and mark is referred to as the region. When this variable is set to "on", Readline allows certain commands to designate the region as active. When the region is active, Readline highlights the text in the region using the value of the active-region-start-color , which defaults to reverse video ("\e[0;7m"). The active region shows the text inserted by bracketed-paste and any matching text found by incremental and non-incremental history searches. The default is "on". |
.expand-tilde |
If set to "on", tilde expansion is performed when Readline attempts word completion. The default is "off". |
.history-preserve-point |
If set to "on", the history code attempts to place the point (the current cursor position) at the same location on each history line retrieved with previous-history or next-history . The default is "off". |
.horizontal-scroll-mode |
This variable can be set to either "on" or "off". Setting it to "on" means that the text of the lines being edited will scroll horizontally on a single screen line when they are longer than the width of the screen, instead of wrapping onto a new screen line. This variable is automatically set to "on" for terminals of height 1. By default, this variable is set to "off". |
.isearch-terminators |
The string of characters that should terminate an incremental search without subsequently executing the character as a command (see Searching for Commands in the History). If this variable has not been given a value, the characters Esc and Ctrl-j will terminate an incremental search. |
.keymap |
Sets Readline's idea of the current keymap for key binding commands. Built-in keymap names are emacs , emacs-standard , emacs-meta , emacs-ctlx , vi , vi-move , vi-command , and vi-insert . vi is equivalent to vi-command (vi-move is also a synonym); emacs is equivalent to emacs-standard . The default value is emacs . The value of the editing-mode variable also affects the default keymap. |
.mark-directories |
If set to "on", completed directory names have a slash appended. The default is "on". |
.mark-modified-lines |
This variable, when set to "on", causes Readline to display an asterisk (* ) at the start of history lines which have been modified. This variable is "off" by default. |
.mark-symlinked-directories |
If set to "on", completed names which are symbolic links to directories have a slash appended (subject to the value of mark-directories ). The default is "off". |
.match-hidden-files |
This variable, when set to "on", causes Readline to match files whose names begin with a . (hidden files on Unix and Linux) when performing filename completion. If set to "off", the leading . must be supplied by the user in the filename to be completed. This variable is "on" by default. |
.menu-complete-display-prefix |
If set to "on", menu completion displays the common prefix of the list of possible completions (which may be empty) before cycling through the list. The default is "off". |
.page-completions |
If set to "on", Readline uses an internal more -like pager to display a screenful of possible completions at a time. This variable is "on" by default. |
.print-completions-horizontally |
If set to "on", Readline will display completions with matches sorted horizontally in alphabetical order, rather than down the screen. The default is "off". |
.show-all-if-ambiguous |
This alters the default behavior of the completion functions. If set to "on", words which have more than one possible completion cause the matches to be listed immediately instead of ringing the bell. The default value is "off". |
.show-all-if-unmodified |
This alters the default behavior of the completion functions in a fashion similar to show-all-if-ambiguous . If set to "on", words which have more than one possible completion without any possible partial completion (the possible completions don't share a common prefix) cause the matches to be listed immediately instead of ringing the bell. The default value is "off". |
.show-mode-in-prompt |
If set to "on", add a string to the beginning of the prompt indicating the editing mode: emacs, vi command, or vi insertion. The mode strings are user-settable (e.g., emacs-mode-string ). The default value is "off". |
.skip-completed-text |
If set to "on", this alters the default completion behavior when inserting a single match into the line. It's only active when performing completion in the middle of a word. If enabled, Readline does not insert characters from the completion that match characters after point (the cursor position) in the word being completed, so portions of the word following the cursor are not duplicated. For instance, if this is enabled, attempting completion when the cursor is after the e in "Makefile" will result in "Makefile" rather than "Makefilefile", assuming there is a single possible completion. The default value is "off". |
.vi-cmd-mode-string |
If the show-mode-in-prompt variable is enabled, this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in command mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. Use the "\1" and "\2" escapes to begin and end sequences of non-printing characters, which can be used to embed a terminal control sequence into the mode string. The default is "(cmd)". |
.vi-ins-mode-string |
If the show-mode-in-prompt variable is enabled, this string is displayed immediately before the last line of the primary prompt when vi editing mode is active and in insertion mode. The value is expanded like a key binding, so the standard set of meta- and control prefixes and backslash escape sequences is available. Use the "\1" and "\2" escapes to begin and end sequences of non-printing characters, which can be used to embed a terminal control sequence into the mode string. The default is "(ins)". |
.visible-stats |
If set to "on", a character denoting a file's type is appended to the filename when listing possible completions. The default is "off". |
Clink adds some new configuration variables for Readline:
Variable | Description |
---|---|
.completion-auto-query-items |
If set to "on", automatically prompts before displaying completions if they won't fit without scrolling (this overrules the completion-query-items variable). The default is "on". |
.history-point-at-end-of-anchored-search |
If set to "on", this puts the cursor at the end of the line when using history-search-forward or history-search-backward . The default is "off". |
.menu-complete-wraparound |
If this is "on", the menu-complete family of commands wraps around when reaching the end of the possible completions. The default is "on". |
.search-ignore-case |
Controls whether the history search commands ignore case. The default is "on". |
Some configuration variables are deprecated in Clink:
Variable | Description |
---|---|
.bind-tty-special-chars |
Clink doesn't need or use this. |
.completion-map-case |
Instead, use the match.ignore_case Clink setting (see the relaxed mode). |
.convert-meta |
Clink requires this to be "on", and sets it to "on". |
.disable-completion |
If set to "on", Readline will inhibit word completion. Completion characters will be inserted into the line as if they had been mapped to self-insert . The default is "off". |
.enable-bracketed-paste |
Clink doesn't support this. Instead use the [`clink-paste``](#rlcmd-clink-paste) command to perform the equivalent of a bracketed paste. |
.enable-meta-key |
Clink requires this to be "on", and sets it to "on". |
.history-size |
Instead, use the history.max_lines Clink setting. |
.input-meta |
Clink requires this to be "on", and sets it to "on". |
.keyseq-timeout |
Clink does not support this. |
.output-meta |
Clink requires this to be "on", and sets it to "on". |
.revert-all-at-newline |
Clink always reverts all in-memory changes to history lines each time a new input prompt starts. |
.Readline key bindings up top
The syntax for controlling key bindings in the init file is simple. First you need to find the name of the command that you want to change. The following sections contain tables of the command name, the default keybinding, if any, and a short description of what the command does (see Bindable Commands).
Once you know the name of the command, simply place on a line in the init file the name of the key you wish to bind the command to, a colon, and then the name of the command. There can be no space between the key name and the colon (any space will be interpreted as part of the key name). The name of the key can be expressed in different ways, depending on what you find most comfortable.
In addition to command names, Readline allows keys to be bound to a string that is inserted when the key is pressed (a macro).
Line | Description |
---|---|
keyname: command | Binds a named command to a key. |
keyname: "literal text" | Binds a macro to a key. A macro inserts the literal text into the input line. |
keyname: "luafunc:lua_function_name" | Binds a named Lua function to a key. See Lua key bindings for more information. |
Names can be used to refer to simple keys like Space
, Return
, Tab
, letters and digits (A
, b
, 1
, ...), and most punctuation (!
, @
, .
, _
, ...). Names can also include modifier prefixes C-
or Control-
for the Ctrl key, or M-
or Meta-
for the Meta or Alt key. However, modifier prefixes don't work with simple key names; you can't use C-Space
, instead a sequence is needed for special keys like that.
Sequences are surrounded by double quotes, and specify an entire sequence of input characters. Some special escape codes can be used:
Code | Description |
---|---|
\C- |
Prefix meaning Ctrl. |
\M- |
Prefix meaning Meta or Alt. |
\e |
The literal ESC (escape) character code, which is the first character code in most special key sequences. Note: the ESC code isn't necessarily the same as the Esc key; see terminal.raw_esc . |
\\ |
Backslash. |
\" |
" , a double quotation mark. |
\' |
' , a single quote or apostrophe. |
\a |
Alert (bell). |
\b |
Backspace. |
\d |
Delete. (Note: this is not very useful for Clink; it is not the Del key.) |
\f |
Form feed. |
\n |
Newline. |
\r |
Carriage return. |
\t |
Horizontal tab. |
\v |
Vertical tab. |
\nnn |
The eight-bit character whose value is the octal value nnn (one to three digits) |
\xHH |
The eight-bit character whose value is the hexadecimal value HH (one or two hex digits) |
Here are some examples to illustrate the differences between names and sequences:
Name | Sequence | Description |
---|---|---|
C-a |
"\C-a" |
Both refer to Ctrl-a. |
M-a |
"\M-a" |
Both refer to Alt-a. |
M-C-a |
"\M-\C-a" |
Both refer to Alt-Ctrl-a. |
hello |
It's just h. It is not quoted, so it is a name. The ello part is a syntax error and is silently discarded by Readline. |
|
"hello" |
The series of five keys h e l l o. | |
Space |
The Space key. | |
"Space" |
The series of five keys S p a c e. |
Special keys like Up are represented by VT220 escape codes such as "\e[A"
. See Discovering Clink key sequences and Binding special keys for how to find the keyname for the key you want to bind.
blah-blah
binds to a function named "blah-blah"."blah-blah"
is a macro that inserts the literal text "blah-blah" into the line.
When entering the text of a macro, single or double quotes must be used to indicate a macro definition. Unquoted text is assumed to be a function name. In the macro body, the backslash escapes described above are expanded. Backslash will quote any other character in the macro text, including "
and '
. For example, the following binding will make pressing Ctrl-x \ insert a single \
into the line:
"\C-x\\": "\\"
# Using key names.
C-u: universal-argument # Bind Ctrl-u to invoke the universal-argument command.
C-o: "> output" # Bind Ctrl-o to insert the text "> output" into the line.
# Using key sequences.
"\C-u": universal-argument # Bind Ctrl-u to invoke the universal-argument command.
"\C-x\C-r": clink-reload # Bind Ctrl-x,Ctrl-r to reload the configuration and Lua scripts for Clink.
"\eOP": clink-popup-show-help # Bind F1 to invoke the clink-popup-show-help command.
See Customizing Key Bindings for more information about binding keys in Clink.
.Conditional init constructs up top
Readline implements a facility similar in spirit to the conditional compilation features of the C preprocessor which allows key bindings and variable settings to be performed as the result of tests. There are four parser directives used.
The $if
construct allows bindings to be made based on the editing mode, the terminal being used, or the application using Readline. The text of the test, after any comparison operator, extends to the end of the line; unless otherwise noted, no characters are required to isolate it.
The $if mode=
form of the $if
directive is used to test whether Readline is in emacs
or vi
mode. This may be used in conjunction with the "set keymap" command, for instance, to set bindings in the emacs-standard
and emacs-ctlx
keymaps only if Readline is starting out in emacs
mode. (The directive is only tested during startup.)
$if mode == emacs
set show-mode-in-prompt on
$endif
The $if term=
form may be used to include terminal-specific key bindings, perhaps to bind the key sequences output by the terminal's function keys. The word on the right side of the "=" is tested against both the full name of the terminal and the portion of the terminal name before the first "-". This allows sun
to match both sun
and sun-cmd
, for instance. This is not useful with Clink, because Clink has its own terminal driver.
The $if version
test may be used to perform comparisons against specific Readline versions. The version
expands to the current Readline version. The set of comparison operators includes =
(and ==
), !=
, <=
, >=
, <
, and >
. The version number supplied on the right side of the operator consists of a major version number, an optional decimal point, and an optional minor version (e.g., "7.1"). If the minor version is omitted, it is assumed to be "0". The operator may be separated from the string version
and from the version number argument by whitespace. The following example sets a variable if the Readline version being used is 7.0 or newer:
$if version >= 7.0
set show-mode-in-prompt on
$endif
The $if clink
construct is used to include Clink-specific settings. For instance, the following command adds a key sequence that quotes the current or previous word, but only in Clink:
$if clink
# Quote the current or previous word
"\C-xq": "\eb\"\ef\""
$endif
The $if clink_version
test may be used to perform comparisons against specific Clink versions. The clink_version
expands to the current Clink version. The set of comparison operators includes =
(and ==
), !=
, <=
, >=
, <
, and >
. The version number supplied on the right side of the operator consists of a major version number, an optional decimal point and minor version, and an optional decimal point and patch version (e.g., "1.6" or "1.6.2"). If the minor or patch versions are omitted, they are assumed to be "0". The operator may be separated from the string clink_version
and from the version number argument by whitespace. In other applications that use Readline (such as bash
) or in versions of Clink before v1.6.1, the test is always false. The following example sets a key binding if the Clink version being used is 1.6.1 or newer:
$if clink_version >= 1.6.1
"\C-x\C-f": clink-dump-functions # This function doesn't exist before Clink 1.6.1,
# and would print an error in older versions.
$endif
The $if variable
construct provides simple equality tests for Readline variables and values. The permitted comparison operators are =
, ==
, and !=
. The variable name must be separated from the comparison operator by whitespace; the operator may be separated from the value on the right hand side by whitespace. Both string and boolean variables may be tested. Boolean variables must be tested against the values on and off. The following example is equivalent to the mode=emacs
test described above:
$if editing-mode == emacs
set show-mode-in-prompt on
$endif
This command, as seen in the previous example, terminates an $if
command.
Commands in this branch of the $if
directive are executed if the test fails.
This directive takes a single filename as an argument and reads commands and bindings from that file. For example, the following directive reads from "c:\dir\inputrc":
$include c:\dir\inputrc
.Sample .inputrc file up top
Here is a sample .inputrc
file with some of the variables and key bindings that I use:
$if clink # begin clink-only section
set colored-completion-prefix on
set colored-stats on
set mark-symlinked-directories on
set visible-stats off
set completion-auto-query-items on
set history-point-at-end-of-anchored-search on
set menu-complete-wraparound off
set search-ignore-case on
# The following key bindings are for emacs mode.
set keymap emacs
"\e[27;8;72~": clink-popup-show-help # Alt-Ctrl-Shift-H
# Completion key bindings.
"\t": old-menu-complete # Tab
"\e[Z": old-menu-complete-backward # Shift-Tab
"\e[27;5;32~": clink-select-complete # Ctrl-Space
# Some key bindings I got used to from 4Dos/4NT/Take Command.
C-b: # Ctrl-B (cleared because I redefined Ctrl-F)
C-d: remove-history # Ctrl-D (replaces `delete-char`)
C-f: clink-expand-doskey-alias # Ctrl-F (replaces `forward-char`)
C-k: add-history # Ctrl-K (replaces `kill-line`)
"\e[A": history-search-backward # Up (replaces `previous-history`)
"\e[B": history-search-forward # Down (replaces `next-history`)
"\e[5~": clink-popup-history # PgUp (replaces `history-search-backward`)
"\e[6~": # PgDn (cleared because I redefined PgUp)
"\e[1;5F": end-of-line # Ctrl-End (replaces `kill-line`)
"\e[1;5H": beginning-of-line # Ctrl-Home (replaces `backward-kill-line`)
# Some key bindings handy in default (conhost) console windows.
M-b: # Alt-B (cleared because I redefined Alt-F)
M-f: clink-find-conhost # Alt-F for "Find..." from the console's system menu
M-m: clink-mark-conhost # Alt-M for "Mark" from the console's system menu
# Some key bindings for interrogating the Readline configuration.
"\C-x\C-f": dump-functions # Ctrl-X, Ctrl-F
"\C-x\C-m": dump-macros # Ctrl-X, Ctrl-M
"\C-x\C-v": dump-variables # Ctrl-X, Ctrl-V
# Misc other key bindings.
"\e[27;2;32~": clink-magic-suggest-space # Shift-Space
"\e[5;6~": clink-popup-directories # Ctrl-Shift-PgUp
C-_: kill-line # Ctrl-- (replaces `undo`)
$endif # end clink-only section
.Bindable Commands up top
Commands For Moving | Common commands for moving the cursor in the command line. |
Commands For Manipulating The History | Common commands for using the command history list. |
Commands For Changing Text | Common commands for deleting and inserting text. |
Killing And Yanking | Commands for using the "kill ring" (Readline's version of a clipboard). |
Specifying Numeric Arguments | Commands for inputing numeric arguments to other Readline commands. |
Completion Commands | Common completion commands. |
Keyboard Macros | Commands for using keyboard macros. |
Some Miscellaneous Commands | Some commands that aren't commonly used. |
Readline vi Mode | Commands for toggling vi mode. |
Other Readline Commands | Commands that exist only for .inputrc compatibility with the bash shell. |
Clink Commands | Clink adds many new and enhanced commands beyond the basic Readline commands. |
.Commands For Moving up top
Command | Key | Description |
---|---|---|
.beginning-of-line |
Home | Move to the start of the current line. |
.end-of-line |
End | Move to the end of the line, or insert suggestion. |
.forward-char |
Right * | Move forward a character, or insert suggestion. |
.backward-char |
Left | Move back a character. |
.forward-word |
Ctrl-Right | Move forward to the end of the next word, or insert next suggested word. |
.backward-word |
Ctrl-Left | Move back to the start of the current or previous word. |
.previous-screen-line |
Attempt to move point to the same physical screen column on the previous physical screen line. This will not have the desired effect if the current Readline line does not take up more than one physical line or if point is not greater than the length of the prompt plus the screen width. | |
.next-screen-line |
Attempt to move point to the same physical screen column on the next physical screen line. This will not have the desired effect if the current Readline line does not take up more than one physical line or if the length of the current Readline line is not greater than the length of the prompt plus the screen width. | |
.clear-display |
Alt-Ctrl-l | Clear the terminal screen and the terminal's scrollback buffer (if possible), then redraw the current line, leaving the current line at the top of the screen. |
.clear-screen |
Ctrl-l | Clear the terminal screen, then redraw the current line, leaving the current line at the top of the screen. |
.Commands For Manipulating The History up top
Command | Key | Description |
---|---|---|
.accept-line |
Enter | Accept the input line regardless of where the cursor is. The line may be added to the history list for future recall. |
.previous-history |
Ctrl-p | Move "back" through the history list, fetching the previous command. |
.next-history |
Ctrl-n | Move "forward" through the history list, fetching the next command. |
.beginning-of-history |
Alt-< | Move to the first line in the history. |
.end-of-history |
Alt-> | Move to the end of the input history, i.e. the line currently being entered. |
.reverse-search-history |
Ctrl-r | Search backward starting at the current line and moving "up" through the history as necessary. This is an incremental search. This command sets the region to the matched text and activates the mark. |
.forward-search-history |
Ctrl-s | Search forward starting at the current line and moving "down" through the history as necessary. This is an incremental search. This command sets the region to the matched text and activates the mark. |
.non-incremental-reverse-search-history |
Alt-p | Search backward starting at the current line and moving "up" through the history as necessary using a non-incremental search for a string supplied by the user. The search string may match anywhere in a history line. |
.non-incremental-forward-search-history |
Alt-n | Search forward starting at the current line and moving "down" through the history as necessary using a non-incremental search for a string supplied by the user. The search string may match anywhere in a history line. |
.history-search-forward |
PgDn | Search forward through the history for the string of characters between the start of the current line and the point. The search string must match at the beginning of a history line. This is a non-incremental search. |
.history-search-backward |
PgUp | Search backward through the history for the string of characters between the start of the current line and the point. The search string must match at the beginning of a history line. This is a non-incremental search. |
.history-substring-search-forward |
Search forward through the history for the string of characters between the start of the current line and the point. The search string may match anywhere in a history line. This is a non-incremental search. By default, this command is unbound. | |
.history-substring-search-backward |
Search backward through the history for the string of characters between the start of the current line and the point. The search string may match anywhere in a history line. This is a non-incremental search. By default, this command is unbound. | |
.yank-nth-arg |
Alt-Ctrl-y | Insert the first argument to the previous command (usually the second word on the previous line) at point. With an argument n, insert the n-th word from the previous command (the words in the previous command begin with word 0). A negative argument inserts the n-th word from the end of the previous command. Once the argument n is computed, the argument is extracted as if the "!n" history expansion had been specified. |
.yank-last-arg |
Alt-. or Alt-_ | Insert last argument to the previous command (the last word of the previous history entry). With a numeric argument, behave exactly like yank-nth-arg . Successive calls to yank-last-arg move back through the history list, inserting the last word (or the word specified by the argument to the first call) of each line in turn. Any numeric argument supplied to these successive calls determines the direction to move through the history. A negative argument switches the direction through the history (back or forward). The history expansion facilities are used to extract the last argument, as if the "!$" history expansion had been specified. |
.operate-and-get-next |
Ctrl-o | Accept the current line for return to the calling application as if a newline had been entered, and fetch the next line relative to the current line from the history for editing. A numeric argument, if supplied, specifies the history entry to use instead of the current line. |
.fetch-history |
With a numeric argument, fetch that entry from the history list and make it the current line. Without an argument, move back to the first entry in the history list. |
.Commands For Changing Text up top
Command | Key | Description |
---|---|---|
.delete-char |
Ctrl-d | Delete the character at point. Note: also see the cmd.ctrld_exits Clink setting. |
.backward-delete-char |
Backspace | Delete the character behind the cursor. A numeric argument means to kill the characters instead of deleting them. |
.forward-backward-delete-char |
Delete the character under the cursor, unless the cursor is at the end of the line, in which case the character behind the cursor is deleted. | |
.quoted-insert |
Ctrl-q | Add the next character typed to the line verbatim. This is how to insert key sequences like Ctrl-h or Esc, for example. |
.self-insert |
a, b, A, 1, !, etc | Insert the key itself. |
.transpose-chars |
Ctrl-t | Drag the character before the cursor forward over the character at the cursor, moving the cursor forward as well. If the insertion point is at the end of the line, then this transposes the last two characters of the line. Negative arguments have no effect. |
.transpose-words |
Alt-t | Drag the word before point past the word after point, moving point past that word as well. If the insertion point is at the end of the line, this transposes the last two words on the line. |
.upcase-word |
Alt-u | Uppercase the current (or following) word. With a negative argument, uppercase the previous word, but do not move the cursor. |
.downcase-word |
Alt-l | Lowercase the current (or following) word. With a negative argument, lowercase the previous word, but do not move the cursor. |
.capitalize-word |
Capitalize the current (or following) word. With a negative argument, capitalize the previous word, but do not move the cursor. | |
.overwrite-mode |
Ins | Toggle overwrite mode. With an explicit positive numeric argument, switches to overwrite mode. With an explicit non-positive numeric argument, switches to insert mode. This command affects only emacs mode; vi mode does overwrite differently. Each new command line prompt starts in insert mode. In overwrite mode, characters bound to self-insert replace the text at point rather than pushing the text to the right. Characters bound to backward-delete-char replace the character before point with a space. |
.Killing And Yanking up top
Command | Key | Description |
---|---|---|
.kill-line |
Ctrl-End | Kill the text from point to the end of the line. With a negative numeric argument, kill backward from the cursor to the beginning of the current line. |
.backward-kill-line |
Ctrl-Home | Kill backward from the cursor to the beginning of the current line. With a negative numeric argument, kill forward from the cursor to the end of the current line. |
.unix-line-discard |
Ctrl-u | Kill backward from the cursor to the beginning of the current line. |
.kill-whole-line |
Kill all characters on the current line, no matter where point is. | |
.kill-word |
Ctrl-Del | Kill from point to the end of the current word, or if between words, to the end of the next word. Word boundaries are the same as forward-word . |
.backward-kill-word |
Ctrl-Backspace | Kill the word behind point. Word boundaries are the same as backward-word . |
.unix-word-rubout |
Ctrl-w | Kill the word behind the cursor point, using white space as a word boundary. The killed text is saved on the kill-ring. |
.unix-filename-rubout |
Kill the word behind point, using white space and the slash character as the word boundaries. The killed text is saved on the kill-ring. | |
.delete-horizontal-space |
Delete all spaces and tabs around point. | |
.kill-region |
Kill the text in the current region. | |
.copy-region-as-kill |
Copy the text in the region to the kill buffer, so it can be yanked right away. | |
.copy-backward-word |
Copy the word before point to the kill buffer. The word boundaries are the same as backward-word . |
|
.copy-forward-word |
Copy the word following point to the kill buffer. The word boundaries are the same as forward-word . |
|
.yank |
Ctrl-y | Yank the top of the kill ring into the buffer at the cursor point. |
.yank-pop |
Alt-y | Rotate the kill-ring and yank the new top; but only if the prior command is yank or yank-pop . |
.Specifying Numeric Arguments up top
Command | Key | Description |
---|---|---|
.digit-argument |
Alt-digit or Alt-- | Add this digit to the argument already accumulating, or start a new argument. Alt-- starts a negative argument. |
.universal-argument |
This is another way to specify an argument. If this command is followed by one or more digits, optionally with a leading minus sign, those digits define the argument. If the command is followed by digits, executing universal-argument again ends the numeric argument, but is otherwise ignored. As a special case, if this command is immediately followed by a character that is neither a digit nor minus sign, the argument count for the next command is multiplied by four. The argument count is initially one, so executing this function the first time makes the argument count four, a second time makes the argument count sixteen, and so on. By default, this is not bound to a key. |
.Completion Commands up top
Command | Key | Description |
---|---|---|
.complete |
Tab * | Attempt to perform completion on the text before point. |
.possible-completions |
Alt-= | List the possible completions of the text before point. When displaying completions, Readline sets the number of columns used for display to the value of completion-display-width , the value of the environment variable %COLUMNS% , or the screen width, in that order. |
.insert-completions |
Alt-* | Insert all completions of the text before point that would have been generated by possible-completions . |
.menu-complete |
Similar to complete , but replaces the word to be completed with a single match from the list of possible completions. Repeated execution of menu-complete steps through the list of possible completions, inserting each match in turn. At the end of the list of completions, the bell is rung (subject to the setting of bell-style ) and the original text is restored. An argument of n moves n positions forward in the list of matches; a negative argument may be used to move backward through the list. This command is intended to be bound to Tab, but is unbound by default. |
|
.menu-complete-backward |
Identical to menu-complete , but moves backward through the list of possible completions, as if menu-complete had been given a negative argument. |
|
.old-menu-complete |
* | Similar to menu-complete but isn't limited by completion-query-items and doesn't include the common prefix of the possible completions. This behaves like the default completion in cmd.exe on Windows. When Clink is installed using the setup program with the "Autorun when cmd.exe starts" box checked or when clink.default_bindings is set to windows , then this is bound by default to Tab. |
.delete-char-or-list |
Deletes the character under the cursor if not at the beginning or end of the line (like delete-char ). If at the end of the line, behaves identically to possible-completions . |
.Keyboard Macros up top
Command | Key | Description |
---|---|---|
.start-kbd-macro |
Ctrl-x ( | Begin saving the characters typed into the current keyboard macro. |
.end-kbd-macro |
Ctrl-x ) | Stop saving the characters typed into the current keyboard macro and save the definition. |
.call-last-kbd-macro |
Ctrl-x e | Re-execute the last keyboard macro defined, by making the characters in the macro appear as if typed at the keyboard. |
.print-last-kbd-macro |
Print the last keboard macro defined in a format suitable for the inputrc file. |
.Some Miscellaneous Commands up top
Command | Key | Description |
---|---|---|
.re-read-init-file |
Read in the contents of the inputrc file, and incorporate any bindings or variable assignments found there. In Clink clink-reload is preferred since it also reloads Lua scripts. |
|
.abort |
Ctrl-g | Abort the current editing command and ring the terminal's bell (subject to the setting of bell-style ). |
.do-lowercase-version |
Alt-X, etc | If the key X is an upper case letter, run the command that is bound to the corresponding Alt-x lower case letter. The behavior is undefined if x is already lower case. |
.undo |
Ctrl-z or Ctrl-_ | Incremental undo, separately remembered for each line. |
.revert-line |
Alt-r | Undo all changes made to this line. This is like executing the undo command enough times to get back to the beginning. |
.tilde-expand |
Alt-~ | Perform tilde expansion on the current word. |
.set-mark |
Ctrl-@ | Set the mark to the point. If a numeric argument is supplied, the mark is set to that position. |
.exchange-point-and-mark |
Ctrl-x Ctrl-x | Swap the point with the mark. The current cursor position is set to the saved position, and the old cursor position is saved as the mark. |
.character-search |
Ctrl-] | A character is read and point is moved to the next occurrence of that character. A negative count searches for previous occurrences. |
.character-search-backward |
Alt-Ctrl-] | A character is read and point is moved to the previous occurrence of that character. A negative count searches for subsequent occurrences. |
.insert-comment |
Alt-# | Without a numeric argument, the value of the comment-begin variable is inserted at the beginning of the current line. If a numeric argument is supplied, this command acts as a toggle: if the characters at the beginning of the line do not match the value of comment-begin , the value is inserted, otherwise the characters in comment-begin are deleted from the beginning of the line. In either case, the line is accepted as if a newline had been typed. |
.redraw-current-line |
Refresh the current line. | |
.dump-functions |
Print all of the functions and their key bindings to the Readline output stream. If a numeric argument is supplied, the output is formatted in such a way that it can be made part of an inputrc file. | |
.dump-variables |
Print all of the settable variables and their values to the Readline output stream. If a numeric argument is supplied, the output is formatted in such a way that it can be made part of an inputrc file. | |
.dump-macros |
Print all of the Readline key sequences bound to macros and the strings they output. If a numeric argument is supplied, the output is formatted in such a way that it can be made part of an inputrc file. | |
.execute-named-command |
Alt-x | Read a bindable readline command name from the input and execute the function to which it's bound, as if the key sequence to which it was bound appeared in the input. If this function is supplied with a numeric argument, it passes that argument to the function it executes. |
.Readline vi Mode up top
While the Readline library does not have a full set of vi editing functions, it does contain enough to allow simple editing of the line. The Readline vi mode behaves as specified in the POSIX standard.
In order to switch interactively between emacs and vi editing modes, use the command Alt-Ctrl-j (bound to emacs-editing-mode
when in vi mode and to vi-editing-mode
in emacs mode). The Readline default is emacs mode.
When you enter a line in vi mode, you are already placed in "insertion" mode, as if you had typed an "i". Pressing Esc switches you into "command" mode, where you can edit the text of the line with the standard vi movement keys, move to previous history lines with "k" and subsequent lines with "j", and so forth.
Command | Key | Description |
---|---|---|
.emacs-editing-mode |
Ctrl-e | When in vi command mode, this causes a switch to emacs editing mode. |
.vi-editing-mode |
Alt-Ctrl-j | When in emacs editing mode, this causes a switch to vi editing mode. |
.Other Readline Commands up top
These other commands are not very useful in Clink, but exist nevertheless.
Command | Key | Description |
---|---|---|
.tab-insert |
Alt-Ctrl-i | Insert a tab character. Note: this command exists for compatibility with bash, but it isn't useful in Clink because CMD doesn't support entering a tab character in the input line. |
.prefix-meta |
"Metafy" the next character typed. This is for keyboards without an Alt meta key. Typing a key bound to prefix-meta and then f is equivalent to typing Alt-f. By default this is bound to Esc, but only when the terminal.raw_esc Clink setting is enabled. |
|
.skip-csi-sequence |
This has no effect unless the terminal.raw_esc Clink setting is enabled. Reads enough characters to consume a multi-key sequence such as those defined for keys like Home and End. Such sequences begin with a Control Sequence Indicator (CSI), which is ESC [ . If this sequence is bound to "\e[", keys producing such sequences will have no effect unless explicitly bound to a readline command, instead of inserting stray characters into the editing buffer. |
|
.bracketed-paste-begin |
This function is intended to be bound to the "bracketed paste" escape sequence sent by some terminals, and such a binding is assigned by default. It allows Readline to insert the pasted text as a single unit without treating each character as if it had been read from the keyboard. The characters are inserted as if each one was bound to self-insert instead of executing any editing commands.Bracketed paste sets the region (the characters between point and the mark) to the inserted text. It uses the concept of an active mark: when the mark is active, Readline redisplay uses the terminal's standout mode to denote the region. Note: this command exists for compatibility with bash, but Clink doesn't support bracketed paste. Instead use the clink-paste command to perform the equivalent of a bracketed paste. |
.Clink Commands up top
Clink also adds some new commands, beyond what's normally provided by Readline.
Command | Key | Description |
---|---|---|
.add-history |
Alt-Ctrl-k | Add the current line to the history without executing it, and clear the editing line. |
.alias-expand-line |
A synonym for clink-expand-doskey-alias . |
|
.clink-accept-suggested-line |
If there is a suggestion, insert the suggestion and accept the input line (like accept-line ). |
|
.clink-backward-bigword |
Move back to the start of the current or previous space delimited word. | |
.clink-complete-numbers |
Like complete , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
|
.clink-copy-cwd |
Alt-c | Copies the current working directory to the clipboard. |
.clink-copy-line |
Alt-Ctrl-c | Copies the input line to the clipboard. |
.clink-copy-word |
Alt-Ctrl-w | Copies the word at the cursor point to the clipboard, or copies the n-th word if a numeric argument is provided via the digit-argument keys. |
.clink-ctrl-c |
Ctrl-c | Copies any selected text to the clipboard, otherwise cancels the input line and starts a new one. |
.clink-diagnostics |
Ctrl-x Ctrl-z | Show internal diagnostic information. |
.clink-dump-functions |
Print all of the functions and their key bindings. If a numeric argument is supplied, formats the output so that it can be made part of an INPUTRC file. Unlike dump-functions , this uses friendly key names and includes luafunc: macros. |
|
.clink-dump-macros |
Print all of the key names bound to macros and the strings they output. If a numeric argument is supplied, formats the output so that it can be made part of an INPUTRC file. Unlike dump-macros , this uses friendly key names and omits luafunc: macros. |
|
.clink-exit |
Alt-F4 | Replaces the input line with exit and executes it (exits the CMD instance). |
.clink-expand-doskey-alias |
Alt-Ctrl-f | Expands doskey aliases in the input line. |
.clink-expand-env-var |
Expands environment variables in the word at the cursor point. | |
.clink-expand-history |
Alt-^ | Performs history expansion in the input line. |
.clink-expand-history-and-alias |
Performs history and doskey alias expansion in the input line. | |
.clink-expand-line |
Alt-Ctrl-e | Performs history, doskey alias, and environment variable expansion in the input line. |
.clink-find-conhost |
Activates the "Find" dialog when running in a standard console window (hosted by the OS conhost). This is equivalent to picking "Find..." from the console window's system menu. When clink.default_bindings is enabled, this is bound to Ctrl-f. |
|
.clink-forward-bigword |
Move forward to the beginning of the next space delimited word, or insert the next full suggested word up to a space. | |
.clink-insert-dot-dot |
Alt-a | Inserts ..\ at the cursor point. |
.clink-insert-suggested-full-word |
If there is a suggestion, insert the next full word from the suggested line. | |
.clink-insert-suggested-line |
If there is a suggestion, insert the suggested line. | |
.clink-insert-suggested-word |
If there is a suggestion, insert the next word from the suggested line. | |
.clink-magic-suggest-space |
Insert the next full suggested word (if any) up to a space, and insert a space. | |
.clink-mark-conhost |
Activates the "Mark" mode when running in a standard console window (hosted by the OS conhost). This is equivalent to picking "Mark" from the console window's system menu. When clink.default_bindings is enabled, this is bound to Ctrl-m. |
|
.clink-menu-complete-numbers |
Like menu-complete , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
|
.clink-menu-complete-numbers-backward |
Like menu-complete-backward , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
|
.clink-old-menu-complete-numbers |
Alt-Ctrl-n | Like old-menu-complete , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
.clink-old-menu-complete-numbers-backward |
Like old-menu-complete-backward , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
|
.clink-paste |
Ctrl-v | Paste text from the clipboard at the cursor point. |
.clink-popup-complete |
A synonym for clink-select-complete . |
|
.clink-popup-complete-numbers |
Alt-Ctrl-Shift-N | Like clink-select-complete , but for numbers from the console screen (3 digits or more, up to hexadecimal). |
.clink-popup-directories |
Alt-Ctrl-PgUp | Show recent directories in a popup list. In the popup, use Enter to cd /d to the selected directory. |
.clink-popup-history |
Alt-Ctrl-Up | Show history entries in a popup list. Filters using any text before the cursor point. In the popup, use Enter to execute the selected history entry. If history.time_stamp is show then timestamps are shown unless a numeric argument of 0 is provided. If history.time_stamp is save then timestamps are only shown if a non-zero numeric argument is provided. |
.clink-popup-show-help |
Alt-Ctrl-H | Show all key bindings in a searchable popup list. In the popup, use Enter to invoke the selected key binding. If a numeric argument of 4 is supplied, it includes unbound commands. |
.clink-reload |
Ctrl-x Ctrl-r | Reload Lua scripts and the .inputrc file. |
.clink-reset-line |
Esc | Clear the input line. Can be undone, unlike revert-line . |
.clink-scroll-bottom |
Alt-End | Scroll the console window to the bottom (the current input line). |
.clink-scroll-line-down |
Alt-Down | Scroll the console window down one line. |
.clink-scroll-line-up |
Alt-Up | Scroll the console window up one line. |
.clink-scroll-page-down |
Alt-PgDn | Scroll the console window down one page. |
.clink-scroll-page-up |
Alt-PgUp | Scroll the console window up one page. |
.clink-scroll-top |
Alt-Home | Scroll the console window to the top. |
.clink-select-complete |
Ctrl-Space | Like complete , but shows an interactive menu of matches and responds to arrow keys and typing to filter the matches. If there is only one match, it is inserted. While completing, F1 toggles showing match descriptions at the bottom vs next to each match. |
.clink-selectall-conhost |
Mimics the "Select All" command when running in a standard console window (hosted by the OS conhots). Selects the input line text. If already selected, then it invokes the "Select All" command from the console window's system menu and selects the entire screen buffer's contents. When clink.default_bindings is enabled, this is bound to Ctrl-a. |
|
.clink-shift-space |
Shift-Space | Invoke the normal Space key binding, so that Shift-Space behaves the same as Space. |
.clink-show-help |
Alt-h | Show all key bindings. A numeric argument affects showing categories and descriptions: 0 for neither, 1 for categories, 2 for descriptions, 3 for categories and descriptions (the default). Add 4 to include unbound commands. |
.clink-show-help-raw |
Show raw key sequence strings for all key bindings. A numeric argument affects showing categories and descriptions: 0 for neither, 1 for categories, 2 for descriptions, 3 for categories and descriptions (the default). Add 4 to include unbound commands. | |
.clink-toggle-slashes |
Ctrl-/ | Toggle between forward and backslashes in the word at the cursor point, or toggle in the n-th word if a numeric argument is provided via the digit-argument keys. |
.clink-up-directory |
Ctrl-PgUp | Execute cd .. to move up one directory. |
.clink-what-is |
Alt-Shift-/ | Show the key binding for the next key sequence input. If a numeric argument is supplied, the raw key sequence string is shown instead of the friendly key name. |
.cua-backward-bigword |
Extend the selection backward one space delimited word. | |
.cua-backward-char |
Shift-Left | Extend the selection backward one character. |
.cua-backward-word |
Ctrl-Shift-Left | Extend the selection backward one word. |
.cua-beg-of-line |
Shift-Home | Extend the selection to the beginning of the line. |
.cua-copy |
Shift-Ins | Copy the selected text to the clipboard. |
.cua-cut |
Shift-Del | Cut the selected text to the clipboard. |
.cua-end-of-line |
Shift-End | Extend the selection to the end of the line. |
.cua-forward-bigword |
Extend the selection forward one space delimited word, or insert the next full suggested word up to a space. | |
.cua-forward-char |
Shift-Right | Extend the selection forward one character, or insert the next full suggested word up to a space. |
.cua-forward-word |
Ctrl-Shift-Right | Extend the selection forward one word. |
.cua-next-screen-line |
Shift-Down | Extend the selection down one screen line. |
.cua-previous-screen-line |
Shift-Up | Extend the selection up one screen line. |
.cua-select-all |
Extend the selection to the entire input line. | |
.cua-select-word |
Select the word at the cursor point. | |
.edit-and-execute-command |
Ctrl-x Ctrl-e | Invoke an editor on the current input line, and execute the result as commands. This attempts to invoke %VISUAL% , %EDITOR% , or notepad.exe as the editor, in that order. |
.glob-complete-word |
Alt-g | Perform wildcard completion on the text before the cursor point, with a * implicitly appended. |
.glob-expand-word |
Ctrl-x * | Insert all the wildcard completions that glob-list-expansions would list. If a numeric argument is supplied, a * is implicitly appended before completion. |
.glob-list-expansions |
Ctrl-x g | List the possible wildcard completions of the text before the cursor point. If a numeric argument is supplied, a * is implicitly appended before completion. |
.history-and-alias-expand-line |
A synonym for clink-expand-history-and-alias . |
|
.history-expand-line |
A synonym for clink-expand-history . |
|
.insert-last-argument |
A synonym for yank-last-arg . |
|
.magic-space |
Perform history expansion on the text before the cursor position and insert a space. | |
.old-menu-complete-backward |
Like old-menu-complete , but in reverse. This behaves like the default completion in cmd.exe on Windows. When Clink is installed using the setup program with the "Use enhanced default settings" box checked or when clink.default_bindings is set to windows , then this is bound by default to Shift-Tab. |
|
.remove-history |
Alt-Ctrl-d | While searching history, removes the current line from the history. |
.shell-expand-line |
Alt-Ctrl-e | A synonym for clink-expand-line . |
.win-copy-history-number |
F9 | Enter a history number and replace the input line with the history entry (mimics Windows console F9). |
.win-copy-up-to-char |
F2 | Enter a character and copy up to it from the previous command (mimics Windows console F2). |
.win-copy-up-to-end |
F3 | Copy the rest of the previous command (mimics Windows console F3). |
.win-cursor-forward |
F1 | Move cursor forward, or at end of line copy character from previous command, or insert suggestion (mimics Windows console F1 and Right). |
.win-delete-up-to-char |
F4 | Enter a character and delete up to it in the input line (mimics Windows console F4). |
.win-history-list |
F7 | Executes a history entry from a list (mimics Windows console F7). |
.win-insert-eof |
F6 | Insert ^Z (mimics Windows console F6). |
Note: Some commands have alternative default key bindings when Clink is installed with "Use enhanced default settings" checked in the setup program or when
clink.default_bindings
is set towindows
.
.Completion Colors up top
The match.coloring_rules
setting provides a string that determines how match completions are displayed.
The string can contain a series of one or more rules separated by colons (:
). If an environment variable %CLINK_MATCH_COLORS%
exists, its value supersedes this setting.
Each rule is a series of one or more conditions separated by spaces, followed by an equals sign and then the SGR parameters for an ANSI escape code. All of the conditions must be true for the rule to match (in other words, a space is like an AND operator).
Each condition can be any of the following:
- A pattern, for example
*.zip
(for zip files). This is an fnmatch pattern (like .gitignore globbing patterns). The pattern is compared only to the filename portion after stripping the path. For example,*.zip
. - A type, for example
di
(for directories). The available types are listed below. - A
not
operator, which negates the next condition. For example,not di
applies to anything that isn't a directory, ornot *.zip
applies to any name that doesn't match*.zip
.
Any quoted string is assumed to be a pattern, so "hi"
is a pattern instead of the Hidden type, and etc.
Rules are evaluated in the order listed, with one exception: Rules with exactly one type and no patterns are evaluated last; this makes it easier to list the rules -- you can put the simple defaults first, followed by specializations.
Type | Description | Default |
---|---|---|
di |
Directory. | 01;34 (bright blue) |
ex |
Executable file. | 01;32 (bright green) |
fi |
Normal file. | |
ro |
Readonly file or directory. | The color.readonly setting. |
hi |
Hidden file or directory. | The color.hidden setting. |
mi |
Missing file or directory. | |
ln |
Symlinks. When ln=target then symlinks are colored according to the target of the symlink. |
target |
or |
Orphaned symlink (the target of the symlink is missing). | |
no |
Normal color; covers anything not covered by any other types. | |
any |
This clears all types in the rule so far, including the implicit default fi type when no type is given. For example, any history* applies to directories as well as to files (any directory or file whose name begins with "history"). |
For backward compatibility with %LS_COLORS%
, either so
or *.readline-colored-completion-prefix
may be used to override thecolor.common_match_prefix
setting.
Here is an example that defines colors for various types.
clink set match.coloring_rules di=93:ro ex=1;32:ex=1:ro=32:di *.tmp=90
di=93
uses bright yellow for directories.ro ex=1;32
uses bright green for readonly executable files.ex=1
uses bold for executable files (depending on the terminal's color theme, bold by itself usually ends up being bright white).ro=32
uses dark green for readonly files.di *.tmp=90
uses bright magenta for directory names ending in.tmp
.
Note: The
match.coloring_rules
setting was added in Clink v1.6.1. It works similar to how the%LS_COLORS%
environment variable works, except it adds "hi", "ro", "any", and "not", and patterns can be fnmatch patterns instead of just "*.ext" patterns.
.LS_COLORS (for backward compatibility) up top
The %LS_COLORS%
environment variable is supported for backwards compatibility with Readline. It can provide color definitions as a series of color definitions separated by colons (:
). Each definition is a either a two character type id or a file extension, followed by an equals sign and then the SGR parameters for an ANSI escape code. The two character type ids are listed below.
If either match.coloring_rules
or %CLINK_MATCH_COLORS
are set, then they take precedence and %LS_COLORS%
is ignored.
When colored-stats
is configured to on
, then file completions are colored according to their file type or extension from %LS_COLORS%
. Also, since %LS_COLORS%
doesn't cover readonly files, hidden files, doskey aliases, or shell commands the color.readonly, color.hidden, color.doskey, and color.cmd Clink settings exist to cover those.
When colored-completion-prefix
is configured to on
, then the "so" color from %LS_COLORS%
is used to color the common prefix when displaying possible completions. The default for "so" is bright magenta, but for example set LS_COLORS=so=90
sets the color to bright black (which shows up as a dark gray).
Types | Description | Default |
---|---|---|
di |
Directories. | 01;34 (bright blue) |
ex |
Executable files. | 01;32 (bright green) |
fi |
Normal files. | |
ln |
Symlinks. When ln=target then symlinks are colored according to the target of the symlink. |
target |
mi |
Missing file or directory. | |
no |
Normal color. This is used for anything not covered by one of the other types. It may be overridden by various other Clink color settings as appropriate depending on the completion type. |
|
or |
Orphaned symlink (the target of the symlink is missing). | |
so |
Common prefix for possible completions. | 01;35 (bright magenta) |
Special extensions | Description | Default |
---|---|---|
.readline-colored-completion-prefix |
If there is a color definition in %LS_COLORS% for the custom suffix .readline-colored-completion-prefix , it is used for the common prefix, superseding the so type. |
Here is an example where %LS_COLORS%
defines colors for various types.
set LS_COLORS=so=90:fi=97:di=93:ex=92:*.pdf=30;105:*.md=4
so=90
uses bright black (dark gray) for the common prefix for possible completions.fi=97
uses bright white for files.di=93
uses bright yellow for directories.ex=92
uses bright green for executable files.*.pdf=30;105
uses black on bright magenta for .pdf files.*.md=4
uses underline for .md files.
.Popup Windows up top
Some commands show a searchable popup window that lists the available completions, directory history, or command history.
For example, win-history-list
(F7) and clink-popup-directories
(Ctrl-Alt-PgUp) show popup windows.
Here's how the popup windows work:
Key | Description |
---|---|
Escape | Cancels the popup. |
Enter | Inserts the highlighted completion, changes to the highlighted directory, or executes the highlighted command. |
Shift-Enter | Inserts the highlighted completion, inserts the highlighted directory, or jumps to the highlighted command history entry without executing it. |
Ctrl-Enter | Same as Shift-Enter. |
Del | In a command history popup, Del deletes the selected history entry. |
Left/Right | Scroll horizontally if possible. |
Ctrl-Left/Right | Scroll faster horizontally if possible. |
Ctrl-Home/End | Scroll horizontally to far left/right if possible. |
Most of the popup windows also have incremental search:
Key | Description |
---|---|
Typing | Typing does an incremental search. |
F1 | Open this help topic in the default web browser. |
F3 | Go to the next match. |
Ctrl-L | Go to the next match. |
Shift-F3 | Go to the previous match. |
Ctrl-Shift-L | Go to the previous match. |
F4 | Toggle the search mode between "find" and "filter". When the search mode is filter, typing filters the list instead of doing an incremental search (only in v1.6.13 and higher). Use the clink.popup_search_mode setting to set the default search mode. |
The win-history-list
command has a different search feature. Typing digits 0
-9
jumps to the numbered history entry, or typing a letter jumps to the preceding history entry that begins with the typed letter. Left/Right inserts the highlighted command history entry without executing it. These are for compatibility with the F7 behavior built into Windows console prompts.
Use the clink-popup-history
command instead if you prefer for typing to do an incremental search.
.Extending Clink With Lua top
Clink can be extended with Lua scripts to customize startup actions, create completion matches, customize the prompt, and more. The following sections describe these in more detail and show some examples.
Location of Lua Scripts | Locations from which scripts are loaded. |
Writing Lua Scripts | Some tips for starting to write Lua scripts. |
Argument Completion | How to give commands contextual match generators for their arguments. |
Match Generators | How to write match generators, or custom completion providers. |
Coloring the Input Text | How to make a match generator or argument matcher override the input coloring. |
Customizing the Prompt | How to write custom prompt filters. |
Customizing Suggestions | How to write custom [suggestion](#auto-suggest) generators. |
Showing Input Hints | How to write custom input hint providers (input hints can be displayed below the input line). |
.Location of Lua Scripts up top
Clink loads all Lua scripts it finds in these directories:
- All directories listed in the
clink.path
setting, separated by semicolons. - If
clink.path
is not set, then the DLL directory and the profile directory are used (see File Locations for info about the profile directory). - All directories listed in the
%CLINK_PATH%
environment variable, separated by semicolons. - All directories registered by the
clink installscripts
command.
Lua scripts are loaded once and are only reloaded if forced because the scripts locations change or the clink-reload
command is invoked (Ctrl-X,Ctrl-R).
Run clink info
to see the script paths for the current session.
Notes:
- "completions" is a special reserved directory name: a "completions" directory under any of the Lua script directories listed in
clink info
has special meaning, and should not contain scripts unless they are specially written to be put in a "completions" directory. See Completion directories for more information.- Clink performs tilde expansion on the Lua script directory names. If the path begins with
~\
then it is replaced with the current user's home directory (%HOME%
or%HOMEDRIVE%%HOMEPATH%
or%USERPROFILE%
).
.Completion directories up top
You may optionally put Lua completion scripts in a completions\
directory when using Clink v1.3.23 and higher. That prevents them from being loaded when Clink starts, and instead they are only loaded when needed. That can make Clink load faster if you have a large quantity of Lua scripts that define argmatchers.
When a command name is typed, if a corresponding argmatcher is not already loaded then the completions directories are searched for a Lua script by the same name. If found, then the Lua script is loaded. This is similar to how completion scripts work in shells like bash, zsh, and fish.
For example, if you type xyz
and an argmatcher for xyz
is not yet loaded, then if xyz.lua
exists in one of the completions directories it will be loaded.
Clink looks for completion scripts in these directories:
- Any directories listed in the
%CLINK_COMPLETIONS_DIR%
environment variable (multiple directories may be separated by semicolons). - A
completions\
subdirectory under each scripts directory listed byclink info
(see Location of Lua Scripts).
In v1.5.3 and higher, when a completions\
script is loaded on demand the script receives as an argument the fully qualified path name to the typed program or file. The script can access the argument by using local fullname = ...
(literally three dots). For example, that can be useful for checking whether it's a supported program, registering different argmatchers for different copies of the program or file, checking whether it's a supported program, and so on.
Note: If you download scripts, then don't put them in a "completions" directory unless they specifically say they can be put there.
If a script defines more than an argmatcher, then putting it in a completions directory may cause its other functionality to not work until a command is typed with the same name as the script. For example, if a script in a completions directory defines an argmatcher and also a prompt filter, the prompt filter won't be loaded until the corresponding command name is typed. Whether that is desirable depends on the script and on your preference.
For example, the scripts from the clink-completions project belong in a normal script directory, because they have other functionality besides just completions, and they won't work correctly in a "completions" directory.
.Writing Lua Scripts up top
Lua is a versatile and lightweight language. It's very approachable and easy to learn for beginners, but it also has powerful capabilities available if you need them.
Here are some tips for getting started writing Lua scripts:
- Clink uses Lua 5.2.
- Loading a Lua script executes it; so when Clink loads Lua scripts from the locations above, it executes the scripts.
- Code not inside a function is executed immediately when the script is loaded.
- Usually scripts will register functions to customize various behaviors:
- Generate completion matches.
- Apply color to input text.
- Customize the prompt.
- Perform actions before or after the user gets to edit each input line.
- Provide new custom commands that can be bound to keys via the luafunc: key macro syntax.
- Often scripts will also define some functions and variables for use by itself and/or other scripts.
- Clink extends the Lua language by adding many new APIs and features for use within Clink.
.Argument Completion up top
Clink provides a framework for writing complex argument match generators in Lua. It works by creating a parser object that describes a command's arguments and flags and associating the parser with one or more commands. When Clink detects a parser is associated with the command being edited, it uses the parser to generate matches and apply input line coloring.
The Basics | A quick example to show the basics. |
Automatic Filename Completion | By default, filename completion is used. |
Descriptions for Flags and Arguments | How to add descriptive text. |
More Advanced Stuff | |
Linking Parsers | How to link a parser to a word or flag. |
Functions As Argument Options | Using a function to provide completions. |
Show a Usage Hint | How to show a usage hint for the argument under the cursor. |
Generate Matches From History | Providing completions from the history. |
Disable Sorting Matches | How to disable auto-sorted completions. |
Fully Qualified Pathnames | How to make different argmatchers for programs with the same name. |
Delimited Arguments | How to allow multiple completions in the same argument slot (e.g. file1;file2;file3 ). |
Overcoming Word Breaks | How to prevent characters like `,` from breaking words. |
Adaptive Argmatchers | How an argmatcher can define or modify itself on the fly. |
Responding to Arguments in Argmatchers | When argument slots need to influence one another. |
Shorthand | Alternative syntax for defining argmatchers. |
.The Basics up top
Here is an example of a simple parser for the command foobar
;
clink.argmatcher("foobar")
:addarg({ "hello", "hi" }) -- Completions for arg #1.
:addarg({ "world", "wombles", "xyzzy" }) -- Completions for arg #2.
:addflags("-foo", "-bar") -- Flags.
This parser describes a command that has two arguments, and some flags.
Arguments are positional. Each :addarg()
adds a new argument position and defines the possible completions for that argument position.
Flags are position independent. Any :addflags()
add to the set of possible flag completions. Any word that begins with the flag prefix character (in this example -
) is considered to be a flag, even if it is not listed as a possible completion. The flags may be input at any position; before arguments, between arguments, and after arguments.
On the command line completion would look something like this, if Alt-= were pressed at the end of each input line below:
C:\>foobar -
-bar -foo
C:\>foobar -bar hello
wombles world xyzzy
C:\>foobar -bar hello wo
wombles world
C:\>foobar -bar hello wombles -
-bar -foo
C:\>foobar -bar hello wombles -foo _
When displaying possible completions, flag matches are only shown if the flag character has been input. So foobar
and Alt-= would list matches for the first argument position, or foobar some_word
and Alt-= would list matches for the second argument position, or foobar -
and Alt-= would list only flag matches.
If a command doesn't have an argmatcher but is a doskey macro, Clink automatically expands the doskey macro and looks for an argmatcher for the expanded command. A macro like gco=git checkout $*
automatically reuses a git
argmatcher and produces completions for its checkout
argument. However, it only expands the doskey macro up to the first $
, so complex aliases like foo=app 2$gnul text $*
or foo=$2 $1
might behave strangely.
Also see clink.argmatcher(), :addflags() and :addarg().
.Automatic Filename Completion up top
A fresh, empty argmatcher provides no completions.
clink.argmatcher("foobar") -- The "foobar" command provides no completions.
Once any flags or argument positions have been added to an argmatcher, then the argmatcher will provide completions.
clink.argmatcher("foobar")
:addarg({ "hello", "hi" }) -- Completions for arg #1.
:addarg({ "world", "wombles", "xyzzy" }) -- Completions for arg #2.
:addflags("-foo", "-bar") -- Flags.
When completing a word that doesn't have a corresponding argument position the argmatcher will automatically use filename completion. For example, the foobar
argmatcher has two argument positions, and completing a third word uses filename completion.
C:\>foobar hello world pro
Program Files\ Program Files(x86)\ ProgramData\
C:\>foobar hello world pro_
Use _argmatcher:nofiles() if you want to disable the automatic filename completion and "dead end" an argmatcher for extra words. This stops all further parsing for the command.
clink.argmatcher("foobar")
:addarg({ "hello", "hi" }) -- Completions for arg #1
:addarg({ "world", "wombles", "xyzzy" }) -- Completions for arg #2
:addflags("-foo", "-bar") -- Flags
:nofiles() -- Using :nofiles() prevents further completions.
.Descriptions for Flags and Arguments up top
Flags and arguments may optionally have descriptions associated with them. The descriptions, if any, are displayed when listing possible completions.
Use _argmatcher:adddescriptions() to add descriptions for flags and/or arguments. Refer to its documentation for further details about how to use it, including how to also show arguments that a flag accepts.
For example, with the following matcher, typing foo -
Alt-= will list all of the flags, plus descriptions for each.
clink.argmatcher("foo")
:addflags("-?", "-h", "-n", "-v", "--help", "--nothing", "--verbose")
:addarg("print", "delete")
:addarg(clink.filematches)
:nofiles()
:adddescriptions(
{ "-n", "--nothing", description = "Do nothing; show what would happen without doing it" },
{ "-v", "--verbose", description = "Verbose output" },
{ "-h", "--help", "-?", description = "Show help text" },
{ "print", description = "Print the specified file" },
{ "delete", description = "Delete the specified file" },
)
.More Advanced Stuff up top
.Linking Parsers up top
There are often situations where the parsing of a command's arguments is dependent on the previous words (git merge ...
compared to git log ...
for example). For these scenarios Clink allows you to link parsers to arguments' words using Lua's concatenation operator.
local a_parser = clink.argmatcher():addarg({ "foo", "bar" })
local b_parser = clink.argmatcher():addarg({ "abc", "123" })
local c_parser = clink.argmatcher()
c_parser:addarg({ "foobar" .. a_parser }) -- Arg #1 is "foobar", which has args "foo" or "bar".
c_parser:addarg({ b_parser }) -- Arg #2 is "abc" or "123".
As the example above shows, it is also possible to use a parser without concatenating it to a word.
When Clink follows a link to a parser it will only return to the previous parser when the linked parser runs out of arguments. Using :nofiles()
prevents returning to the previous parser.
.Flags With Arguments up top
Parsers can be concatenated with flags, too.
Here's an example of a flag that takes an argument:
clink.argmatcher("git")
:addarg({
"merge"..clink.argmatcher():addflags({
"--strategy"..clink.argmatcher():addarg({
"resolve",
"recursive",
"ours",
"octopus",
"subtree",
})
})
})
A :
or =
at the end of a flag indicates the flag takes an argument but requires no space between the flag and its argument. If such a flag is not linked to a parser, then it automatically gets linked to a parser to match files. Here's an example with a few flags that take arguments without a space in between:
clink.argmatcher("findstr")
:addflags({
"/b", "/e", "/l", "/r", "/s", "/i", "/x", "/v", "/n", "/m", "/o", "/p", "/offline",
"/a:"..clink.argmatcher():addarg( "attr" ),
"/f:"..clink.argmatcher():addarg( clink.filematches ),
"/c:"..clink.argmatcher():addarg( "search_string" ),
"/g:", -- This is the same as linking with clink.argmatcher():addarg(clink.filematches).
"/d:"..clink.argmatcher():addarg( clink.dirmatches )
})
.Functions As Argument Options up top
Argument options are not limited solely to strings. Clink also accepts functions too so more context-aware argument options can be used.
The function is called each time matches are generated for the argument position.
local function rainbow_function(word)
return { "red", "white", "blue" }
end
local the_parser = clink.argmatcher()
the_parser:addarg({ "zippy", "bungle", "george" })
the_parser:addarg({ rainbow_function, "yellow", "green" })
The functions are passed five arguments:
word
is a partial string for the word under the cursor, corresponding to the argument for which matches are being generated: it is an empty string, or if a filename is being entered then it will be the path portion (e.g. for "dir1\dir2\pre"word
will be "dir1\dir2").word_index
is the word index inline_state
, corresponding to the argument for which matches are being generated.line_state
is a line_state object that contains the words for the associated command line.match_builder
is a builder object (but for adding matches the function should return them in a table).user_data
is a table that the argmatcher can use to help it parse the input line. See Responding to Arguments in Argmatchers for more information about theuser_data
table.
The functions can return any of the following:
- Return a table of potential matches (strings). The table may optionally also contain tables that describe the matches; the format is the same as in builder:addmatches().
- Return
true
to stop generating matches. - Return
false
ornil
(or don't return anything) to stop generating matches and use file completions.
Compatibility Note: When a function argument uses the old v0.4.9
clink.match_display_filter
approach, then theword
argument will be the full word under the cursor, for compatibility with the v0.4.9 API.
Some built-in matcher functions are available:
Function | Description |
---|---|
clink.dirmatches | Generates directory matches. |
clink.filematches | Generates file matches. |
.Show a Usage Hint up top
A usage hint can be shown in the comment row (below the input line). Usage hints for argmatchers are only shown if both comment_row.show_hints (off by default) and argmatcher.show_hints (on by default) are enabled.
To use this, Clink v1.7.0 or higher is required.
Argmatchers can automatically supply input hints based on arginfo
fields from match completions.
To supply a custom usage hint, an argmatcher can include either hint="text"
or hint=function_name
in the argument table.
clink.argmatcher("foo")
:addarg({ clink.filematches, hint="Argument expected: filename" })
C:\dir>foo _
Argument expected: filename
If a function name is supplied, then the function is passed five arguments:
arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a string containing the word being parsed. Note: when the cursor is between words or after the last word thenword
is an empty string.word_index
is the word index inline_state
, corresponding to the word being parsed. Note: when the cursor is between words thenword_index
is the index of the next word after the cursor, or when the cursor is after the last word thenword_index
is greater thanline_state:getwordcount()
.line_state
is a line_state object that contains the words for the associated command line.user_data
is a table that the argmatcher can use to help it parse the input line. See Responding to Arguments in Argmatchers for more information about theuser_data
table.
The function returns a hint string, and an optional position in the line text where the hint refers to. If the position is omitted, then the offset to the beginning of the word is assumed.
local function foo_hint_func(arg_index, word, word_index, line_state, user_data)
local hint = "Argument expected for '"..line_state:getword(word_index - 1).."': filename"
local pos = line_state:getwordinfo(word_index).offset -- Shown for completeness, but this is automatically assumed if omitted.
return hint, pos
end
clink.argmatcher("foo")
:addarg({ "add", "remove" })
:addarg({ clink.filematches, hint=foo_hint_func })
C:\dir>foo add _
Argument expected for 'add': filename
.Generate Matches From History up top
An argument position can collect matches from the history file. When an argument table contains fromhistory=true
then additional matches are generated by parsing the history file to find values for that argument slot from commands in the history file.
This example generates matches for arguments to a --host
flag by parsing the history file for host names used in the past, and also includes the current computer name.
local host_parser = clink.argmatcher():addarg({ fromhistory=true, os.getenv("COMPUTERNAME") })
clink.argmatcher("program"):addflags({ "--host"..host_parser })
.Disable Sorting Matches up top
Match completions are normally listed in sorted order. In some cases it may be desirable to disable sorting and list match completions in a specific order. To disable sorting, include nosort=true
in the argument table. When sorting is disabled, matches are listed in the order they were added.
local the_parser = clink.argmatcher()
the_parser:addarg({ nosort=true, "red", "orange", "yellow", "green", "blue", "indigo", "violet" })
.Fully Qualified Pathnames up top
Sometimes there may be more than one program installed with the same name. For example, there might be multiple versions of grep
installed.
In Clink v1.3.38 and higher, you can define argmatchers using fully qualified pathnames. For example, this makes it possible to define one argmatcher for c:\EmployerTools\grep.exe
and another for d:\PersonalTools\grep.exe
, and the corresponding argmatcher will be used when appropriate.
In the example above, you could define an argmatcher for c:\EmployerTools\grep.exe
, and also define an argmatcher for grep
(or have a grep.lua
file in a completions\
directory). The plain grep
one would be used whenever the typed grep
doesn't resolve to the EmployerTools copy.
.Delimited Arguments up top
In some cases an argument for programs may accept a list of values separated by ;
or +
or etc. Normally ;
or +
are argument separators (like space), and advance the argmatcher to the next argument slot.
In Clink v1.3.37 and higher, you can make them stay on the current argument slot by including loopchars=";"
(or set loopchars=
a list of value delimiters).
-- This argmatcher accepts syntax like "foo color filename".
-- Typing "foo red f" and pressing TAB generates completions for files.
-- Typing "foo red;" and pressing TAB generates completions for files.
clink.argmatcher("foo")
:addarg({"red", "green", "blue"})
:addarg(clink.filematches)
-- This argmatcher accepts syntax like "foo color[;color...] filename".
-- Typing "foo red f" and pressing TAB generates completions for files.
-- Typing "foo red;" and pressing TAB generates completions for colors (not files).
clink.argmatcher("foo")
:addarg({loopchars=";", "red", "green", "blue"})
:addarg(clink.filematches)
.Overcoming Word Breaks up top
Clink and parses the input line into a line_state
by ending a word whenever one of the following characters is encountered (except when inside quotes). These are the same word break characters as CMD.exe uses.
- Whitespace characters SPACE, TAB, and NEWLINE.
- Punctuation symbols
'
,‵
,=
,+
,;
, and,
. - Grouping symbols
(
,)
,[
,]
,{
, and}
.
However, many programs parse their command line arguments using different word break characters than CMD does.
In Clink v1.5.17 and higher, argmatchers can override the word break rules for specific argument positions by including nowordbreakchars=","
(or set nowordbreakchars=
a list of characters that shouldn't denote word breaks). This can allow more accurate completions and input line coloring when these characters are present. But nowordbreakchars
is always ignored for builtin CMD commands and Batch scripts (because CMD.exe itself always parses word breaks a specific way). Flags in argmatchers for anything other than builtin CMD commands and Batch scripts default to assuming nowordbreakchars="'‵+;,"
, but that can be overridden by setting nowordbreakchars=
some other string.
-- This argmatcher accepts syntax like "wt --pos x,y --size cols,rows command".
clink.argmatcher("wt")
:addflags({
"--pos" .. clink.argmatcher():addarg({fromhistory=true, nowordbreakchars=","}),
"--size" .. clink.argmatcher():addarg({fromhistory=true, nowordbreakchars=","}),
})
:chaincommand()
It's also possible to combine nowordbreakchars
and loopchars
:
-- This argmatcher accepts syntax like "foo color[,color...] filename".
-- Typing "foo red " and pressing TAB generates completions for files.
-- Typing "foo red," and pressing TAB generates completions for colors (not files).
clink.argmatcher("foo")
:addarg({loopchars=",", nowordbreakchars=",", "red", "green", "blue"})
:addarg(clink.filematches)
.Adaptive Argmatchers up top
Some argmatchers may need to adapt on the fly. For example, a program may have different features available depending on the current directory, or may want to define its arguments and flags by parsing the --help
text from running a program.
An argmatcher can define a "delayed initialization" callback function that gets calls when the argmatcher gets used, allowing it to defer potentially expensive initialization work until it's actually needed. An argmatcher can also define a separate "delayed initialization" function for each argument position.
.Delayed initialization for the argmatcher up top
You can use _argmatcher:setdelayinit() to set a function that performs delayed initialization for the argmatcher. The function receives up to two parameters:
argmatcher
is the argmatcher to be initialized.- In Clink v1.3.12 and higher,
command_word
is the word in the command line that matched this argmatcher.
If the definition needs to adapt based on the current directory or other criteria, then the callback function should first test whether the definition needs to change. If so, first reset the argmatcher and then initialize it. To reset the argmatcher, use _argmatcher:reset() which resets it back to an empty, freshly created state.
local prev_dir = ""
-- Initialize the argmatcher.
-- v1.3.12 and higher receive a command_word parameter as well, which is the
-- word in the command line that matched this argmatcher.
local function init(argmatcher, command_word)
local r = io.popen("some_command --help 2>nul")
for line in r:lines() do
-- PUT PARSING CODE HERE.
-- Use the Lua string functions to parse the lines.
-- Use argmatcher:addflags(), argmatcher:addarg(), etc to initialize the argmatcher.
end
r:close()
end
-- This function has the opportunity to reset and (re)initialize the argmatcher.
local function ondelayinit(argmatcher, command_word)
local dir = os.getcwd()
if prev_dir ~= dir then -- When current directory has changed,
prev_dir = dir -- Remember the new current directory,
argmatcher:reset() -- Reset the argmatcher,
init(argmatcher, command_word) -- And re-initialize it.
end
end
-- Create the argmatcher and set up delayed initialization.
local m = clink.argmatcher("some_command")
if m.setdelayinit then -- Can't use setdelayinit before Clink v1.3.10.
m:setdelayinit(ondelayinit)
end
.Delayed initialization for an argument position up top
If the overall flags and meaning of the argument positions don't need to be updated, and only the possible values need to be updated within certain argument positions, then you can include delayinit=function
in the argument table.
The function should return a table of matches which will be added to the values for the argument position. The table of matches supports the same syntax as _argmatcher:addarg(). The function receives two parameters:
argmatcher
is the current argmatcher.argindex
is the argument position in the argmatcher (0 is flags, 1 is the first argument position, 2 is the second argument position, and so on).
The function is called only once, the first time the argument position is used. The only way for the function to be called again for that argmatcher is to use Delayed initialization for the argmatcher and reset the argmatcher and then re-initialize it.
Delayed initialization for an argument position is different from Functions As Argument Options. The delayinit
function is called the first time the argmatcher is used, and the results are added to the matches for the rest of the Clink session. But a function as an argument option is called every time matches are generated for the argument position, and it is never called when applying input line coloring.
-- A function to delay-initialize argument values.
-- This function is used to delay-initialize two different argument positions,
-- and so it gets called up to two separate times (once for each position where
-- it is specified).
-- If the function needs to behave slightly differently for different
-- argmatchers or argument positions, it can use the two parameters it receives
-- to identify the specific context in which it is being called.
local function sc_init_dirs(argmatcher, argindex)
return {
path.join(os.getenv("USERPROFILE"), "Documents"),
path.join(os.getenv("USERPROFILE"), "Pictures")
}
end
-- A function to delay-initialize flag values.
local function sc_init_flags(argmatcher)
-- This calls sc_init_dirs() when the '--dir=' flag is used.
return { "--dir=" .. clink.argmatcher():addarg({ delayinit=sc_init_dirs }) }
end
-- Define an argmatcher with two argument positions, and the second one uses
-- delayed initialization.
local m = clink.argmatcher("some_command")
m:addarg({ "abc", "def", "ghi" })
m:addarg({ delayinit=sc_init_dirs }) -- This sc_init_dirs() when the second arg position is used.
-- You can also use delayinit with flags, but you must set the flag prefix
-- character(s) so that Clink can know when to call the delayinit function.
m:addflags({ delayinit=sc_init_flags })
m:setflagprefix("-")
.Responding to Arguments in Argmatchers up top
Argmatchers can be more involved in parsing the command line, if they wish.
An argmatcher can supply "on advance" or "on arg" functions to be called when the argmatcher parses an argument position. The functions can influence parsing the rest of the input line. For example, the presence of a flag --only-dirs
might change what match completions should be provided somewhere else in the input line.
- An "on advance" function is called before parsing a word. It can influence which argument position will parse the word (it can advance to the next position before parsing, or it can repeat the same argument position for parsing both the current word and the next word).
- An "on alias" function is called before parsing a word. It can examine the word and return some other text to parse instead.
- An "on arg" function is called when parsing a word. It can examine the word and do custom processing.
- An "on link" function is called after parsing a word. It can examine the word and override what argmatcher it links to (see Linking Parsers).
All of these callback functions receive a user_data
table. Your "on advance" and "on arg" and "on link" functions can set data into the table, and functions called later during parsing can get the data that was set by earlier functions (for example to keep track of what flags were specified earlier in the command line). When parsing begins for a command, the user_data
is an empty table. Each time a flag or argument links to another argmatcher, the new argmatcher gets a separate new empty user_data
table. In Clink v1.6.10 and higher, each user_data
table contains a shared_user_data
field which is a reference to another table. The user_data.shared_user_data
enables linked argmatchers to share data with each other while parsing a command.
Note: These callback functions are called very often, so they need to be very fast or they can cause responsiveness problems while typing.
.The "on advance" function up top
Supply an "on advance" function by including onadvance=function
in the argument table with _argmatcher:addarg(). The function can return an integer to choose how to advance through the argument positions.
To use this, Clink v1.5.14 or higher is required.
The function receives five arguments:
arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a string containing the word being parsed. If it's the word under the cursor, then the string will be empty, or if a filename is being entered then it will be the path portion (e.g. for "dir1\dir2\pre"word
will be "dir1\dir2").word_index
is the word index inline_state
, corresponding to the argument being parsed.line_state
is a line_state object that contains the words for the associated command line.user_data
is a table that the argmatcher can use to help it parse the input line (see Responding to Arguments in Argmatchers for details).
The function may return any of the following values:
- Return
1
to advance to the next argument position before parsing the word (normally the parser advances after parsing a word). Multiple advances are possible for the same word: if the "on advance" functions for argument positions 2, 3, and 4 all return1
, then argument position 5 will parse the word. - Return
0
to repeat using same argument position to parse both the current word and the next word. Multiple repetitions are possible for the same argument position: if the "on advance" function for argument position 3 returns0
for three words in a row, then all three of the words are parsed using argument position 3. - Return
-1
to behave as though :chaincommand() were used, and start parsing a new command line beginning atword_index
. To start at the next word index, see the "chain next" example below. - Return
nil
(eitherreturn nil
or justreturn
) to advance to the next argument position after parsing the word (this is the default behavior).
In Clink v1.6.2 and higher, when returning -1
the function may also return a second value which is a string that lets Clink know how the command will get interpreted. The string is the same as the modes argument in :chaincommand().
This example demonstrates treating arg index 1 as an optional title string only if quoted:
local function maybe_string(arg_index, word, word_index, line_state, user_data)
local info = line_state:getwordinfo(word_index)
if not info.quoted then
return 1 -- Advance; this arg position is optional and only accepts a
-- quoted string. Anything else can't be parsed by this
-- argument position.
end
end
clink.argmatcher("start")
:addarg({
onadvance = maybe_string,
fromhistory = true,
})
:addflags({
"/min", "/max",
"/wait", "/b",
"/d"..clink.argmatcher():addarg(clink.dirmatches),
})
:chaincommand()
This example demonstrates how to chain on the next word, or also on the current word:
foo chain bar
chains starting at word 3 ("bar").foo whatever.exe
chains starting at word 2 ("whatever.exe").
local function chain_on_word(arg_index, word, word_index, line_state, user_data)
if user_data.do_chain then
return -1 -- Chain command because the "chain" keyword was seen previously.
elseif word == "chain" then
user_data.do_chain = true -- Remember that the "chain" keyword was seen.
return 0 -- Use the same arg_index for the next word index.
elseif path.getextension(word) ~= "" then
return -1 -- Chain command immediately when the word has an extension.
end
end
clink.argmatcher("foo")
:addarg({
onadvance=chain_on_keyword,
"abc", "def", "ghi",
})
:nofiles()
.The "on alias" function up top
Supply an "on alias" function by including onalias=function
in the argument table with _argmatcher:addarg(). The function can examine the word and return some other text to parse instead.
To use this, Clink v1.6.18 or higher is required.
The function receives five arguments:
arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a string containing the word being parsed.word_index
is the word index inline_state
, corresponding to the argument being parsed.line_state
is a line_state object that contains the words for the associated command line.user_data
is a table that the argmatcher can use to help it parse the input line (see Responding to Arguments in Argmatchers for details).
If the function returns nothing, then parsing continues as usual.
If the function returns a string, then the words in the string are parsed instead. When those words are finished being parsed, then parsing continues with the rest of the remaining words from the input line.
If the function returns a string and true
, then the words in the string are parsed, but they begin a new command (similar to :chaincommand()). When those words are finished being parsed, then parsing continues with the rest of the remaining words from the input line.
For example, the init()
function in the git.lua script in clink-completions repo uses this to enable completion to work with custom git aliases.
.The "on arg" function up top
Supply an "on arg" function by including onarg=function
in the argument table with _argmatcher:addarg(). The function can examine the word and do custom processing.
To use this, Clink v1.3.3 or higher is required.
The function receives five arguments:
arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a string containing the word being parsed. If it's the word under the cursor, then the string will be empty, or if a filename is being entered then it will be the path portion (e.g. for "dir1\dir2\pre"word
will be "dir1\dir2").word_index
is the word index inline_state
, corresponding to the argument being parsed.line_state
is a line_state object that contains the words for the associated command line.user_data
is a table that the argmatcher can use to help it parse the input line (see Responding to Arguments in Argmatchers for details).
The function doesn't return anything.
An "on arg" function can even use os.chdir() to set the current directory. Generating match completions saves and restores the current directory when finished, so argmatcher "on arg" functions can set the current directory and thus cause match completion later in the input line to complete file names relative to the change directory. For example, the built-in cd
and pushd
argmatches use an "on arg" function so that pushd \other_dir & program
Tab can complete file names from \other_dir
instead of the (real) current directory.
local function onarg_pushd(arg_index, word, word_index, line_state, user_data)
-- Match generation after this is relative to the new directory.
if word ~= "" then
os.chdir(word)
end
end
clink.argmatcher("pushd")
:addarg({
onarg=onarg_pushd, -- Chdir to the directory argument.
clink.dirmatches, -- Generate directory matches.
})
:nofiles()
.The "on link" function up top
Supply an "on link" function by including onlink=function
in the argument table with _argmatcher:addarg(). The function can return an argmatcher to override when to link to another parser, and which parser to link to.
To use this, Clink v1.5.14 or higher is required.
The function receives six arguments:
link
is the linked argmatcher, if any, that will be used if this function returnsnil
.arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a string containing the word being parsed. If it's the word under the cursor, then the string will be empty, or if a filename is being entered then it will be the path portion (e.g. for "dir1\dir2\pre"word
will be "dir1\dir2").word_index
is the word index inline_state
, corresponding to the argument being parsed.line_state
is a line_state object that contains the words for the associated command line.user_data
is a table that the argmatcher can use to help it parse the input line (see Responding to Arguments in Argmatchers for details).
The function may return any of the following:
- Return an argmatcher to override subsequent parsing and use the specified argmatcher.
- Return
false
ornil
to allow parsing to continue normally.
Note: Avoid creating new argmatchers in "on link" functions; instead return cached argmatchers that were previously created. The "on link" functions may be called frequently, and creating new argmatchers every time can create responsiveness problems while typing.
This example demonstrates linking to another argmatcher if the first argument is any .txt file. Any other value for the first argument continues using the same argmatcher to parse the rest of the command.
foo file.txt open abc
foo file.doc abc
local txt_file_actions = clink.argmatcher():addarg({"open", "print"})
local function maybe_txt_actions(link, arg_index, word, word_index, line_state, user_data)
-- If a txt file name is specified, link to another argmatcher.
if path.getextension(word):lower() == ".txt" then
return txt_file_actions
end
-- Otherwise continue normally with the current argmatcher.
end
clink.argmatcher("foo")
:addarg({
onlink=maybe_txt_actions, -- Link to another argmatcher only when any .txt file is specified.
clink.filematches,
})
:addarg("abc", "xyz")
:nofiles()
.Shorthand up top
It is also possible to omit the addarg
and addflags
function calls and use a more declarative shorthand form:
-- Shorthand form; requires tables.
clink.argmatcher()
{ "one", "won" } -- Arg #1
{ "two", "too" } -- Arg #2
{ "-a", "-b", "/?", "/h" } -- Flags
-- Normal form:
clink.argmatcher()
:addarg({ "one", "won" }) -- Arg #1
:addarg({ "two", "too" }) -- Arg #2
:addflags("-a", "-b", "/?", "/h") -- Flags
With the shorthand form flags are implied rather than declared. When a shorthand table's first value is a string starting with -
or /
then the table is interpreted as flags. Note that it's still possible with shorthand form to mix flag prefixes, and even add additional flag prefixes, such as { '-a', '/b', '=c' }
.
.Match Generators up top
These are Lua functions that are called as part of Readline's completion process (for example when pressing Tab).
Using a match generator enables lets you do custom parsing for the input line, or provide completions for the first word in the input line. Otherwise, using an argmatcher will probably be both easier and more powerful.
The Basics | A quick example to show the basics. |
More Advanced Stuff | |
Filtering Match Completions | How to modify how completion happens. |
Filtering the Match Display | How to modify how possible completions are displayed. |
.The Basics up top
First create a match generator object:
local my_generator = clink.generator(priority)
The priority argument is a number that influences when the generator gets called, with lower numbers going before higher numbers.
.The :generate() Function up top
Next define a match generator function on the object, taking the following form:
function my_generator:generate(line_state, match_builder)
-- Use the line_state object to examine the current line and create matches.
-- Submit matches to Clink using the match_builder object.
-- Return true or false.
end
line_state is a line_state object that has information about the current line.
match_builder is a builder object to which matches can be added.
If no further match generators need to be called then the function should return true. Returning false or nil continues letting other match generators get called.
Here is an example script that supplies git branch names as matches for git checkout
. This example doesn't handle git aliases, but that could be added with additional script code.
local git_branch_autocomplete = clink.generator(1)
local function starts_with(str, start)
return string.sub(str, 1, string.len(start)) == start
end
local function is_checkout_ac(text)
if starts_with(text, "git checkout") then
return true
end
return false
end
local function get_branches()
-- Run git command to get branches.
local handle = io.popen("git branch -a 2>&1")
local result = handle:read("*a")
handle:close()
-- Parse the branches from the output.
local branches = {}
if starts_with(result, "fatal") == false then
for branch in string.gmatch(result, " %S+") do
branch = string.gsub(branch, " ", "")
if branch ~= "HEAD" then
table.insert(branches, branch)
end
end
end
return branches
end
function git_branch_autocomplete:generate(line_state, match_builder)
-- Check if it's a checkout command.
if not is_checkout_ac(line_state:getline()) then
return false
end
-- Get branches and add them (does nothing if not in a git repo).
local matchCount = 0
for _, branch in ipairs(get_branches()) do
match_builder:addmatch(branch)
matchCount = matchCount + 1
end
-- If we found branches, then stop other match generators.
return matchCount > 0
end
.The :getwordbreakinfo() Function up top
If needed, a generator can optionally influence word breaking for the end word by defining a :getwordbreakinfo()
function.
The function takes a line_state argument which is a line_state object that has information about the current line.
If it returns nil or 0, the end word is truncated to 0 length. This is the normal behavior, which allows Clink to collect and cache all matches and then filter them based on typing. Or it can return two numbers: word break length and an optional end word length. The end word is split at the word break length: one word contains the first word break length characters from the end word (if 0 length then it's discarded), and the next word contains the rest of the end word truncated to the optional word length (0 if omitted).
A good example to look at is Clink's own built-in environment variable match generator. It has a :getwordbreakinfo()
function that understands the %
syntax of environment variables and produces word break info accordingly.
When the environment variable match generator's :getwordbreakinfo()
function sees the end word is abc%USER
it returns 3,1
so that the last two words become "abc" and "%" so that its generator knows it can do environment variable matching. But when it sees abc%FOO%def
it returns 8,0
so that the last two words become "abc%FOO%" and "" so that its generator won't do environment variable matching, and also so other generators can produce matches for what follows, since "%FOO%" is an already-completed environment variable and therefore should behave like a word break. In other words, it breaks the end word differently depending on whether the number of percent signs is odd or even, to account for environent variable syntax rules.
And when an argmatcher sees the end word begins with a flag character it returns 0,1
so the end word contains only the flag character in order to switch from argument matching to flag matching.
Note: The
:getwordbreakinfo()
function is called very often, so it needs to be very fast or it can cause responsiveness problems while typing.
local envvar_generator = clink.generator(10)
function envvar_generator:generate(line_state, match_builder)
-- Does the word end with a percent sign?
local word = line_state:getendword()
if word:sub(-1) ~= "%" then
return false
end
-- Add env vars as matches.
for _, i in ipairs(os.getenvnames()) do
match_builder:addmatch("%"..i.."%", "word")
end
match_builder:setsuppressappend() -- Don't append a space character.
match_builder:setsuppressquoting() -- Don't quote envvars.
return true
end
function envvar_generator:getwordbreakinfo(line_state)
local word = line_state:getendword()
local in_out = false
local index = nil
-- Paired percent signs denote already-completed environment variables.
-- So use envvar completion for abc%foo%def%USER but not for abc%foo%USER.
for i = 1, #word do
if word:sub(i, i) == "%" then
in_out = not in_out
if in_out then
index = i - 1
else
index = i
end
end
end
-- If there were any percent signs, return word break info to influence the
-- match generators.
if index then
return index, (in_out and 1) or 0
end
end
.More Advanced Stuff up top
.Filtering Match Completions up top
A match generator or argmatcher or luafunc: key binding can use clink.onfiltermatches() to register a function that will be called after matches are generated but before they are displayed or inserted (this is reset every time match generation is invoked).
The function receives a table argument containing the matches to be displayed, a string argument indicating the completion type, and a boolean argument indicating whether filename completion is desired. The table argument has a match
string field and a type
string field; these are the same as in builder:addmatch(). In Clink v1.6.5 and newer, the table includes the full set of match fields, especially including the display
field.
The possible completion types are:
Type | Description | Example |
---|---|---|
"?" |
List the possible completions. | possible-completions or popup-complete |
"*" |
Insert all of the possible completions. | insert-completions |
"\t" |
Do standard completion. | complete |
"!" |
Do standard completion, and list all possible completions if there is more than one. | complete (when the show-all-if-ambiguous config variable is set) |
"@" |
Do standard completion, and list all possible completions if there is more than one and partial completion is not possible. | complete (when the show-all-if-unmodified config variable is set) |
"%" |
Do menu completion (cycle through possible completions). | menu-complete or old-menu-complete |
The return value is a table with the input matches filtered as desired. The match filter function can remove matches, but cannot add matches (use a match generator instead). If only one match remains after filtering, then many commands will insert the match without displaying it. This makes it possible to spawn a process (such as fzf) to perform enhanced completion by interactively filtering the matches and keeping only one selected match.
settings.add("fzf.height", "40%", "Height to use for the --height flag")
settings.add("fzf.exe_location", "", "Location of fzf.exe if not on the PATH")
-- Build a command line to launch fzf.
local function get_fzf()
local height = settings.get("fzf.height")
local command = settings.get("fzf.exe_location")
if not command or command == "" then
command = "fzf.exe"
else
command = os.getshortname(command)
end
if height and height ~= "" then
command = command..' --height '..height
end
return command
end
local fzf_complete_intercept = false
-- Sample key binding in .inputrc:
-- M-C-x: "luafunc:fzf_complete"
function fzf_complete(rl_buffer)
fzf_complete_intercept = true
rl.invokecommand("complete")
if fzf_complete_intercept then
rl_buffer:ding()
end
fzf_complete_intercept = false
rl_buffer:refreshline()
end
local function filter_matches(matches, completion_type, filename_completion_desired)
if not fzf_complete_intercept then
return
end
-- Start fzf.
local r,w = io.popenrw(get_fzf()..' --layout=reverse-list')
if not r or not w then
return
end
-- Write matches to the write pipe.
for _,m in ipairs(matches) do
w:write(m.match.."\n")
end
w:close()
-- Read filtered matches.
local ret = {}
while (true) do
local line = r:read('*line')
if not line then
break
end
for _,m in ipairs(matches) do
if m.match == line then
table.insert(ret, m)
end
end
end
r:close()
-- Yay, successful; clear it to not ding.
fzf_complete_intercept = false
return ret
end
local interceptor = clink.generator(0)
function interceptor:generate(line_state, match_builder)
-- Only intercept when the specific key binding command was used.
if fzf_complete_intercept then
clink.onfiltermatches(filter_matches)
end
return false
end
Note: A much more complete fzf integration script is available at clink-gizmos or clink-fzf.
.Filtering the Match Display up top
In some instances it may be preferable to display different text when listing potential matches versus when inserting a match in the input line, or to display a description next to a match. For example, it might be desirable to display a *
next to some matches, or to show additional information about some matches.
The simplest way to do that is just include the display
and/or description
fields when using builder:addmatch(). Refer to that function's documentation for usage details.
However, older versions of Clink don't support those fields. And in some cases it may be desirable to display a list of possible completions that includes extra matches, or omits some matches (but that's discouraged because it can be confusing to users).
A match generator or argmatcher or luafunc: key binding can alternatively use clink.ondisplaymatches() to register a function that will be called before matches are displayed (this is reset every time match generation is invoked).
The function receives a table argument containing the matches to be displayed, and a boolean argument indicating whether they'll be displayed in a popup window. The table argument has a match
string field and a type
string field; these are the same as in builder:addmatch().
The return value is a table with the input matches filtered as required by the match generator. The returned table can also optionally include a display
string field and a description
string field. When present, display
will be displayed instead of the match
field, and description
will be displayed next to the match. Putting the description in a separate field enables Clink to align the descriptions in a column.
Filtering the match display can affect completing matches: the match
field is what gets inserted. It can also affect displaying matches: the display
field is displayed if present, otherwise the match
field is displayed.
If a match's type
is "none" or its match
field is different from its display
field then the match is displayed using the color specified by the color.filtered Clink setting, otherwise normal completion coloring is applied. The display
and description
fields can include ANSI escape codes to apply other colors if desired.
local function my_filter(matches, popup)
local new_matches = {}
local magenta = "\x1b[35m"
local filtered = settings.get("color.filtered")
for _,m in ipairs(matches) do
if m.match:find("[0-9]") then
-- Ignore matches with one or more digits.
else
-- Keep the match, and also add a magenta * prefix to directory matches.
if m.type:find("^dir") then
m.display = magenta.."*"..filtered..m.match
end
table.insert(new_matches, m)
end
end
return new_matches
end
function my_match_generator:generate(line_state, match_builder)
...
clink.ondisplaymatches(my_filter)
end
Compatibility Notes:
- In v1.3.1 and higher, the table received by the registered ondisplaymatches function includes all the match fields (such as
display
,description
,appendchar
, etc), and the function can include any of these fields in the table it returns. In other words, in v1.3.1 and higher match filtering supports all the same fields as builder:addmatch().- In v1.5.4 and higher, the table received by the registered ondisplaymatches function can include an
arginfo
field, and the function can includearginfo
in the table it returns.
.Coloring the Input Text up top
When the clink.colorize_input
setting is enabled, then argmatchers automatically apply colors to the input text as they parse it. When the setting is disabled, then the entire input line is colored by the color.input
setting.
See Color Themes for information on loading and saving color theme files (whose names end with ".clinktheme").
Coloring the Command Word | How the command word is colored. |
Coloring Command Separators and Redirection | How special characters are colored. |
Coloring Other Input Text | How other text is colored. |
More Advanced Stuff | |
Setting a classifier function in an argmatcher | How to apply colors for arguments. |
Setting a classifier function for the whole input line | How to apply colors anywhere in the line. |
.Coloring the Command Word up top
The command word is colored based on the command type, in priority order:
- Commands that have an argmatcher defined use
color.argmatcher
. - Built-in CMD commands use
color.cmd
. - Doskey aliases use
color.doskey
. - Recognized executable files use
color.executable
if it is set. - Unrecognized command words use
color.unrecognized
if it is set. - If none of the above apply, then
color.input
is used.
Here are examples, using the colors from the Use enhanced defaults installation option:
c:\dir>clink 'clink' has an argmatcher
c:\dir>attrib 'attrib' is a CMD command
c:\dir>myalias if 'myalias' is a doskey alias
c:\dir>control 'control' is an executable
c:\dir>xyzabc123 unrecognized
c:\dir>whatever if executable and unrecognized colors are not set
.Coloring Command Separators and Redirection up top
Command separators and redirection are colored accordingly:
- Command separators use
color.cmdsep
. - Redirection symbols use
color.cmdredir
. - Redirected files use
color.input
.
Here are examples, using the colors from the Use enhanced defaults installation option:
c:\dir>pushd & popd '&' is the command separator
c:\dir>set >file redirecting 'set' to 'file'
.Coloring Other Input Text up top
Other input words are colored based on how argmatchers parse the input text.
- If an argmatcher isn't defined for a command, then the input text is colored using
color.input
. - Flags defined by the command's argmatcher use
color.flag
. - Arguments defined by the command's argmatcher use
color.arg
. - Text that goes past what the command's argmatcher expects uses
color.unexpected
. - Auto-suggestion text uses
color.suggestion
.
Here are examples, using the colors from the Use enhanced defaults installation option:
c:\dir>clink --help '--help' is defined as a flag for 'clink'
c:\dir>clink set 'set' is defined as an argument for 'clink'
c:\dir>clink set color.arg 'color.arg' is defined as an argument for 'clink set'
c:\dir>clink set abc.xyz 'abc.xyz' is not a recognized argument for 'clink set'
c:\dir>findstr /s needle haystack\* if 'findstr' has no argmatcher, all words use 'color.input'
c:\dir>findstr /s_needle haystack\* press RIGHT to insert an auto-suggestion
.More Advanced Stuff up top
.Setting a classifier function in an argmatcher up top
In cases where an argmatcher isn't able to color the input text in the desired manner, it's possible to supply a classifier function that overrides how the argmatcher colors the input text. An argmatcher's classifier function is called once for each word the argmatcher parses, but it can classify any words (not just the word it was called for). Each argmatcher can have its own classifier function, so when there are linked argmatchers more than one function may be invoked.
The classifier function is passed up to six arguments:
arg_index
is the argument index in the argmatcher, corresponding to the argument being parsed. 0 means it is a flag, rather than an argument.word
is a partial string for the word under the cursor, corresponding to the argument for which matches are being generated: it is an empty string, or if a filename is being entered then it will be the path portion (e.g. for "dir1\dir2\pre"word
will be "dir1\dir2").word_index
is the word index inline_state
, corresponding to the argument for which matches are being generated.line_state
is a line_state object that contains the words for the associated command line.classifications
is a word_classifications object which can be used to apply colors.- In Clink v1.5.17 and higher,
user_data
is a table that the argmatcher can use to help it parse the input line (see Responding to Arguments in Argmatchers for details).
Words are colored by classifying the words, and each classification has an associated color. See word_classifications:classifyword() for the available classification codes.
The clink set
command has different syntax depending on the setting type, so the argmatcher for clink
needs help in order to get everything right. A custom generator function parses the input text to provide appropriate matches, and a custom classifier function applies appropriate coloring.
-- In this example, the argmatcher matches a directory as the first argument and
-- a file as the second argument. It uses a word classifier function to classify
-- directories (words that end with a path separator) as "unexpected" in the
-- second argument position.
local function classify_handler(arg_index, word, word_index, line_state, classifications, user_data)
-- `arg_index` is the argument position in the argmatcher.
-- In this example only position 2 needs special treatent.
if arg_index ~= 2 then
return
end
-- `arg_index` is the argument position in the argmatcher.
-- `word_index` is the word position in the `line_state`.
-- Ex1: in `samp dir file` for the word `dir` the argument index is 1 and
-- the word index is 2.
-- Ex2: in `samp --help dir file` for the word `dir` the argument index is
-- still 1, but the word index is 3.
-- `word` is the word the classifier function was called for and `word_index`
-- is its position in the line. Because `line_state` is also provided, the
-- function can examine any words in the input line.
if word:sub(-1) == "\\" then
-- The word appears to be a directory, but this example expects only
-- files in argument position 2. Here the word gets classified as "n"
-- (unexpected) so it gets colored differently.
classifications:classifyword(word_index, "n")
end
end
local matcher = clink.argmatcher("samp")
:addflags("--help")
:addarg({ clink.dirmatches })
:addarg({ clink.filematches })
:setclassifier(classify_handler)
.Setting a classifier function for the whole input line up top
In some cases it may be desireable to use a custom classifier to apply coloring in an input line.
First create a classifier object:
local my_classifier = clink.classifier(priority)
The priority argument is a number that influences when the classifier gets called, with lower numbers going before higher numbers.
Next define a classify function on the object, taking the following form:
function my_classifier:classify(commands)
-- See further below for how to use the commands argument.
-- Returning true stops any further classifiers from being called, or
-- returning false or nil continues letting other classifiers get called.
end
commands is a table of tables, with the following scheme:
-- commands[n].line_state [line_state] Contains the words for the Nth command.
-- commands[n].classifications [word_classifications] Use this to classify the words.
The line_state
field is a line_state object that contains the words for the associated command line.
The classifications
field is a word_classifications object to use for classifying the words in the associated command line.
-- In this example, a custom classifier applies colors to environment variables
-- in the input line.
local envvar_classifier = clink.classifier(50)
function envvar_classifier:classify(commands)
-- This example doesn't need to parse words within commands, it just wants
-- to parse the whole line.
--
-- So it can simply use the first command's `classifications` object because
-- the `classifications:applycolor()` method can apply color anywhere in the
-- entire input line.
--
-- (Note that the `classifications:classifyword()` method can only affect
-- the words for its corresponding command.)
if commands[1] then
local line_state = commands[1].line_state
local classifications = commands[1].classifications
local line = line_state:getline()
local len = #line
-- Loop through the line looking for environment variables, starting at
-- the first character of the line.
local idx = 1
while (idx <= len) do
-- Find the next percent sign (idx is walking through the line).
local pos = line:find('%', idx, true--[[plain]])
if not pos then
-- No more? Then all done.
break
end
-- Find the next percent sign (which would close the possible
-- environment variable).
local posend = line:find('%', pos + 1, true--[[plain]])
if not posend then
-- No close? Then all done.
break
end
-- Extract the text between the percent signs and check if there
-- is an environment variable by that name.
local name = line:sub(pos + 1, posend - 1)
if name == '' then
-- Skip a double percent. It's an escaped percent sign, not an
-- environment variable.
idx = posend + 1
elseif os.getenv(name) then
-- Apply a color to the environment variable.
classifications:applycolor(pos, posend - pos + 1, "95")
idx = posend + 1
else
-- Ignore the percent sign, but continue looking for more.
idx = idx + 1
end
end
end
end
.Customizing the Prompt up top
Before Clink displays the prompt it filters the prompt through Lua so that the prompt can be customized. This happens each and every time that the prompt is shown which allows for context sensitive customizations (such as showing the current branch of a git repository).
See Custom Prompts for information on loading custom prompt files (whose names end with ".clinkprompt").
The Basics | A quick example to show the basics. |
ANSI escape codes in the prompt string | How special characters are colored. |
Sharing Custom Prompts | How to share your custom prompt with other people as a *.clinkprompt file. |
More Advanced Stuff | |
Right Side Prompt | How to add prompt text at the right edge of the terminal. |
Asynchronous Prompt Filtering | How to make the prompt show up instantly. |
Transient Prompt | How to display completed prompts differently than the current prompt. |
.The Basics up top
Writing a prompt filter is straightforward:
- Create a new prompt filter by calling clink.promptfilter() along with a priority id which dictates the order in which filters are called. Lower priority ids are called first.
- Define a
:filter()
function on the returned prompt filter.
The filter function takes a string argument that contains the filtered prompt so far.
If the filter function returns nil, it has no effect. If the filter function returns a string, that string is used as the new filtered prompt (and may be further modified by other prompt filters with higher priority ids). If the filter function returns a string and a boolean, then if the boolean is false the prompt filtering is done and no further filter functions are called.
local p = clink.promptfilter(30)
function p:filter(prompt)
return "new prefix "..prompt.." new suffix" -- Add ,false to stop filtering.
end
The following example illustrates setting the prompt, modifying the prompt, using ANSI escape code for colors, running a git command to find the current branch, and stopping any further processing.
local green = "\x1b[92m"
local yellow = "\x1b[93m"
local cyan = "\x1b[36m"
local normal = "\x1b[m"
-- A prompt filter that discards any prompt so far and sets the
-- prompt to the current working directory. An ANSI escape code
-- colors it yellow.
local cwd_prompt = clink.promptfilter(30)
function cwd_prompt:filter(prompt)
return yellow..os.getcwd()..normal
end
-- A prompt filter that inserts the date at the beginning of the
-- the prompt. An ANSI escape code colors the date green.
local date_prompt = clink.promptfilter(40)
function date_prompt:filter(prompt)
return green..os.date("%a %H:%M")..normal.." "..prompt
end
-- A prompt filter that may stop further prompt filtering.
-- This is a silly example, but on Wednesdays, it stops the
-- filtering, which in this example prevents git branch
-- detection and the line feed and angle bracket.
local wednesday_silliness = clink.promptfilter(60)
function wednesday_silliness:filter(prompt)
if os.date("%a") == "Wed" then
-- The ,false stops any further filtering.
return prompt.." HAPPY HUMP DAY! ", false
end
end
-- A prompt filter that appends the current git branch.
local git_branch_prompt = clink.promptfilter(65)
function git_branch_prompt:filter(prompt)
local line = io.popen("git branch --show-current 2>nul"):read("*a")
local branch = line:match("(.+)\n")
if branch then
return prompt.." "..cyan.."["..branch.."]"..normal
end
end
-- A prompt filter that adds a line feed and angle bracket.
local bracket_prompt = clink.promptfilter(150)
function bracket_prompt:filter(prompt)
return prompt.."\n> "
end
The resulting prompt will look like this:
Tue 12:54 c:\dir [master]
> _
...except on Wednesdays, when it will look like this:
Wed 12:54 c:\dir HAPPY HUMP DAY! _
.ANSI escape codes in the prompt string up top
Readline needs to be told which characters in the prompt are unprintable or invisible. To help with that, Clink automatically detects most standard ANSI escape codes (and most of ConEmu's non-standard escape codes) and the BEL character (^G, audible bell) and surrounds them with \001
(^A) and \002
(^B) characters. For any other unprintable characters, the \001
and \002
characters need to be added manually. Otherwise Readline misinterprets the length of the prompt and can display the prompt and input line incorrectly in some cases (especially if the input line wraps onto a second line).
Here are a couple of links with more information about ANSI escape codes:
.Sharing Custom Prompts up top
Custom prompts can be shared in Clink v1.7.0 and newer.
To make a custom prompt shareable, put it in a file whose name ends with ".clinkprompt" instead of ".lua".
For many custom prompts, it's as simple as that! Some prompts may want additional capabilities, which are described further below.
A .clinkprompt file can be shared and installed on other computers. If it's in a "themes" subdirectory under any of the script directories, then Clink can find it automatically (run clink info
and look for the "scripts" line in the output). If the file in some other directory, then you can use it by telling Clink the full path to the file.
Any prompt filters or registered event handlers (such as clink.onbeginedit) in a .clinkprompt file are only called while the prompt is active. Running clink config prompt use prompt_file
select a custom prompt which gets activated in each Clink session using the current profile directory. Only one .clinkprompt file at a time can be active.
.The "exports table" in a .clinkprompt file up top
A .clinkprompt file can return a table with certain fields which gain additional capabilities. Each field is optional, as is the table itself.
Field | Description |
---|---|
onactivate = function_name |
If function_name is not nil, then it's called when the prompt is loaded and activated. |
ondeactivate = function_name |
If function_name is not nil, then it's called when the prompt is deactivated. |
demo = function_name |
If function_name is not nil, then it's called when clink config prompt show is run. |
dependson = string |
If the string is not empty, then it is a list of clinkprompt names upon which this clinkprompt depends. When this clinkprompt file is loaded and activated, the other files are also loaded, and their prompt filters and event handlers are allowed to run even though they aren't part of the current active clinkprompt file. |
Here's a "Sample.clinkprompt" file to illustrate how to write .clinkprompt files, including the onactivate
and ondeactivate
and demo
functions.
--------------------------------------------------------------------------------
-- This is a sample clinkprompt module. It shows how (easy it is) to write a
-- clinkprompt module.
--
-- While a clinkprompt module is deactivated, it stops receiving calls to any
-- prompt filters or events it may have registered until the clinkprompt module
-- is reactivated later.
local norm = "\x1b[m"
local bold = "\x1b[1m"
local reverse = "\x1b[0;7m"
local red = "\x1b[91m"
local green = "\x1b[92m"
local darkgray = "\x1b[90m"
local symbol = ">"
--------------------------------------------------------------------------------
-- Normal prompt filter stuff...
local function cwdstring()
local cwd = os.getcwd()
return rl.collapsetilde(cwd, true)
end
local function errorlevelcolor()
return (os.geterrorlevel() == 0) and green or red
end
local p = clink.promptfilter(25)
function p:filter()
return bold..cwdstring()..norm.." "..errorlevelcolor()..symbol..norm.." "
end
function p:rightfilter()
return os.date("%a %H:%M", os.time())
end
function p:transientfilter()
return errorlevelcolor()..symbol..norm.." "
end
--------------------------------------------------------------------------------
-- Some event handlers...
local function onbeginedit()
print(darkgray.."-- SAMPLEPROMPT: onbeginedit --"..norm)
end
local function onendedit()
print(darkgray.."-- SAMPLEPROMPT: onendedit --"..norm)
end
clink.onbeginedit(onbeginedit)
clink.onendedit(onendedit)
--------------------------------------------------------------------------------
-- Special clinkprompt module stuff...
local function onactivate()
print(darkgray.."-- SAMPLEPROMPT: onactivate --"..norm)
end
local function ondeactivate()
print(darkgray.."-- SAMPLEPROMPT: ondeactivate --"..norm)
end
local function demo()
local left = bold..cwdstring()..norm.." "..green..symbol..norm.." "
local right = os.date("%a %H:%M", os.time())
left = left..reverse.." "..norm
local left_len = console.cellcount(left)
local right_len = console.cellcount(right)
local pad = ""
if left_len + 4 + right_len >= console.getwidth() then
right = ""
else
pad = string.rep(" ", console.getwidth() - (left_len + right_len))
end
print(left..pad..right)
end
local exports =
{
onactivate = onactivate,
ondeactivate = ondeactivate,
-- Uncomment this if you want to supply a custom demo function which will
-- be invoked by 'clink config prompt show Sample'.
--demo = demo,
}
-- Returning an exports table is optional, but allows the clinkprompt module to
-- print a custom demo from 'clink config prompt show Sample'.
return exports
.More Advanced Stuff up top
.Right Side Prompt up top
In addition to the normal prompt filtering, Clink can also show a prompt on the right side of the first line of input. The right side prompt defaults to the value of the %CLINK_RPROMPT%
environment variable, if set, otherwise it is blank. This right side prompt is automatically hidden if the input line text reaches it.
Clink expands CMD prompt $
codes in %CLINK_RPROMPT%
, with a few exceptions: $+
is not supported, $_
ends the prompt string (it can't be more than one line), and $V
is not supported. Additionally, if %CLINK_RPROMPT%
ends with $M
then trailing spaces are trimmed from the expanded string, to maintain right alignment since $M
includes a space if the current drive is a network drive (so e.g. $t $d $m
is right-aligned regardless whether the current drive has a remote name).
The right side prompt can be filtered through Lua just like the normal prompt can be. Simply define a :rightfilter()
function on the prompt filter returned by a call to clink.promptfilter(). A prompt filter can define both :filter()
and :rightfilter()
, or can define only :filter()
.
The :rightfilter()
function works the same as the :filter()
function, except that it operates on the right side prompt. It takes a string argument that contains the filtered right side prompt so far.
If the rightfilter function returns nil, it has no effect. If the rightfilter function returns a string, that string is used as the new filtered right side prompt (and may be further modified by other prompt filters with higher priority ids). If either the rightfilter function or the normal filter function returns a string and a boolean, then if the boolean is false the prompt filtering is done and no further filter functions are called.
This example modifies the right side prompt by prepending the current date:
local p = clink.promptfilter(30)
function p:filter(prompt)
-- The :filter() function must be defined. But if the prompt filter is
-- only interested in modifying the right side prompt, then the :filter()
-- function may do nothing.
end
function p:rightfilter(prompt)
local sep = #prompt > 0 and " " or ""
return os.date()..sep..prompt
end
Notes:
- If the console font and encoding are mismatched, or if some kinds of emojis are present, then the right side prompt might show up positioned incorrectly. If that happens, try adjusting the font or encoding (e.g. sometimes running
chcp utf-8
can resolve positioning issues).- If the
:filter()
function returns a string and false to stop filtering, then the:rightfilter()
is not called (because no further filter functions are called). If you want to stop filtering but have both a left and right side prompt, then return only a string from:filter()
and return a string and false from:rightfilter()
.
.Asynchronous Prompt Filtering up top
Prompt filtering needs to be fast, or it can interfere with using the shell (e.g. git status
can be slow in a large repo).
Clink provides a way for prompt filters to do some initial work and set the prompt, continue doing work in the background, and then refresh the prompt again when the background work is finished. This is accomplished by using Lua coroutines, but Clink simplifies and streamlines the process.
A prompt filter can call clink.promptcoroutine(my_func) to run my_func()
inside a coroutine. Clink will automatically resume the coroutine repeatedly while input line editing is idle. When my_func()
completes, Clink will automatically refresh the prompt by triggering prompt filtering again.
Typically the motivation to use asynchronous prompt filtering is that one or more io.popen("some slow command")
calls take too long. They can be replaced with io.popenyield() calls inside the prompt coroutine to let them run in the background.
Global data: If
my_func()
needs to use any global data, then it's important to use clink.onbeginedit() to register an event handler that can reset the global data for each new input line session. Otherwise the data may accidentally "bleed" across different input line sessions.Backward compatibility: A prompt filter must handle backward compatibility itself if it needs to run on versions of Clink that don't support asynchronous prompt filtering (v1.2.9 and lower). E.g. you can use
if clink.promptcoroutine then
to test whether the API exists.
The following example illustrates running git status
in the background. It also remembers the status from the previous input line, so that it can reduce flicker by using the color from last time until the background status operation completes.
Note: This is for illustration purposes and works when no other custom prompt filters are installed. If another custom prompt filter is present and runs earlier and chooses to halt further prompt filtering, then this example code might not get reached.
local prev_dir -- Most recent git repo visited.
local prev_info -- Most recent info retrieved by the coroutine.
local function collect_git_info()
-- This is run inside the coroutine, which happens while idle while waiting
-- for keyboard input.
local info = {}
info.status = git.getstatus()
-- Until this returns, the call to clink.promptcoroutine() will keep
-- returning nil. After this returns, subsequent calls to
-- clink.promptcoroutine() will keep returning this return value, until a
-- new input line begins.
return info
end
local git_prompt = clink.promptfilter(55)
function git_prompt:filter(prompt)
-- Do nothing if not a git repo.
local dir = git.getgitdir()
if not dir then
return
end
-- Reset the cached status if in a different repo.
if prev_dir ~= dir then
prev_info = nil
prev_dir = dir
end
-- Do nothing if git branch not available. Getting the branch name is fast,
-- so it can run outside the coroutine. That way the branch name is visible
-- even while the coroutine is running.
local branch = git.getbranch()
if not branch or branch == "" then
return
end
-- Start a coroutine to collect various git info in the background. The
-- clink.promptcoroutine() call returns nil immediately, and the
-- coroutine runs in the background. After the coroutine finishes, prompt
-- filtering is triggered again, and subsequent clink.promptcoroutine()
-- calls from this prompt filter immediately return whatever the
-- collect_git_info() function returned when it completed. When a new input
-- line begins, the coroutine results are reset to nil to allow new results.
local info = clink.promptcoroutine(collect_git_info)
-- If no status yet, use the status from the previous prompt.
if info == nil then
info = prev_info or {}
else
prev_info = info
end
-- Prefer using the branch name from git.getstatus(), once it's available.
if info.status and info.status.branch then
branch = info.status.branch
end
-- Choose color for the git branch name.: green if status is clean, yellow
-- if status is not clean, red if conflict is present, or default color if
-- status isn't known yet.
local sgr
if not info.status then
sgr = "39" -- Default color when status not available yet.
elseif info.status.conflict then
sgr = "31;1" -- Red when conflict.
elseif info.status.dirty then
sgr = "33;1" -- Yellow when dirty (changes are present).
else
sgr = "32;1" -- Green when status is clean.
end
-- Prefix the prompt with "[branch]" using the status color.
-- NOTE: This is for illustration purposes and works when no other custom
-- prompt filters are installed. If another custom prompt filter is present
-- and runs earlier and chooses to halt further prompt filtering, then this
-- example code might not get reached.
return "\x1b["..sgr.."m["..branch.."]\x1b[m "..prompt
end
.Transient Prompt up top
Clink can replace a past prompt with a differently formatted "transient" prompt. For example, if your normal prompt contains many bits of information that don't need to be seen later, then it may be desirable to replace past prompts with a simpler prompt. Or it may be useful to update the timestamp in a prompt to indicate when the prompt was completed, rather than when it was first shown.
The %CLINK_TRANSIENT_PROMPT%
environment variable provides the initial prompt string for the transient prompt.
Turn on the transient prompt with clink set prompt.transient always
. Or use same_dir
instead of always
to only use a transient prompt when the current directory is the same as the previous prompt.
The transient prompt can be customized by a prompt filter:
- Create a new prompt filter by calling clink.promptfilter() along with a priority id which dictates the order in which filters are called. Lower priority ids are called first.
- Define a
:transientfilter()
function on the returned prompt filter.
The transient filter function takes a string argument that contains the filtered prompt so far.
If the filter function returns nil, it has no effect. If the filter function returns a string, that string is used as the new filtered prompt (and may be further modified by other prompt filters with higher priority ids). If the filter function returns a string and a boolean, then if the boolean is false the prompt filtering is done and no further filter functions are called.
A transient right side prompt is also possible (similar to the usual right side prompt). The %CLINK_TRANSIENT_RPROMPT%
environment variable (note the R
in _RPROMPT
) provides the initial prompt string for the transient right side prompt, which can be customized by a :transientrightfilter()
function on a prompt filter.
A prompt filter must have a :filter()
function defined on it, and may in addition have any combination of :rightfilter()
, :transientfilter()
, and :transientrightfilter()
functions defined on it.
Related: The prompt.spacing setting can optionally remove blank lines before the prompt, and can optionally insert one blank line before the normal (non-transient) prompt.
The next example shows how to make a prompt that shows:
- The current directory and
>
on the left, and the date and time on the right. - Just
>
on the left, for past commands.
-- Colors for the prompt strings.
local cwd_color = "\x1b[0;1;37;44m"
local symbol_color = "\x1b[0;1;34m"
local date_color = "\x1b[0;36m"
local transient_date_color = "\x1b[0;1;30m"
local normal = "\x1b[m"
-- Create prompt filter.
local pf = clink.promptfilter(10)
-- Customize the normal prompt.
function pf:filter(prompt)
-- Don't return false yet; let rightfilter have a chance.
return cwd_color.." "..os.getcwd().." "..symbol_color.." > "..normal
end
-- Customize the normal right side prompt.
function pf:rightfilter(prompt)
-- If you have want stop further filtering, this is where to add returning false.
return date_color..os.date() --, false
end
-- Customize the transient prompt.
function pf:transientfilter(prompt)
-- Don't return false yet; let transientrightfilter have a chance.
return symbol_color.."> "..normal
end
-- Customize the transient right side prompt.
function pf:transientrightfilter(prompt)
-- Returns false to stop filtering.
return transient_date_color..os.date("%c", os.time()), false
end
-- Show a reminder to turn on the transient prompt, to try out the example.
if settings.get("prompt.transient") == "off" then
print("Use 'clink set prompt.transient same_dir' to enable the transient prompt.")
end
Note: In v1.4.25 and higher, the
:transientfilter()
or:transientrightfilter()
functions can suppress the transient prompt on a case by case basis by returningnil, false
.
.Prefix and Suffix Escape Codes up top
In some cases the prompt and/or right side prompt might need to be surrounded with special escape codes. For example, some file editors with integrated terminals want to receive additional escape codes surrounding the prompt strings.
After all prompt filters have finished, the last line of the final prompt string is automatically surrounded with the values of the %CLINK_PROMPT_PREFIX%
and %CLINK_PROMPT_SUFFIX%
environment variables, and the final right side prompt is automatically surrounded with the values of the %CLINK_RPROMPT_PREFIX%
and %CLINK_RPROMPT_SUFFIX%
environment variables.
The prompt prefix and suffix strings expand CMD prompt $
codes (run prompt /?
for more info). So, for example, $p
could be combined with escape codes to set the terminal window title to the current working directory. Consult documentation for your terminal program for information about what escape codes may be available.
Additionally, individual prompt filters may want to add escape codes surrounding the prompt strings. To do that, a prompt filter can define a :surround()
function which returns prefix and suffix strings.
local p = clink.promptfilter(-100) -- Negative number so it runs early.
function p:filter(prompt)
-- The :filter() function must be defined. But if the prompt filter is
-- only interested in surrounding the prompt with escape codes, then the
-- :filter() function may do nothing.
end
function p:surround()
-- For the normal (left side) prompt.
local prompt_prefix = "" -- Fill this in with escape codes to be printed before the prompt text.
local prompt_suffix = "" -- Fill this in with escape codes to be printed after the prompt text.
-- For the right side prompt (if any).
local rprompt_prefix = "" -- Fill this in with escape codes to be printed before the right side prompt text.
local rprompt_suffix = "" -- Fill this in with escape codes to be printed after the right side prompt text.
return prompt_prefix, prompt_suffix, rprompt_prefix, rprompt_suffix
end
Notes:
- The prefix and suffix strings should only contain escape code strings. Any printable text in the prefix and suffix strings could have unintended effects on displaying the prompt.
- Only the last line of the final prompt string is surrounded with the prefix and suffix. This is intended to help shell integration escape codes work properly.
.Customizing Suggestions up top
Clink can offer suggestions how to complete a command as you type, and you can select how it generates suggestions.
Turn on automatic suggestions with clink set autosuggest.enable true
. Once enabled, Clink will show suggestions in a muted color after the end of the typed command. Insert the whole suggestion with the Right arrow or End key, insert the next word of the suggestion with Ctrl-Right, or insert the next full word of the suggestion up to a space with Shift-Right. You can ignore the suggestion if it isn't what you want; suggestions have no effect unless you insert them.
Scripts can provide custom suggestion generators, in addition to the built-in options:
- Create a new suggestion generator by calling clink.suggester() along with a name that identifies the suggestion generator, and can be added to the
autosuggest.strategy
setting. - Define a
:suggest()
function on the returned suggestion generator.
The function takes a line_state argument that contains the input line, and a matches argument that contains the possible matches from the completion engine.
If the function returns nil, the next generator listed in the strategy is called. If the function returns a string (even an empty string), then the string is used as the suggestion. The function can optionally return a string and an offset to where the suggestion begins in the input line. This makes it easier to return suggestions in some cases, and also makes it possible to update the capitalization of the whole inserted suggestion (even the part that's already been typed).
This example illustrates how to make a suggestion generator that returns the longest common prefix of the possible matches.
local prefix_suggestor = clink.suggester("completion_prefix")
function prefix_suggestor:suggest(line_state, matches)
-- If the input line is empty or only spaces, don't suggest anything.
if not line_state:getline():match("[^ ]") then
return
end
-- If there is no common prefix, don't suggest anything.
local prefix = matches:getprefix()
if prefix == "" then
return
end
-- Return the common prefix as the suggestion.
local info = line_state:getwordinfo(line_state:getwordcount())
return prefix, info.offset
end
.Showing Input Hints up top
Clink can show contextual input hints while you type. Lua scripts can provide input hints. When a hint is available, it's shown in the comment row (below the input line). For example:
C:\dir>foo _
Argument expected: filename
To use this, Clink v1.7.0 or higher is required.
To turn on input hints, run clink set comment_row.show_hints true
. Lua scripts can add hinters to do things like show the value of an environment variable under the cursor, or show the value of a doskey macro, or show a hint about what kind of argument a command expects to be entered next, or other things. The clink-gizmos repo has some scripts that add hinters.
Scripts can provide custom input hint generators:
- Create a new hint generator by calling clink.hinter() along with an optional priority id which dictates the order in which hinters are called. Lower priority ids are called first.
- Define a
:gethint()
function on the returned hint generator.
The function takes a line_state argument that contains the input line.
If the function returns nil, the next hint generator is called. If the function returns a string (even an empty string), then the string is used as a hint candidate. The function can optionally return a string and a position in the line text where the hint refers to (for example, the offset to the beginning of a word). The hint string with the highest position not exceeding the cursor position is used as the "best hint" (if a hint is returned without a position, then the beginning of the line is assumed).
Note: The
:gethint
callback function is called very often, so it needs to be very fast or it can cause responsiveness problems while typing.
This example illustrates how to make an input hint generator that shows the offset of the start of the word under the cursor.
local hinter = clink.hinter()
function hinter:gethint(line_state)
local h, p
local cursorpos = line_state:getcursor()
for i = 1, line_state:getwordcount() do
local info = line_state:getwordinfo(i)
if info.offset <= cursorpos and cursorpos <= info.offset + info.length then
h = string.format("word starts at %d", info.offset)
p = info.offset
end
end
return h, p
end
.Miscellaneous top
These sections provide more information about various aspects of Clink:
Customizing Key Bindings | How to customize key bindings. |
Saved Command History | How the saved command history works. |
Using History Expansion | How to use history expansion. |
Directory Shortcuts | Convenient shortcuts for changing the current directory. |
Enhanced Doskey Expansion | How enhanced Doskey expansion works. |
Popular Scripts | Some popular scripts to enhance Clink. |
Terminal Support | Information about how Clink's terminal support works. |
How Clink Works | Technical details about how Clink injects into cmd.exe. |
Troubleshooting Tips | How to troubleshoot and report problems. |
Privacy | Privacy statement for Clink. |
.Customizing Key Bindings up top
Key bindings are defined in .inputrc files.
The clink-show-help
command is bound to Alt-H and lists all currently active key bindings. The list displays "friendly" key names, and these names are generally not suitable for use in .inputrc files. For example "Up" is the friendly name for "\e[A"
, and "A-C-F2" is the friendly name for "\e\e[1;5Q"
. To see key sequence strings suitable for use in .inputrc files use clink echo
as described below.
The .inputrc file | Where to find the .inputrc file, and more information about it. |
Discovering Clink key sequences | How to find key names to use for key bindings. |
Binding special keys | A table of special key names. |
Lua key bindings | How to bind keys to Lua functions. |
I do not have a Meta or Alt key | What to do if your keyboard doesn't have any Alt or Meta keys. |
.The .inputrc file up top
You can use clink info
to find the directories and configuration files for the current Clink session, including where the .inputrc file is located, or can be located. See the Readline Init File section for detailed information about .inputrc files.
Note: Third party console hosts such as ConEmu may have their own key bindings that supersede Clink. They usually have documentation for how to change or disable their key bindings to allow console programs to handle the keys instead.
.Discovering Clink key sequences up top
Clink provides an easy way to find the key sequence for any key combination that Clink supports. Run clink echo
and then press key combinations; the associated key binding sequence is printed to the console output and can be used for a key binding in the inputrc file.
A chord can be formed by concatenating multiple key binding sequences. For example, "\C-X"
and "\e[H"
can be concatenated to form "\C-X\e[H"
representing the chord Ctrl-X,Home.
When finished, press Ctrl-C to exit from clink echo
.
Note: With non-US keyboard layouts,
clink echo
is not able to ignore dead key input (accent keys, for example). It prints the key sequence for the dead key itself, which is not useful. You can ignore that and press the next key, and then it prints the correct key sequence to use in key bindings.
.Binding special keys up top
Here is a table of the key binding sequences for the special keys. Clink primarily uses VT220 emulation for keyboard input, but also uses some Xterm extended key sequences.
Normal | Shift | Ctrl | Ctrl-Shift | Alt | Alt-Shift | Alt-Ctrl | Alt-Ctrl-Shift | |
---|---|---|---|---|---|---|---|---|
Up | \e[A |
\e[1;2A |
\e[1;5A |
\e[1;6A |
\e[1;3A |
\e[1;4A |
\e[1;7A |
\e[1;8A |
Down | \e[B |
\e[1;2B |
\e[1;5B |
\e[1;6B |
\e[1;3B |
\e[1;4B |
\e[1;7B |
\e[1;8B |
Left | \e[D |
\e[1;2D |
\e[1;5D |
\e[1;6D |
\e[1;3D |
\e[1;4D |
\e[1;7D |
\e[1;8D |
Right | \e[C |
\e[1;2C |
\e[1;5C |
\e[1;6C |
\e[1;3C |
\e[1;4C |
\e[1;7C |
\e[1;8C |
Insert | \e[2~ |
\e[2;2~ |
\e[2;5~ |
\e[2;6~ |
\e[2;3~ |
\e[2;4~ |
\e[2;7~ |
\e[2;8~ |
Delete | \e[3~ |
\e[3;2~ |
\e[3;5~ |
\e[3;6~ |
\e[3;3~ |
\e[3;4~ |
\e[3;7~ |
\e[3;8~ |
Home | \e[H |
\e[1;2H |
\e[1;5H |
\e[1;6H |
\e[1;3H |
\e[1;4H |
\e[1;7H |
\e[1;8H |
End | \e[F |
\e[1;2F |
\e[1;5F |
\e[1;6F |
\e[1;3F |
\e[1;4F |
\e[1;7F |
\e[1;8F |
PgUp | \e[5~ |
\e[5;2~ |
\e[5;5~ |
\e[5;6~ |
\e[5;3~ |
\e[5;4~ |
\e[5;7~ |
\e[5;8~ |
PgDn | \e[6~ |
\e[6;2~ |
\e[6;5~ |
\e[6;6~ |
\e[6;3~ |
\e[6;4~ |
\e[6;7~ |
\e[6;8~ |
Tab | \t |
\e[Z |
\e[27;5;9~ |
\e[27;6;9~ |
- | - | - | - |
Space | Space |
\e[27;2;32~ |
\e[27;5;32~ |
\e[27;6;32~ |
- | - | \e[27;7;32~ |
\e[27;8;32~ |
Backspace | ^h |
\e[27;2;8~ |
Rubout |
\e[27;6;8~ |
\e^h |
\e[27;4;8~ |
\eRubout |
\e[27;8;8~ |
F1 | \eOP |
\e[1;2P |
\e[1;5P |
\e[1;6P |
\e\eOP |
\e\e[1;2P |
\e\e[1;5P |
\e\e[1;6P |
F2 | \eOQ |
\e[1;2Q |
\e[1;5Q |
\e[1;6Q |
\e\eOQ |
\e\e[1;2Q |
\e\e[1;5Q |
\e\e[1;6Q |
F3 | \eOR |
\e[1;2R |
\e[1;5R |
\e[1;6R |
\e\eOR |
\e\e[1;2R |
\e\e[1;5R |
\e\e[1;6R |
F4 | \eOS |
\e[1;2S |
\e[1;5S |
\e[1;6S |
\e\eOS |
\e\e[1;2S |
\e\e[1;5S |
\e\e[1;6S |
F5 | \e[15~ |
\e[15;2~ |
\e[15;5~ |
\e[15;6~ |
\e\e[15~ |
\e\e[15;2~ |
\e\e[15;5~ |
\e\e[15;6~ |
F6 | \e[17~ |
\e[17;2~ |
\e[17;5~ |
\e[17;6~ |
\e\e[17~ |
\e\e[17;2~ |
\e\e[17;5~ |
\e\e[17;6~ |
F7 | \e[18~ |
\e[18;2~ |
\e[18;5~ |
\e[18;6~ |
\e\e[18~ |
\e\e[18;2~ |
\e\e[18;5~ |
\e\e[18;6~ |
F8 | \e[19~ |
\e[19;2~ |
\e[19;5~ |
\e[19;6~ |
\e\e[19~ |
\e\e[19;2~ |
\e\e[19;5~ |
\e\e[19;6~ |
F9 | \e[20~ |
\e[20;2~ |
\e[20;5~ |
\e[20;6~ |
\e\e[20~ |
\e\e[20;2~ |
\e\e[20;5~ |
\e\e[20;6~ |
F10 | \e[21~ |
\e[21;2~ |
\e[21;5~ |
\e[21;6~ |
\e\e[21~ |
\e\e[21;2~ |
\e\e[21;5~ |
\e\e[21;6~ |
F11 | \e[23~ |
\e[23;2~ |
\e[23;5~ |
\e[23;6~ |
\e\e[23~ |
\e\e[23;2~ |
\e\e[23;5~ |
\e\e[23;6~ |
F12 | \e[24~ |
\e[24;2~ |
\e[24;5~ |
\e[24;6~ |
\e\e[24~ |
\e\e[24;2~ |
\e\e[24;5~ |
\e\e[24;6~ |
When the terminal.differentiate_keys
setting is enabled then the following key bindings are also available:
Ctrl | Ctrl-Shift | Alt | Alt-Shift | Alt-Ctrl | Alt-Ctrl-Shift | |
---|---|---|---|---|---|---|
H |
\e[27;5;72~ |
\e[27;6;72~ |
\eh |
\eH |
\e[27;7;72~ |
\e[27;8;72~ |
I |
\e[27;5;73~ |
\e[27;6;73~ |
\ei |
\eI |
\e[27;7;73~ |
\e[27;8;73~ |
M |
\e[27;5;77~ |
\e[27;6;77~ |
\em |
\eM |
\e[27;7;77~ |
\e[27;8;77~ |
[ |
\e[27;5;219~ |
\e[27;6;219~ |
\e[27;3;219~ |
\e[27;4;219~ |
\e[27;7;219~ |
\e[27;8;219~ |
The terminal.raw_esc
setting controls the binding sequence for the Esc key and a couple of other keys:
terminal.raw_esc Setting Value |
Esc | Alt-[ | Alt-Shift-O |
---|---|---|---|
False (the default) | \e[27;27~ |
\e[27;3;91~ |
\e[27;4;79~ |
True (replicate Unix terminal input quirks and issues) | \e |
\e[ |
\eO |
.Lua key bindings up top
You can bind a key to a Lua function by binding it to a macro that begins with "luafunc:". Clink will invoke the named Lua function when the key binding is input. Function names can include periods (such as foo.bar
) but cannot include any other punctuation.
The Lua function receives two arguments:
rl_buffer gives it access to the input buffer.
line_state gives it access to the same line state that a match generator receives.
Lua functions can print output, but should first call rl_buffer:beginoutput() so that the output doesn't overwrite the displayed input line.
Notes:
- The line_state is nil if not using Clink v1.2.34 or higher.
- The end word is always empty for generators. So to get the word at the cursor use:
local info = line_state:getwordinfo(line_state:getwordcount()) local word_at_cursor = line_state:getline():sub(info.offset, line_state:getcursor())
.Basic example up top
Example of a Lua function key binding in a .inputrc file:
M-C-y: "luafunc:insert_date"
M-C-z: "luafunc:print_date"
Example functions to go with that:
function insert_date(rl_buffer)
rl_buffer:insert(os.date("%x %X"))
end
function print_date(rl_buffer)
rl_buffer:beginoutput()
print(os.date("%A %B %d, %Y %I:%M %p"))
end
.Example to change how auto-suggested text is inserted up top
This example creates new commands that change Right and Shift-Right to swap how they behave when auto-suggested text is present. It also uses Lua to add descriptions for the new commands, and to set key bindings.
function cursor_forward_or_insert_full_word(rl_buffer)
local at_end = (rl_buffer:getcursor() > rl_buffer:getlength())
local command = at_end and "clink-insert-suggested-full-word" or "win-cursor-forward"
rl.invokecommand(command)
end
rl.describemacro([["luafunc:cursor_forward_or_insert_full_word"]], "Move cursor forward, or at end of line insert the next full suggested word up to a space")
rl.setbinding([["\e[C"]], [["luafunc:cursor_forward_or_insert_full_word"]])
function cua_forward_char_or_insert_line(rl_buffer)
local at_end = (rl_buffer:getcursor() > rl_buffer:getlength())
local command = at_end and "clink-insert-suggested-line" or "cua-forward-char"
rl.invokecommand(command)
end
rl.describemacro([["luafunc:cua_forward_char_or_insert_line"]], "Extend the selection forward one character, or insert the suggested line")
rl.setbinding([["\e[1;2C"]], [["luafunc:cua_forward_char_or_insert_line"]])
.Advanced example up top
Here is an example that makes F7/F8 jump to the previous/next screen line containing "error" or "warn" colored red or yellow, and makes Shift-F7/Shift-F8 jump to the previous/next prompt line.
One way to use these is when reviewing compiler errors after building a project at the command line. Press Shift-F7 to jump to the previous prompt line, and then use F8 repeatedly to jump to each next compiler warning or error listed on the screen.
Example key bindings for the .inputrc file:
"\e[18~": "luafunc:find_prev_colored_line"
"\e[19~": "luafunc:find_next_colored_line"
"\e[18;2~": "luafunc:find_prev_prompt"
"\e[19;2~": "luafunc:find_next_prompt"
Example functions to go in a Lua script file:
local max_recent_prompts = 10 -- Keep track of up to this many recent prompts.
local min_match_text = 10 -- Minimum length of text to count as a match.
local recent_prompts = {} -- Queue of recent prompt match strings.
local scroll_stack = {} -- Stack of found scroll positions.
-- Remember our most recent scroll position, so that if something else scrolls
-- the screen we can reset the find_prev_prompt/find_next_prompt stack.
local was_top
local function add_recent_prompt(text)
-- Escape characters that have special meaning in regular expressions.
text = "^"..text:gsub("([!-/:-@[-`{-~])", "\\%1")
-- Add new entry at the beginning of the queue.
table.insert(recent_prompts, 1, text)
-- Discard excess entries from the end of the queue.
while #recent_prompts > max_recent_prompts do
table.remove(recent_prompts)
end
end
local function reset_prompt_scroll_stack()
was_top = nil
scroll_stack = {}
end
local function update_recent_prompt_queue()
-- Offset minus one because onendedit happens after the cursor moves down
-- past the end of the input area, which skews the info returned from
-- rl.getpromptinfo().
local offset = -1
local info = rl.getpromptinfo()
local line = info.promptline + offset
local last_line = console.getnumlines()
-- Find a long enough string to be considered part of the prompt.
while line <= last_line do
local text = console.getlinetext(line)
text = text:gsub("%s+$", "")
if #text >= min_match_text then
add_recent_prompt(text)
break
end
line = line + 1
end
end
-- Register for events to maintain the scroll stack and recent prompt queue.
clink.onbeginedit(reset_prompt_scroll_stack)
clink.onendedit(update_recent_prompt_queue)
-- Jumps to the previous prompt on the screen (i.e. move upward, searching for
-- preceding recent prompts).
function find_prev_prompt(rl_buffer)
local height = console.getheight()
local offset = math.modf((height - 1) / 2)
local top = console.gettop()
if was_top and was_top ~= top then
reset_prompt_scroll_stack()
end
if not was_top then
was_top = top
end
if top <= 1 then
console.scroll("absolute", 1)
return
end
-- Init the stack if it's empty.
if #scroll_stack == 0 then
local info = rl.getpromptinfo()
scroll_stack[1] = info.promptline
end
local count = #scroll_stack
local start = scroll_stack[count] - 1
local text = recent_prompts[count]
if not text then
if count == 1 then
-- Only ding if there are none; otherwise visual bell will
-- scroll back to the bottom.
rl_buffer:ding()
else
-- No more recent prompts? Maintain the scroll position.
console.scroll("absolute", scroll_stack[count] - offset)
was_top = console.gettop()
end
return
end
-- Search upwards for the next most recent prompt.
local match
repeat
match = console.findprevline(start, text, "regex", {})
if match <= 0 then
-- Can't find it? Maintain the scroll position.
console.scroll("absolute", scroll_stack[count] - offset)
was_top = console.gettop()
return
end
start = match - 1
until match - offset < was_top
-- Add the found prompt to the stack.
table.insert(scroll_stack, match)
-- Scroll to the prompt position
console.scroll("absolute", match - offset)
was_top = console.gettop()
end
-- Jump to the next prompt on the screen (i.e. move downward, backtracking over
-- the prompts already visited by find_prev_prompt).
function find_next_prompt(rl_buffer)
local height = console.getheight()
local offset = math.modf((height - 1) / 2)
-- Pop the last found prompt. If the stack is empty, ding.
if #scroll_stack > 0 then
table.remove(scroll_stack)
end
if #scroll_stack == 0 then
rl_buffer:ding()
return
end
-- Get the scroll position of the next to last found prompt.
local top = scroll_stack[#scroll_stack] - offset
if #scroll_stack == 1 then
-- If it's the last prompt, pop it to reset the stack.
top = console.getnumlines()
table.remove(scroll_stack, #scroll_stack)
end
-- Scroll to the prompt position.
console.scroll("absolute", top)
was_top = console.gettop()
end
-- Searches upwards for a line containing "warn" or "error"
-- colored red or yellow.
function find_prev_colored_line(rl_buffer)
local height = console.getheight()
local cur_top = console.gettop()
local offset = math.modf((height - 1) / 2) -- For vertically centering the found line.
local start = cur_top + offset
local found_index
-- Only search if there's still room to scroll up.
if start - offset > 1 then
local match = console.findprevline(start - 1, "warn|error", "regex", {4,12,14}, "fore")
if match ~= nil and match > 0 then
found_index = match
end
end
-- If scrolled up but no more matches, maintain the scroll position.
if found_index == nil and cur_top <= console.getnumlines() - height then
found_index = start
end
if found_index ~= nil then
console.scroll("absolute", found_index - offset)
else
rl_buffer:ding()
end
end
-- Searches downwards for a line containing "warn" or "error"
-- colored red or yellow.
function find_next_colored_line(rl_buffer)
local height = console.getheight()
local cur_top = console.gettop()
local bottom = console.getnumlines()
local offset = math.modf((height - 1) / 2) -- For vertically centering the found line.
local start = cur_top + offset
local found_index
if cur_top > bottom - height then
rl_buffer:ding()
return
end
-- Only search if there's still room to scroll down.
if start - offset + height - 1 < bottom then
local match = console.findnextline(start + 1, "warn|error", "regex", {4,12,14}, "fore")
if match ~= nil and match > 0 then
found_index = match
end
end
if found_index ~= nil then
console.scroll("absolute", found_index - offset)
else
rl_buffer:ding()
end
end
.I do not have a Meta or Alt key up top
If you do not have a Meta or Alt key, or another key working as a Meta key, there is another way to generate "metafied" keystrokes such as M-k.
You can configure clink set terminal.raw_esc true
to make the Esc work as it does in Unix and Linux, and then you can type Esc followed by k. This is known as "metafying" the k key.
Clink is a Windows program, and so by default it makes the Esc key reset the input state, since that's how Esc generally works on Windows. When you enable the terminal.raw_esc
Clink setting, the Esc key changes its behavior, and pressing unbound special keys can land you in all of the same strange "stuck input" situations as in Unix and Linux.
But it might be more convenient to acquire a keyboard that has an Alt key.
.Saved Command History up top
Clink has a list of commands from the current session, and it can be saved and loaded across sessions.
By prefixing the command you can control whether it's added to history and whether a doskey alias may be expanded.
Line | Description |
---|---|
somecmd |
Can expand a doskey alias and adds to history. |
somecmd |
Starting with a space doesn't expand a doskey alias and doesn't add to history. |
;somecmd |
Starting with a semicolon doesn't expand a doskey alias but does add to history. |
You can list the saved history by running clink history
or the history
doskey alias that Clink automatically defines. Use history --help
for usage info.
There are several settings that control how history works. Run clink set history*
to see them all (orsee here).
Run clink info
to find the history file. See File Locations for more information.
Note: If the first word in the line matches one of the words in the
history.dont_add_to_history_cmds
setting then the command is not added to history. By default,history
andexit
are not added to history.
.Navigating through the history up top
The default key bindings for navigating the history are:
Key Binding | Description | Command Name |
---|---|---|
Enter | Accept the input line and send it to the shell for execution. The line may be added to the history for future recall. | accept-line |
Up | Move "back" through the history list, fetching the previous command. | previous-history |
Down | Move "forward" through the history list, fetching the next command. | next-history |
PgUp | Search backward through the history for entries matching the typed prefix. | history-search-backward |
PgDn | Search forward through the history for entries matching the typed prefix. | history-search-forward |
Ctrl-R | Perform an incremental search backward through the history. | reverse-search-history |
Ctrl-S | Perform an incremental search forward through the history. | forward-search-history |
Ctrl-Alt-Up | Show a popup list of selectable history entries. Typing searches or filters the list. | clink-popup-history |
F7 | Show a popup list of selectable history entries. Typing a number jumps to the corresponding history entry. | win-history-list |
Alt-Ctrl-K | Add the current line to the history without executing it, and clear the editing line. | add-history |
Alt-Ctrl-D | While navigating through the history, removes the current history line from the saved history. Otherwise has no effect. | remove-history |
Ctrl-O | Accept the input line and send it to the shell for execution (without adding it to the history), and then navigate to the next line after it from the saved history. This can be handy for re-running a series of lines from the history. | operate-and-get-next |
See Commands for Manipulating The History and Clink Commands for more history commands and key bindings.
.The master history file up top
When the history.save
setting is enabled, then the command history is loaded and saved as follows (or when the setting is disabled, then it isn't saved between sessions).
Every time a new input line starts, Clink reloads the master history list and prunes it not to exceed the history.max_lines
setting.
For performance reasons, deleting a history line marks the line as deleted without rewriting the history file. When the number of deleted lines gets too large (exceeding the max lines or 200, whichever is larger) then the history file is compacted: the file is rewritten with the deleted lines removed.
You can force the history file to be compacted regardless of the number of deleted lines by running history compact
.
.Shared command history up top
When the history.shared
setting is enabled, then all instances of Clink update the master history file and reload it every time a new input line starts. This gives the effect that all instances of Clink share the same history -- a command entered in one instance will appear in other instances' history the next time they start an input line.
When the setting is disabled, then each instance of Clink loads the master file but doesn't append its own history back to the master file until after it exits, giving the effect that once an instance starts its history is isolated from other instances' history.
.Multiple master history files up top
Normally Clink saves a single saved master history list. All instances of Clink load and save the same master history list.
It's also possible to make one or more instances of Clink use a different saved master history list by setting the %CLINK_HISTORY_LABEL%
environment variable. This can be up to 32 alphanumeric characters, and is appended to the master history file name. Changing the %CLINK_HISTORY_LABEL%
environment variable takes effect at the next input line.
.History timestamps up top
History items can optionally save the timestamp when they were added, and the timestamps can be shown in the history
command.
Use clink set history.time_stamp off
to not save or show timestamps for history items (this is the default). Turning off timestamps doesn't remove existing timestamps.
Use clink set history.time_stamp save
to save timestamps for each history item but only show them in the history
command when the --show-time
flag is used. They may also be shown when a clink-popup-history
or win-history-list
key binding is pressed, if a non-zero numeric argument is supplied.
Use clink set history.time_stamp show
to save timestamps for each history item and show them in the history
command unless the --bare
or --no-show-time
flag is used. They're also shown when a clink-popup-history
or win-history-list
key binding is pressed, unless a numeric argument argument of zero is supplied.
Use clink set history.time_format format
to specify the format for showing timestamps (the default format is %F %T  
).
The format string may contain regular characters and special format specifiers. Format specifiers begin with a percent sign (%
), and are expanded to their corresponding values. For a list of possible format specifiers, refer to the C++ strftime() documentation.
Some common format specifiers are:
Specifier | Expands To |
---|---|
%a |
Abbreviated weekday name for the locale (e.g. Thu). |
%b |
Abbreviated month name for the locale (e.g. Aug). |
%c |
Date and time representation for the locale. |
%D |
Short MM/DD/YY date (e.g. 08/23/01). |
%F |
Short YYYY/MM/DD date (e.g. 2001-08-23). |
%H |
Hour in 24-hour format (00 - 23). |
%I |
Hour in 12-hour format (01 - 12). |
%m |
Month (01 - 12). |
%M |
Minutes (00 - 59). |
%p |
AM or PM indicator for the locale. |
%r |
12-hour clock time for the locale (e.g. 02:55:41 pm). |
%R |
24-hour clock time (e.g. 14:55). |
%S |
Seconds (00 - 59). |
%T |
ISO 8601 time format HH:MM:SS (e.g. 14:55:41). |
%x |
Date representation for the locale. |
%X |
Time representation for the locale. |
%y |
Year without century (00 - 99). |
%Y |
Year with century (e.g. 2001). |
%% |
A % sign. |
.Using History Expansion up top
Clink uses Readline's History library to
add history expansion capabilities. If these are undesirable, they can be turned off by running
clink set history.auto_expand off
or
clink set history.expand_mode off
.
When enabled, history expansion is automatically performed when a command line
is accepted (by pressing Enter). When disabled, history expansion
is performed only when a corresponding expansion command is used (such as
clink-expand-history
Alt-^,
or clink-expand-line
Alt-Ctrl-E).
Expansion commands also work when history expansion is enabled.
The History library provides a history expansion feature that is similar
to the history expansion provided by csh
. This section describes the
syntax used to manipulate the history information.
History expansions introduce words from the history list into the input stream, making it easy to repeat commands, insert the arguments to a previous command into the current input line, or fix errors in previous commands quickly.
History expansion takes place in two parts. The first is to
determine which line from the history list should be used during
substitution. The second is to select portions of that line for
inclusion into the current one. The line selected from the history is
called the "event", and the portions of that line that are acted upon
are called "words". Various "modifiers" are available to manipulate the
selected words. The line is broken into words in the same fashion that
Bash does, so that several words surrounded by quotes are considered one
word. History expansions are introduced by the appearance of the
history expansion character, which is !
.
History expansion implements shell-like quoting conventions: a backslash can be used to remove the special handling for the next character; single quotes enclose verbatim sequences of characters, and can be used to inhibit history expansion; and characters enclosed within double quotes may be subject to history expansion, since backslash can escape the history expansion character, but single quotes may not, since they are not treated specially within double quotes.
The color.histexpand
setting controls highlighting when
text under the cursor is subject to history expansion. The
history.show_preview
setting shows a preview of the
expanded result below the input line using the
color.comment_row
setting.
Event Designators | How to specify which history line to use. |
Word Designators | Specifying which words are of interest. |
Modifiers | Modifying the results of substitution. |
.Event Designators up top
An event designator is a reference to a command line entry in the history list. Unless the reference is absolute, events are relative to the current position in the history list.
!
|
Start a history substitution, except when followed by a space, tab,
the end of the line, or = .
|
!n
| Refer to command line n. |
!-n
| Refer to the command n lines back. |
!!
|
Refer to the previous command. This is a synonym for !-1 .
|
!string
| Refer to the most recent command preceding the current position in the history list starting with string. |
!?string[?]
|
Refer to the most recent command preceding the current position in
the history list containing string. The trailing ? may be
omitted if the string is followed immediately by a newline. If
string is missing, the string from the most recent search is used;
it is an error if there is no previous search string.
|
^string1^string2^
|
Quick Substitution. Repeat the last command, replacing string1
with string2. Equivalent to !!:s^string1^string2^ .
|
!#
| The entire command line typed so far. |
.Word Designators up top
Word designators are used to select desired words from the event. A :
separates the event specification from the word designator. It may be
omitted if the word designator begins with a ^
, $
, *
, -
, or %
.
Words are numbered from the beginning of the line, with the first word
being denoted by 0 (zero). Words are inserted into the current line
separated by single spaces.
For example,
!!
| designates the preceding command. When you type this, the preceding command is repeated in toto. |
!!:$
|
designates the last argument of the preceding command. This may be
shortened to !$ .
|
!fi:2
|
designates the second argument of the most recent command starting
with the letters fi .
|
Here are the word designators:
0 (zero)
| The 0th word. For many applications, this is the command word. |
n
| The n-th word. |
^
| The first argument; that is, word 1. |
$
| The last argument. |
%
|
The first word matched by the most recent !?string? search, if the
search string begins with a character that is part of a word.
|
x-y
|
A range of words; -y abbreviates 0-y .
|
*
|
All of the words, except the 0th. This is a synonym for 1-$ .
It is not an error to use * if there is just one word in the
event; the empty string is returned in that case.
|
x*
|
Abbreviates x-$
|
x-
|
Abbreviates x-$ like x* , but omits the last word. If x is
missing, it defaults to 0.
|
If a word designator is supplied without an event specification, the previous command is used as the event.
.Modifiers up top
After the optional word designator, you can add a sequence of one or
more of the following modifiers, each preceded by a :
. These modify,
or edit, the word or words selected from the history event.
h
| Remove a trailing pathname component, leaving only the head. |
t
| Remove all leading pathname components, leaving the tail. |
r
|
Remove a trailing suffix of the form .suffix , leaving the
basename.
|
e
| Remove all but the trailing suffix. |
p
| Print the new command but do not execute it. |
s/old/new/
|
Substitute new for the first occurrence of old in the event line.
Any character may be used as the delimiter in place of / . The
delimiter may be quoted in old and new with a single backslash. If
& appears in new, it is replaced by old. A single backslash will
quote the & . If old is empty, it is set to the last old
substituted, or, if no previous history substitutions took place,
the last string in a !?string? search. If new is empty, each
matching old is deleted. The final delimiter is optional if it is
the last character on the input line.
|
&
| Repeat the previous substitution. |
g
|
Cause changes to be applied over the entire event line. Used in
conjunction with s , as in gs/old/new/ , or with & .
|
a
|
The same as g .
|
G
|
Apply the following s or & modifier once to each word in the
event.
|
.Directory Shortcuts up top
Clink provides some typing savers for changing the current directory.
- Typing a directory name followed by a path separator is a shortcut for
cd /d
to that directory. - Typing
..
or...
is a shortcut forcd ..
orcd ..\..
(each additional.
adds another\..
). - Typing
-
orcd -
changes to the previous current working directory.
These shortcuts only work in the interactive command line; they do not work in batch scripts.
.Enhanced Doskey Expansion up top
Enhanced Doskey expansion is enabled by default. You can turn it off by running clink set doskey.enhanced off
.
When enabled, this adds two behaviors:
- Expansion of Doskey macros that follow
|
and&
command separators. - Respects quotes around words when expanding
$1
...$9
tags in Doskey macros.
You can suppress macro expansion for an individual command by prefixing the command with a space or semicolon (e.g. foo
or ;foo
). If the command follows a |
or &
command separator, you can suppress macro expansion by prefixing the command with two spaces or a semicolon (e.g. foo| bar
or foo|;bar
).
Note: Some Doskey macros might be incompatible with the enhanced Doskey expansion feature, especially if they use special or complicated syntax. If you encounter problems, you might need to turn off enhanced Doskey expansion or adjust the problematic macros.
.Popular Scripts up top
Here are some popular scripts that show off what can be done with Clink.
.clink-completions up top
The clink-completions collection of scripts has a bunch of argument matchers and completion generators for things like git, mercurial, npm, and more.
.clink-flex-prompt up top
The clink-flex-prompt script is similar to the zsh powerlevel10k theme. It gives Clink a very customizable prompt, with many style options. It's extensible so you can add your own segments.
It also takes advantage of Clink's asynchronous prompt refresh to make prompts show up instantly, even in large git repos, for example.
.clink-fzf up top
The clink-fzf script integrates the popular fzf "fuzzy finder" tool with Clink.
.clink-gizmos up top
The clink-gizmos collection of scripts has several handy scripts such as:
- Argmatchers for
msbuild
,findstr
,robocopy
,xcopy
,doskey
,premake5
, and more. - Scripts to auto-generate argmatchers for commands by parsing their help text.
- Automatically show a divider line before + after certain commands, to make it easy to see where their output begins and ends, and the elapsed time taken by the command. This is especially handy when invoking compilers and build tools.
- The
i.lua
script which makesi directory command
set the current directory to directory then run command then restore the original current directory afterwards. While typing the command, completions are even generated relative to the specified directory rather than the current directory. - The
fzf.lua
script from clink-fzf for integrating the popular fzf "fuzzy finder" tool with Clink. - The
luaexec.lua
script which has various features handy for Clink Lua script authors. - And more.
.clink-themes up top
The clink-themes repository contains some color themes and custom prompts which can be used with Clink. If you have one you want to share, this can be a good place to share it.
.oh-my-posh up top
The oh-my-posh program can generate fancy prompts. Refer to its documentation for installation instructions, sample themes, and more information.
But in Clink v1.7.0 and newer, don't create a Lua script for oh-my-posh.
Instead do the following:
- Run
clink config prompt use oh-my-posh
to activate oh-my-posh as the custom prompt. - If the oh-my-posh.exe file is not in the system PATH, then run
clink set ohmyposh.exepath "full_path_to_oh-my-posh.exe"
to tell Clink where to find the oh-my-posh program file. - To configure oh-my-posh to use a particular prompt theme, run
clink set ohmyposh.theme "full_path_to_theme_file.omp.json"
to select the theme file.
.starship up top
The starship program can also generate fancy prompts. Refer to its documentation for how to configure it.
Integrating starship with Clink is just as easy: save the following text to a starship.lua
file in your Clink scripts directory (run clink info
to find that), and make sure the starship.exe
program is in a directory listed in the %PATH%
environment variable (or edit the script below to provide a fully qualified path to the starship.exe program). The config file for starship is located at C:\Users\username.config\starship.toml
.
-- starship.lua
load(io.popen('starship.exe init cmd'):read("*a"))()
.z.lua up top
The z.lua tool is a faster way to navigate directories, and it integrates with Clink.
.Terminal Support up top
Windows programs generally don't need to worry about terminal support. But the Readline library used by Clink comes from Unix, where there are many different kinds of terminals, and the library requires certain kinds of terminal support.
Clink's keyboard driver generally produces VT220 style key sequences, but it also includes many extensions from Xterm and other sources. Use clink echo
to find key sequences for specific inputs.
Clink's terminal output driver is designed for use with Windows and its console subsystem. Clink can optionally handle output itself instead, and emulate terminal output support when the terminal.emulation
setting is emulate
, or when auto
and Clink is running on an older version of Windows that doesn't support ANSI escape codes. In emulation mode, 8 bit and 24 bit color escape codes are mapped to the nearest 4 bit colors.
By default Clink sets the cursor style to a blinking horizontal partial-height block, or to a blink full-height solid block. Some terminals support escape codes to select alternative cursor styles. Clink provides environment variables where you may optionally provide escape codes to override the cursor style. %CLINK_TERM_VE%
selects the style for the normal cursor (insert mode), %CLINK_TERM_VS%
selects the style for the enhanced cursor (overwrite mode).
Special codes recognized in the cursor style escape code strings:
Code | Description |
---|---|
\e | Translated to the ESC character (27 decimal, 0x1b hex). |
\xHH | Translated to the character matching the hex HH value. E.g. \x1b is the same as \e , or \x08 is a backspace, etc. |
\\ | Translated to the \ character. |
\c | Any other backslash is translate to whatever character immediately follows it. E.g. \a becomes a . |
Refer to the documentation for individual terminal programs to find what (if any) escape codes they may support. The default console in Windows 10 supports the DECSCUSR escape codes for selecting cursor shape.
This .cmd script sets the normal cursor to a blinking vertical bar, and the enhanced cursor to a non-blinking solid box:
set CLINK_TERM_VE=\e[5 q
set CLINK_TERM_VS=\e[2 q
Or this .cmd script sets the normal cursor to blink, and the enhanced cursor to not blink:
set CLINK_TERM_VE=\e[?12h
set CLINK_TERM_VS=\e[?12l
.Color Emojis up top
The Unicode specification for emojis is constantly evolving. It's natural for operating system versions, code libraries, and application programs to lag behind the latest Unicode specification.
Clink's emoji width predictions work best on Windows 11 with Windows Terminal 1.22 or newer. All of the actual rendering is done by the terminal program. Applications have to make assumptions and predictions about how Unicode characters will end up being rendered by terminal programs. It involves a lot of guesswork.
Clink has no way to know for sure how different combinations of OS / graphics library / Windows Terminal versions will affect how different emoji characters will actually get rendered. Clink also has no way to know for sure how different complex joined emoji sequences or malformed/invalid/nonsensical emoji sequences will end up getting rendered in a terminal program. Windows Terminal 1.22 includes significant improvements for rendering color emojis, but there are still some edge cases that aren't fully implemented yet. (When using older version of Windows Terminal then you should expect some emoji sequences to render incorrectly, and there's nothing Clink can do to work around that.)
If you encounter problems with emoji characters, first check whether the latest OS version and/or the latest terminal program version solves some of the problems. If the problems persist, you can open a new issue in the Clink repo. Please be sure to share details and specific steps for how to reproduce the problem, so that it's possible for someone to try to help.
.How Clink Works up top
The clink inject
command checks whether the parent process is supported and injects a DLL.
The DLL takes over printing the prompt and reading command line input from the user.
.Checking if the parent process is supported up top
The parent process is supported if it is cmd.exe
and its command line indicates that it will be an interactive process. The process will be interactive if the command line has /k
or does not have /c
or /r
.
If the parent process is not supported, then the clink.bat
script or the clink_*.exe
program will exit before it actually injects the DLL into the cmd.exe
process.
.Hooking OS functions up top
If the DLL gets loaded into the cmd.exe
parent process and hooks some OS functions:
Function | Reason |
---|---|
GetEnvironmentVariableW() | To let the DLL finish its initialization. This is always called before CMD displays the prompt and is rarely called otherwise, so it's a reliable spot to hook regardless whether injection is triggered during CMD's AutoRun regkey or by running clink inject at the command line. |
SetEnvironmentVariableW() | To intercept setting the PROMPT variable, and add a special tag so Clink can tell when CMD is trying to print the prompt. |
SetEnvironmentStringsW() | To intercept setting the PROMPT variable, and add a special tag so Clink can tell when CMD is trying to print the prompt. |
WriteConsoleW() | To capture the current prompt and defer printing it until command line editing begins (inside ReadConsoleW()). |
ReadConsoleW() | To replace the command line editing with its own Readline-powered command line editing. |
SetConsoleTitleW() | To enable replacing the "Administrator:" prefix in the title bar. |
.How to prevent injection when Clink is configured for autorun up top
There are several ways:
- The
cmd /d
flag disables CMD's AutoRun regkey processing, which will prevent CMD from running the Clink autorun script. - If the
CLINK_NOAUTORUN
environment variable is set, then the Clink autorun script exits quickly, without even invoking clink_x64.exe. - Clink autorun can be uninstalled:
clink autorun uninstall
.
.Other notes up top
The clink.bat
file exists to enable seamless support for x64/x86/ARM64 on the same computer by detecting the current mode and invoking the corresponding clink_*.exe
program. There is no way for a batch script to figure out whether cmd.exe is going to be interactive, so that check has to happen inside the clink_x64.exe program. If it assesses that it will be non-interactive, then clink_x64.exe exits without injecting clink_dll_x64.dll into the cmd.exe process. The act of checking whether cmd.exe will be interactive is much faster than the act of injecting Clink into the cmd.exe process, and so the check minimizes performance degradation when Clink is configured for autorun.
Personally, I don't use Clink with autorun for three reasons:
- It slows down startup of cmd.exe processes that happen in the background or in automated situations,
- It introduces the possibility of interfering with background or automated cmd usage, and
- I don't want Clink auto-injected into every cmd session. I prefer to be explicit about when I'm going to use Clink, and I use LNK files or Windows Terminal profiles to control how and when Clink is injected.
I haven't removed the autorun feature because:
- It already existed as the default mode before I ever found Clink or took over maintenance,
- Many people like the feature, and
- It performs as efficiently as possible given how the CMD AutoRun regkey operates.
Redirected output is not considered when checking if the parent process is supported. The only way to reliably and accurately check for redirected stdin/stdout is to do the check after having already injected Clink, which would be pointless since by that time Clink has already been injected, so the full slowdown cost has already been paid. So, overall, trying to check for stdin/stdout doesn't have practical value.
.Troubleshooting Tips up top
If something seems to malfunction, here are some things to try that often help track down what's going wrong:
- Check if anti-malware software blocked Clink from injecting.
- Consider adding an exclusion for Clink.
- The contents of the
clink.log
file often help in determining whether anti-malware software blocked Clink. - If it's indeed being blocked by anti-malware software, report the false positive to the publisher of the anti-malware software so they can confirm and update the detection signatures. There's nothing Clink can do about it.
- If something looks wrong with the prompt display or input line display, try pressing Ctrl-x,Ctrl-z to invoke the
clink-diagnostics
command. Any problems it finds in the prompt string are reported at the end. - Check
clink info
. E.g. does the state dir look right, do the script paths look right, do the inputrc files look right? - Check
clink set
. E.g. do the settings look right? - Check the
clink.log
file for clues (its location is reported byclink info
).
When reporting an issue, please include the following which saves time by answering in advance the usual questions:
- Please describe what was expected to happen.
- Please describe what actually happened.
- Please include the output from
clink info
andclink set
. - Please include the
clink.log
file (the location is reported byclink info
).
.Privacy up top
Clink does not collect user data. Clink writes diagnostic information to its local log file, and does not transmit the log file off the local computer. For the location of the log file, refer to File Locations or run clink info
.
.Lua API Reference top
This section describes the Clink Lua API extensions.
Also see Lua Documentation and the Lua 5.2 Manual for more information about the Lua programming language.
.API groups up top
._argmatcher: up apis top
addarg | chaincommand | setclassifier |
addargunsorted | hideflags | setdelayinit |
adddescriptions | loop | setendofflags |
addflags | nofiles | setflagprefix |
addflagsunsorted | reset | setflagsanywhere |
This adds a new argument position with the matches given by choices. Arguments can be a string, a string linked to another parser by the concatenation operator, a table of arguments, or a function that returns a table of arguments. See Argument Completion for more information.
local my_parser = clink.argmatcher("make_color_shape")
:addarg("red", "green", "blue") -- 1st argument is a color
:addarg("circle", "square", "triangle") -- 2nd argument is a shape
When providing a table of arguments, the table can contain some special entries:
Entry | More Info | Version |
---|---|---|
delayinit=function | See Delayed initialization for an argument position. | v1.3.10 and newer |
fromhistory=true | See Generate Matches From History. | v1.3.9 and newer |
hint=string_or_function | See Show a Usage Hint. | v1.7.0 and newer |
loopchars="characters" | See Delimited Arguments. | v1.3.37 and newer |
nosort=true | See Disable Sorting Matches. | v1.3.3 and newer |
nowordbreakchars=true | See Overcoming Word Breaks. | v1.5.17 and newer |
onadvance=function | See Responding to Arguments in Argmatchers. | v1.5.14 and newer |
onalias=function | See Responding to Arguments in Argmatchers. | v1.6.18 and newer |
onarg=function | See Responding to Arguments in Argmatchers. | v1.3.13 and newer |
onlink=function | See Responding to Arguments in Argmatchers. | v1.5.14 and newer |
:addarg()
multiple times adds multiple argument positions, in the order they are specified.This is the same as _argmatcher:addarg except that this disables sorting the matches.
Adds descriptions for arg matches and/or flag matches. Descriptions are displayed for their associated args or flags whenever possible completions are listed, for example by the complete
or clink-select-complete
or possible-completions
commands.
Any number of descriptions tables may be passed to the function, and each table must use one of the following schemes:
- One or more string values that are args or flags, and a
description
field that is the associated description string. - Key/value pairs where each key is an arg or flag, and its value is either a description string or a table containing an optional argument info string and a description string. If an argument info string is provided, it is appended to the arg or flag string when listing possible completions. For example,
["--user"] = { " name", "Specify username"}
gets printed as:--user name Specify username
local foo = clink.argmatcher("foo")
foo:addflags("-h", "--help", "--user")
foo:addarg("info", "set")
-- Example using first scheme and one table per description:
foo:adddescriptions(
{ "-h", "--help", description = "Show help" },
{ "--user", description = "Specify user name" },
{ "info", description = "Prints information" },
{ "set", description = "Show or change settings" },
)
-- Example using second scheme and just one table:
foo:adddescriptions( {
["-h"] = "Show help",
["--help"] = "Show help",
["--user"] = { " name", "Specify user name" },
["info"] = { "Prints information" },
["set"] = { " var[=value]", "Show or change settings" },
} )
You can make your scripts backward compatible with older Clink versions by adding a helper function. The following is the safest and simplest way to support backward compatibility:
-- Helper function to add descriptions, when possible.
local function maybe_adddescriptions(matcher, ...)
if matcher and matcher.adddescriptions then
matcher:adddescriptions(...)
end
end
-- This adds descriptions only if the Clink version being used
-- supports them, otherwise it does nothing.
maybe_adddescriptions(foo, {
["-h"] = "Show help",
-- etc
})
This adds flag matches. Flags are separate from arguments: When listing possible completions for an empty word, only arguments are listed. But when the word being completed starts with the first character of any of the flags, then only flags are listed. See Argument Completion for more information.
local my_parser = clink.argmatcher("git")
:addarg({ "add", "status", "commit", "checkout" })
:addflags("-a", "-g", "-p", "--help")
When providing a table of flags, the table can contain some special entries:
Entry | More Info | Version |
---|---|---|
delayinit=function | See Delayed initialization for an argument position. | v1.3.10 and newer |
fromhistory=true | See Generate Matches From History. | v1.3.9 and newer |
nosort=true | See Disable Sorting Matches. | v1.3.3 and newer |
onarg=function | See Responding to Arguments in Argmatchers. | v1.3.13 and newer |
:addarg()
multiple times with different flags is the same as using :addarg()
once with all of the flags.This is the same as _argmatcher:addflags except that this also disables sorting for flags.
This makes the rest of the line be parsed as a separate command, after the argmatcher reaches the end of its defined argument positions. You can use it to "chain" from one parser to another.
For example, cmd.exe program arg
is example of a line where one command can have another command within it. :chaincommand()
enables program arg
to be parsed separately. If program
has an argmatcher, then it takes over and parses the rest of the input line.
An example that chains in a linked argmatcher:
clink.argmatcher("program"):addflags("/x", "/y")
clink.argmatcher("cmd"):addflags(
"/c" .. clink.argmatcher():chaincommand(),
"/k" .. clink.argmatcher():chaincommand()
):nofiles()
-- Consider the following input:
-- cmd /c program /
-- "cmd" is colored as an argmatcher.
-- "/c" is colored as a flag (by the "cmd" argmatcher).
-- "program" is colored as an argmatcher.
-- "/" generates completions "/x" and "/y".
Examples that chain at the end of their argument positions:
clink.argmatcher("program"):addflags("-x", "-y")
clink.argmatcher("sometool"):addarg(
"exec" .. clink.argmatcher()
:addflags("-a", "-b")
:addarg("profile1", "profile2")
:chaincommand()
)
-- Consider the following input:
-- sometool exec profile1 program -
-- "sometool" is colored as an argmatcher.
-- "exec" is colored as an argument (for "sometool").
-- "profile1" is colored as an argument (for "exec").
-- "program" is colored as an argmatcher.
-- "-" generates completions "-x" and "-y".
In Clink v1.6.2 and higher, an optional modes argument can let Clink know how the command will get interpreted. The string can contain any combination of the following words, separated by spaces or commas. If some words are mutually exclusive, the one that comes last in the string is used.
Mode | Description |
---|---|
cmd | Lets the argmatcher know that the command gets processed how CMD.exe would process it. This is the default if modes is omitted. |
start | Lets the argmatcher know the command gets processed how the START command would process it. |
run | Lets the argmatcher know the command gets processed how the Win-R Windows Run dialog box would process it. |
doskey | Lets the argmatcher know if the command starts with a doskey alias it will be expanded. This is very unusual, but for example the i.lua script in clink-gizmos does this. |
The modes string does not affect how the command gets executed. It only affects how the argmatcher performs completions and input line coloring, to help the argmatcher be accurate.
This hides the specified flags when displaying possible completions (the flags are still recognized).
This is intended for use when there are several synonyms for a flag, so that input coloring and linked argmatchers work, without cluttering the possible completion list.
local dirs = clink.argmatcher():addarg(clink.dirmatches)
local my_parser = clink.argmatcher("mycommand")
:addflags("-a", "--a", "--al", "--all",
"-d"..dirs, "--d"..dirs, "--di"..dirs, "--dir"..dirs)
:hideflags("--a", "--al", "--all", -- Only "-a" is displayed.
"-d", "--d", "--di") -- Only "--dir" is displayed.
This makes the parser loop back to argument position index when it runs out of positional sets of arguments (if index is omitted it loops back to argument position 1).
clink.argmatcher("xyzzy")
:addarg("zero", "cero") -- first arg can be zero or cero
:addarg("one", "uno") -- second arg can be one or uno
:addarg("two", "dos") -- third arg can be two or dos
:loop(2) -- fourth arg loops back to position 2, for one or uno, and so on
This makes the parser prevent invoking match generators. You can use it to "dead end" a parser and suggest no completions.
Resets the argmatcher to an empty state. All flags, arguments, and settings are cleared and reset back to a freshly-created state.
See Adaptive Argmatchers for more information.
This registers a function that gets called for each word the argmatcher handles, to classify the word as part of coloring the input text. See Coloring the Input Text for more information.
This registers a function that gets called the first time the argmatcher is used in each edit line session. See Adaptive Argmatchers for more information.
When endofflags is a string, it is a special flag that signals the end of flags. When endflags is true or nil, then "--
" is used as the end of flags string. Otherwise, the end of flags string is cleared.
This is almost never needed, because :addflags()
automatically identifies flag prefix characters.
However, any flags generated by functions can't influence the automatic flag prefix character(s) detection. So in some cases it may be necessary to directly set the flag prefix.
Note: :setflagprefix()
behaves differently in different versions of Clink:
Version | Description |
---|---|
v1.0.0 through v1.1.3 | Sets the flag prefix characters. |
v1.1.4 through v1.2.35 | Only sets flag prefix characters in an argmatcher created using the deprecated clink.arg.register_parser() function. Otherwise it has no effect. |
v1.2.36 through v1.3.8 | Does nothing. |
v1.3.9 onward | Adds flag prefix characters, in addition to the ones automatically identified. |
local function make_flags()
return { '-a', '-b', '-c' }
end
clink.argmatcher('some_command')
:addflags(make_flags) -- Only a function is added, so flag prefix characters cannot be determined automatically.
:setflagprefix('-') -- Force '-' to be considered as a flag prefix character.
When anywhere is false, flags are only recognized until an argument is encountered. Otherwise they are recognized anywhere (which is the default).
.builder: up apis top
addmatch | setfullyqualify |
addmatches | setnosort |
isempty | setsuppressappend |
setappendcharacter | setsuppressquoting |
setforcequoting | setvolatile |
Adds a match.
The match argument is the match string to add.
The type argument is the optional match type, or "none" if omitted (see below for the possible match types).
Alternatively, the match argument can be a table with the following scheme:
{
match = "..." -- [string] The match text.
display = "..." -- [string] OPTIONAL; alternative text to display when listing possible completions.
arginfo = "..." -- [string] OPTIONAL; an argument info string (requires v1.5.4 or greater).
description = "..." -- [string] OPTIONAL; a description for the match.
type = "..." -- [string] OPTIONAL; the match type.
appendchar = "..." -- [string] OPTIONAL; character to append after the match.
suppressappend = t_or_f -- [boolean] OPTIONAL; whether to suppress appending a character after the match.
}
- The
display
field is optional, and is displayed instead of thematch
field when listing possible completions. It can even include ANSI escape codes for colors, etc. (Requires v1.2.38 or greater.) - The
arginfo
field is optional, and is displayed next to thematch
field. See _argmatcher:adddescriptions for more about the argument info string. Thearginfo
field is ignored if thedisplay
field is present. (Requires v1.5.4 or greater.) - The
description
field is optional, and is displayed in addition tomatch
ordisplay
when listing possible completions. (Requires v1.2.38 or greater.) - The
type
field is optional. If omitted, then the type argument is used for that element. - The
appendchar
field is optional, and overrides the normal behavior for only this match. (Requires v1.3.1 or greater.) - The
suppressappend
field is optional, and overrides the normal behavior for only this match. (Requires v1.3.1 or greater.)
The match type affects how the match is inserted, displayed, and colored. Some type modifiers may be combined with a match type.
Type | Description |
---|---|
"word" | Shows the whole word even if it contains slashes. |
"arg" | Avoids appending a space if the match ends with a colon or equal sign. |
"cmd" | Displays the match using color.cmd. |
"alias" | Displays the match using color.doskey. |
"file" | Shows only the last path component, with appropriate file coloring. |
"dir" | Shows only the last path component and adds a trailing path separator, with appropriate directory coloring. |
"none" | For backward compatibility the match is treated like "file", unless it ends with a path separator in which case it's treated like "dir". |
Modifier | Description |
---|---|
"hidden" | This can be combined with "file" or "dir" to use color.hidden (e.g. "file,hidden"). |
"readonly" | This can be combined with "file" or "dir" to use color.readonly (e.g. "file,readonly"). |
"link" | This can be combined with "file" or "dir" to appropriate symlink coloring (e.g. "file,link"). |
"orphaned" | This can be combined with "link" to use appropriate orphaned symlink coloring (e.g. "file,link,orphaned"). |
See Completion Colors and Color Settings for more information about colors.
builder:addmatch("hello") -- type is "none"
builder:addmatch("some_word", "word")
builder:addmatch("/flag", "arg")
builder:addmatch("abbrev", "alias")
builder:addmatch({ match="foo.cpp", type="file" })
builder:addmatch({ match="bar", type="dir" })
builder:addmatch({ match=".git", type="dir,hidden" })
This is the equivalent of calling builder:addmatch() in a for-loop. Returns the number of matches added and a boolean indicating if all matches were added successfully.
The matches argument can be a table of match strings, or a table of tables describing the matches.
The type argument is used as the type when a match doesn't explicitly include a type, and is "none" if omitted.
builder:addmatches({"abc", "def"}) -- Adds two matches of type "none"
builder:addmatches({"abc", "def"}, "file") -- Adds two matches of type "file"
builder:addmatches({
-- Same table scheme per entry here as in builder:addmatch()
{ match="remote/origin/master", type="word" },
{ match="remote/origin/topic", type="word" }
})
Returns whether the match builder is empty. It is empty when no matches have been added yet.
Sets character to append after matches. For example the set
match generator uses this to append "=" when completing matches, so that completing set USER
becomes set USERDOMAIN=
(rather than set USERDOMAIN
).
Forces quoting rules to be applied to matches even if they aren't filenames.
Forces completions to be inserted as fully qualified paths.
Sets whether to suppress appending anything after the match except a possible closing quote. For example the env var match generator uses this.
Sets whether to suppress quoting for the matches. Set to 0 for normal quoting, or 1 to suppress quoting, or 2 to suppress end quotes. For example the env var match generator sets this to 1 to overcome the quoting that would normally happen for "%" characters in filenames.
Forces the generated matches to be used only once.
Normally Clink tries to reuse the most recently generated list of matches, if possible. It is an optimization, to avoid doing potentally expensive work multiple times in a row to generate the same list of matches when nothing has changed. Normally the optimization is beneficial, and typing more letters in a word can simply filter the existing list of matches.
But sometimes an argument may have special syntax. For example, an email address argument might want to generate matches for names until the word contains a @
, and then it might want to generate matches for domain names. The optimization interferes with situations where parsing the word produces a completely different list of possible matches.
Making the generated matches volatile ensures matches are generated anew each time completion is invoked.
.clink. up apis top
Finds the theme and tries to apply its setting (which are saved in the current profile settings, which affects all Clink sessions using that profile directory).
If successful, it returns true. If unsuccessful, it returns nil followed by a message describing the failure.
Applying a color theme clears the built-in color settings to their default values before loading the theme. If the optional clearall argument is true, then it also clears any color settings added by Lua scripts.
If the optional no_save argument is true, then the color theme is loaded into memory but is not saved back to the Clink settings file.
Refer to Color Themes for more information.
Creates and returns a new argument matcher parser object. Use :addarg() and etc to add arguments, flags, other parsers, and more. See Argument Completion for more information.
If one command is provided and there is already an argmatcher for it, then this returns the existing parser rather than creating a new parser. Using :addarg() starts at arg position 1, making it possible to merge new args and etc into the existing parser.
In Clink v1.3.38 and higher, if a command is a fully qualified path, then it is only used when the typed command expands to the same fully qualified path. This makes it possible to create one argmatcher for c:\general\program.exe
and another for c:\special\program.exe
. For example, aliases may be used to make both programs runnable, or the system PATH might be changed temporarily while working in a particular context.
Note: Merging linked argmatchers only merges the first argument position. The merge is simple, but should be sufficient for common simple cases.
Creates and returns a new word classifier object. Define on the object a :classify()
function which gets called in increasing priority order (low values to high values) when classifying words for coloring the input. See Coloring the Input Text for more information.
You can use this function in an argmatcher to supply directory matches. This automatically handles Readline tilde completion.
-- Make "cd" generate directory matches (no files).
clink.argmatcher("cd")
:addflags("/d")
:addarg({ clink.dirmatches })
This is the same as clink.dirmatches() except this doesn't append a *
to the search pattern.
You can use this function in an argmatcher to supply file matches. This automatically handles Readline tilde completion.
Argmatchers default to matching files, so it's unusual to need this function. However, some exceptions are when a flag needs to accept file matches but other flags and arguments don't, or when matches need to include more than files.
-- Make "foo --file" generate file matches, but other flags and args don't.
-- And the third argument can be a file or $stdin or $stdout.
clink.argmatcher("foo")
:addflags(
"--help",
"--file"..clink.argmatcher():addarg({ clink.filematches })
)
:addarg({ "one", "won" })
:addarg({ "two", "too" })
:addarg({ clink.filematches, "$stdin", "$stdout" })
This is the same as clink.filematches() except this doesn't append a *
to the search pattern.
local function zip_file_matches(word)
return clink.filematchesexact(word.."*.zip")
end
clink.argmatcher("unzip")
:addarg(zip_file_matches) -- First arg is name of a .zip file.
:addarg()
:loop(2)
Creates and returns a new match generator object. Define on the object a :generate()
function which gets called in increasing priority order (low values to high values) when generating matches for completion. See Match Generators for more information.
Returns up to two strings indicating who Clink thinks will currently handle ANSI escape codes.
The first returned string is the "current" handler. This can change based on the terminal.emulation
setting.
Starting in v1.4.26 a second string can be returned which indicates the "native" handler. This is what Clink has detected as the terminal host and is not affected by the `terminal.emulation` setting.
The returned strings will always be "unknown"
until the first edit prompt (see clink.onbeginedit()).
These can be useful in choosing what kind of ANSI escape codes to use, but are a best guess and are not necessarily 100% reliable.
Return | Description |
---|---|
"unknown" | Clink doesn't know. |
"clink" | Clink is emulating ANSI support. 256 color and 24 bit color escape codes are mapped to the nearest of the 16 basic colors. |
"conemu" | Clink thinks ANSI escape codes will be handled by ConEmu. |
"ansicon" | Clink thinks ANSI escape codes will be handled by ANSICON. |
"winterminal" | Clink thinks ANSI escape codes will be handled by Windows Terminal. |
"wezterm" | Clink thinks ANSI escape codes will be handled by WezTerm. |
"winconsole" | Clink thinks ANSI escape codes will be handled by the default console support in Windows, but Clink detected a terminal replacement that won't support 256 color or 24 bit color. |
"winconsolev2" | Clink thinks ANSI escape codes will be handled by the default console support in Windows, or it might be handled by a terminal replacement that Clink wasn't able to detect. |
Finds the argmatcher registered to handle a command, if any.
When find is a string it is interpreted as the name of a command, and this looks up the argmatcher for the named command.
When find is a line_state this looks up the argmatcher for the command line.
If no argmatcher is found, this returns nil.
Returns four values related to the current clinkprompt module, if any:
- A string containing the lowercase name (e.g.
"myprompt"
). - A string containing the full path name of the current clinkprompt module (e.g.
"C:\MyScripts\themes\MyPrompt.clinkprompt"
). - Lowercase full path name of the current clinkprompt module.
- A table of other clinkprompt modules that the current module depends on. The keys are the lowercase names (not full paths) of modules, and the values are all
true
.
If no clinkprompt module is currently active, then the return values are three empty strings and an empty table.
Returns the default popup colors in a table with the following scheme:
{
items = "...", -- The SGR parameters for the items color.
desc = "...", -- The SGR parameters for the description color.
-- Clink v1.7.0 adds the following colors to the table:
border = "...", -- The SGR parameters for the border color.
header = "...", -- The SGR parameters for the title color.
footer = "...", -- The SGR parameters for the footer message color.
select = "...", -- The SGR parameters for the selected item color.
selectdesc = "...", -- The SGR parameters for the selected item description color.
}
See SGR parameters for more information on ANSI escape codes for colors.
This has two different behaviors, depending on whether the optional name argument is provided:
If name is omitted, this returns two tables. The first table is an array of custom prompt names. The second table is a map of lowercase names to their corresponding file paths.
local names, map = clink.getprompts()
for _, name in ipairs(names) do
local file = map[clink.lower(name)]
print(string.format('"%s" -> "%s"', name, file))
end
If name is a string, this returns the file path of a matching custom prompt file. If the ".clinkprompt" extension is not present, it is assumed. If no matching prompt file is found, nil is returned.
clink.getprompt("My Prompt Name")
-- Could return "My Prompt Name.clinkprompt" if that file exists in the current directory.
-- Could return "c:\myclink\scripts\themes\My Prompt Name.clinkprompt" if that exists.
-- Etc.
Refer to Customizing the Prompt for more information.
Returns the current Clink session id.
This is needed when using io.popen() (or similar functions) to invoke clink history
or clink info
while Clink is installed for autorun. The popen API spawns a new CMD.exe, which gets a new Clink instance injected, so the history or info command will use the new session unless explicitly directed to use the calling session.
local exe = string.format('"%s" --session %s', CLINK_EXE, clink.getsession())
local r = io.popen('2>nul '..exe..' history')
if r then
for line in r:lines() do
print(line)
end
r:close()
end
This has two different behaviors, depending on whether the optional name argument is provided:
If name is omitted, this returns two tables. The first table is an array of theme names. The second table is a map of lowercase names to their corresponding file paths.
local names, map = clink.getthemes()
for _, name in ipairs(names) do
local file = map[clink.lower(name)]
print(string.format('"%s" -> "%s"', name, file))
end
If name is a string, this returns the file path of a matching theme file. If the ".clinktheme" extension is not present, it is assumed. If no matching theme file is found, nil is returned.
clink.getthemes("My Theme Name")
-- Could return "My Theme Name.clinktheme" if that file exists in the current directory.
-- Could return "c:\myclink\scripts\themes\My Theme Name.clinktheme" if that exists.
-- Etc.
Refer to Color Themes for more information.
Creates and returns a new hinter object. Define on the object a :gethint()
function which gets called in increasing priority order (low values to high values) when updating the input line display (e.g. while typing). See Showing Input Hints for more information.
This API correctly converts UTF8 strings to lowercase, with international linguistic awareness.
clink.lower("Hello World") -- returns "hello world"
clink.lower("ÁÈÏõû") -- returns "áèïõû"
Registers func to be called after every editing command (key binding).
Registers func to be called when Clink's edit prompt is activated. The function receives no arguments and has no return values.
Registers func to be called when the command word changes in the edit line.
The function receives 2 arguments: the line_state for the command, and a table with the following scheme:
{
command = -- [string] The command.
quoted = -- [boolean] Whether the command is quoted in the command line.
type = -- [string] "unrecognized", "executable", or "command" (a CMD command name).
file = -- [string] The file that would be executed, or an empty string.
}
The function has no return values.
Registers func to be called when Clink is about to display matches. See Filtering the Match Display for more information.
local function my_filter(matches, popup)
local new_matches = {}
for _,m in ipairs(matches) do
if m.match:find("[0-9]") then
-- Ignore matches with one or more digits.
else
-- Keep the match, and also add * prefix to directory matches.
if m.type:find("^dir") then
m.display = "*"..m.match
end
table.insert(new_matches, m)
end
end
return new_matches
end
function my_match_generator:generate(line_state, match_builder)
...
clink.ondisplaymatches(my_filter)
end
Registers func to be called when Clink's edit prompt ends. The function receives a string argument containing the input text from the edit prompt.
Breaking Change in v1.2.16: The ability to replace the user's input has been moved to a separate onfilterinput event.
Registers func to be called after Clink's edit prompt ends (it is called after the onendedit event). The function receives a string argument containing the input text from the edit prompt. The function returns up to two values. If the first is not nil then it's a string that replaces the edit prompt text. If the second is not nil and is false then it stops further onfilterinput handlers from running.
Starting in v1.3.13 func may return a table of strings, and each is executed as a command line.
Note: Be very careful if you replace the text; this has the potential to interfere with or even ruin the user's ability to enter command lines for CMD to process.
Registers func to be called after Clink generates matches for completion. See Filtering Match Completions for more information.
Registers func to be called when an input line has been accepted and is about to be added to history. The function receives a string argument containing the input text from the edit prompt. The function can return false to cancel adding the line to history (if it returns false then no further onhistory handlers will run for that line).
Note: The onhistory handler functions are not called by add-history
or the clink history
command.
Registers func to be called when Clink is injected into a CMD process. The function is called only once per session.
Registers func to be called after an editing command (key binding) makes changes in the input line.
The function receives one argument, a line string which contains the new contents of the input line.
The function has no return values.
Here is a script that demonstrates a lighthearted example of how this could be used. Any time the input line contains "marco" it replaces the prompt with "POLO!".
local has_marco
local polo = clink.promptfilter(-1)
function polo:filter()
if has_marco then
return "\x1b[44;96mPOLO!\x1b[m ", false
end
end
local function onbeginedit()
has_marco = nil
end
local function oninputlinechanged(line)
local new_marco = line:find("marco") and true
if has_marco ~= new_marco then
has_marco = new_marco
clink.refilterprompt()
end
end
clink.onbeginedit(onbeginedit)
clink.oninputlinechanged(oninputlinechanged)
function clink.oninputlinechanged(func)
_add_event_callback("oninputlinechanged", func)
end
Registers func to be called after the onbeginedit event but before the input line editor starts. If func returns a string, it is executed as a command line without showing a prompt. The input line editor is skipped, and the onendedit and onfilterinput events happen immediately.
Note: Be very careful when returning a string; this can interfere with the user's ability to use CMD. Mistakes in the command string can have potential to cause damage to the system very quickly. It is also possible for a script to cause an infinite loop, and therefore Ctrl-Break skips the next onprovideline event, allowing the user to regain control.
This parses the line string into a table of commands, with one line_state for each command parsed from the line string.
The returned table of tables has the following scheme:
local commands = clink.parseline("echo hello & echo world")
-- commands[1].line_state corresponds to "echo hello".
-- commands[2].line_state corresponds to "echo world".
Displays a popup list and returns the selected item. May only be used within a luafunc: key binding or inside a function registered with clink.onfiltermatches().
title is required and captions the popup list.
items is a table of strings to display.
index optionally specifies the default item (or 1 if omitted).
del_callback optionally specifies a callback function to be called when Del is pressed. The function receives the index of the selected item. If the function returns true then the item is deleted from the popup list. This requires Clink v1.3.41 or higher.
The function returns one of the following:
- nil if the popup is canceled or an error occurs.
- Three values:
- string indicating the
value
field from the selected item (or thedisplay
field if no value field is present). - boolean which is true if the item was selected with Shift or Ctrl pressed.
- integer indicating the index of the selected item in the original items table.
- string indicating the
Alternatively, the items argument can be a table of tables with the following scheme:
{
{
value = "...", -- Required; this is returned if the item is chosen.
display = "...", -- Optional; displayed instead of value.
description = "...", -- Optional; displayed in a dimmed color in a second column.
},
...
}
The value
field is returned if the item is chosen.
The optional display
field is displayed in the popup list instead of the value
field.
The optional description
field is displayed in a dimmed color in a second column. If it contains tab characters ("\t"
) the description string is split into multiple columns (up to 3).
Starting in v1.3.18, if any description contains a tab character, then the descriptions are automatically aligned in a column.
Otherwise, the descriptions follow immediately after the display field. They can be aligned in a column by making all of the display fields be the same number of character cells.
Starting in v1.4.0, the items table may optionally include any of the following fields to customize the popup list. The color strings must be SGR parameters and will be automatically converted into the corresponding ANSI escape code.
{
height = 20, -- Preferred height, not counting the border.
width = 60, -- Preferred width, not counting the border.
reverse = true, -- Start at bottom; search upwards.
searchmode = "filter", -- Use "find" or "filter" to override the default search mode (in v1.6.13 and higher).
colors = { -- Override the popup colors using any colors in this table.
items = "97;44", -- The items color (e.g. bright white on blue).
desc = "...", -- The description color.
border = "...", -- The border color (defaults to items color).
header = "...", -- The title color (defaults to border).
footer = "...", -- The footer message color (defaults to border color).
select = "...", -- The selected item color (defaults to reverse video of items color).
selectdesc = "...", -- The selected item description color (defaults to selected item color).
}
}
This works like print(), but this supports ANSI escape codes and Unicode.
If the special value NONL
is included anywhere in the argument list then the usual trailing newline is omitted. This can sometimes be useful particularly when printing certain ANSI escape codes.
Note: In Clink versions before v1.2.11 the clink.print()
API exists (undocumented) but accepts exactly one string argument and is therefore not fully compatible with normal print() syntax. If you use fewer or more than 1 argument or if the argument is not a string, then first checking the Clink version (e.g. clink.version_encoded) can avoid runtime errors.
clink.print("\x1b[32mgreen\x1b[m \x1b[35mmagenta\x1b[m")
-- Outputs "green" in green, a space, and "magenta" in magenta.
local a = "hello"
local world = 73
clink.print("a", a, "world", world)
-- Outputs "a hello world 73".
clink.print("hello", NONL)
clink.print("world")
-- Outputs "helloworld".
Creates a coroutine to run the func function in the background. Clink will automatically resume the coroutine repeatedly while input line editing is idle. When the func function completes, Clink will automatically refresh the prompt by triggering prompt filtering again.
A coroutine is only created the first time each prompt filter calls this API during a given input line session. Subsequent calls reuse the already-created coroutine. (E.g. pressing Enter ends an input line session.)
The API returns nil until the func function has finished. After that, the API returns whatever the func function returned. The API returns one value; if multiple return values are needed, return them in a table.
If the prompt.async
setting is disabled, then the coroutine runs to completion immediately before returning. Otherwise, the coroutine runs during idle while editing the input line. The func function receives one argument: true if it's running in the background, or false if it's running immediately.
See Asynchronous Prompt Filtering for more information.
Note: each prompt filter can have at most one prompt coroutine.
Creates and returns a new promptfilter object that is applied in increasing priority order (low values to high values). Define on the object a :filter()
function that takes a string argument which contains the filtered prompt so far. The function can return nil to have no effect, or can return a new prompt string. It can optionally stop further prompt filtering by also returning false. See Customizing the Prompt for more information.
local foo_prompt = clink.promptfilter(80)
function foo_prompt:filter(prompt)
-- Insert the date at the beginning of the prompt.
return os.date("%a %H:%M").." "..prompt
end
Reads the specified theme and returns a table with its settings. If unsuccessful, it returns nil followed by a message describing the failure.
theme can be a filename or the title of an installed theme.
Refer to Color Themes for more information.
Reclassify the input line text again and refresh the input line display.
This reports the input line coloring word classification to use for a command word. The return value can be passed into word_classifications:classifyword() as its word_class argument.
This is intended for advanced input line coloring purposes. For example if a script uses clink.onfilterinput() to modify the input text, then it can use this function inside a custom classifier to look up the color appropriate for the modified input text.
The line is optional and may be an empty string or omitted. When present, it is parsed to check if it would be processed as a directory shortcut.
The word is a string indicating the word to be analyzed.
The quoted is optional. When true, it indicates the word is quoted and any ^
characters are taken as-is, rather than treating them as the usual CMD escape character.
The possible return values for word_class are:
Code | Classification | Clink Color Setting |
---|---|---|
"x" | Executable; used for the first word when it is not a command or doskey alias, but is an executable name that exists. | color.executable |
"u" | Unrecognized; used for the first word when it is not a command, doskey alias, or recognized executable name. | color.unrecognized |
"o" | Other; used for file names and words that don't fit any of the other classifications. | color.input |
The possible return values for ready are:
- True if the analysis has completed.
- False if the analysis has not yet completed (and the returned word class may be a temporary placeholder).
The return value for file is the fully qualified path to the found executable file, if any, or nil.
Note: This always returns immediately, and it uses a background thread to analyze the word asynchronously. When the background thread finishes analyzing the word, Clink automatically redisplays the input line, giving classifiers a chance to call this function again and get the final word_class result.
Call this with refilter either nil or true to make Clink automatically rerun prompt filters after the terminal is resized. The previous value is returned.
On Windows the terminal is resized while the console program in the terminal (such as CMD) continues to run. If a console program writes to the terminal while the resize is happening, then the terminal display can become garbled. So Clink waits until the terminal has stayed the same size for at least 1.5 seconds, and then it reruns the prompt filters.
Use this with caution: if the prompt filters have not been designed efficiently, then rerunning them after resizing the terminal could cause responsiveness problems. Also, if the terminal is resized again while the prompt filters are being rerun, then the terminal display may become garbled.
Invoke the prompt filters again and refresh the prompt.
Note: This can potentially be expensive; call this only infrequently.
Reloads Lua scripts and Readline config file at the next prompt.
By default, a coroutine is canceled if it doesn't complete before an edit line ends. In some cases it may be necessary for a coroutine to run until it completes, even if it spans multiple edit lines.
Use this with caution: This can potentially cause performance problems or cause prompt filtering to experience delays.
Runs func on the main coroutine.
If main is the current coroutine, then func runs immediately.
If main is not the current coroutine, then func is scheduled to run when control returns to the main coroutine.
Overrides the interval at which a coroutine is resumed. All coroutines are automatically added with an interval of 0 by default, so calling this is only needed when you want to change the interval.
Coroutines are automatically resumed while waiting for input while editing the input line.
If a coroutine's interval is less than 5 seconds and the coroutine has been alive for more than 5 seconds, then the coroutine is throttled to run no more often than once every 5 seconds (regardless how much total time is has spent running). Throttling is meant to prevent long-running coroutines from draining battery power, interfering with responsiveness, or other potential problems.
Sets a name for the coroutine. This is purely for diagnostic purposes.
Creates and returns a new suggester object. Suggesters are consulted in the order their names are listed in the autosuggest.strategy
setting.
Define on the object a :suggest()
function that takes a line_state argument which contains the input line, and a matches argument which contains the possible completions. The function can return nil to give the next suggester a chance, or can return a suggestion (or an empty string) to stop looking for suggestions.
In Clink v1.2.51 and higher, the function may return a suggestion and an offset where the suggestion begins in the line. This is useful if the suggester wants to be able to insert the suggestion using the original casing. For example if you type "set varn" and a history entry is "set VARNAME" then returning "set VARNAME", 1
or "VARNAME", 5
can accept "set VARNAME" instead of "set varnAME".
See Customizing Suggestions for more information.
local doskeyarg = clink.suggester("doskeyarg")
function doskeyarg:suggest(line, matches)
if line:getword(1) == "doskey" and
line:getline():match("[ \t][^ \t/][^ \t]+=") and
not line:getline():match("%$%*") then
-- If the line looks like it defines a macro and doesn't yet add all
-- arguments, suggest adding all arguments.
if line:getline():sub(#line:getline()) == " " then
return "$*"
else
return " $*"
end
end
end
This overrides how Clink translates slashes in completion matches, which is normally determined by the match.translate_slashes
setting.
This is reset every time match generation is invoked, so use a generator to set this.
The mode specifies how to translate slashes when generators add matches:
Mode | Description |
---|---|
0 | No translation. |
1 | Translate using the system path separator (backslash on Windows). |
2 | Translate to slashes (/ ). |
3 | Translate to backslashes (\ ). |
4 | Translate using the first kind of slash found in the word being completed, or the system path separator if there are no slashes yet. (Only available in Clink v1.6.16 and higher.) |
If mode is omitted, then the function returns the current slash translation mode without changing it.
Note: Clink always generates file matches using the system path separator (backslash on Windows), regardless what path separator may have been typed as input. Setting this to 0
does not disable normalizing typed input paths when invoking completion; it only disables translating slashes in custom generators.
-- This example affects all match generators, by using priority -1 to
-- run first and returning false to let generators continue.
-- To instead affect only one generator, call clink.translateslashes()
-- in its :generate() function and return true.
local force_slashes = clink.generator(-1)
function force_slashes:generate()
clink.translateslashes(2) -- Convert to slashes.
return false -- Allow generators to continue.
end
This API correctly converts UTF8 strings to uppercase, with international linguistic awareness.
clink.upper("Hello World") -- returns "HELLO WORLD"
clink.lower("áèïÕÛ") -- returns "ÁÈÏÕÛ"
The commit part of the Clink version number. For v1.2.3.a0f14d the commit part is a0f14d.
The Clink version number encoded as a single integer following the format Mmmmpppp where M is the major part, m is the minor part, and p is the patch part of the version number.
For example, Clink v95.6.723 would be 950060723
.
This format makes it easy to test for feature availability by encoding version numbers from the release notes.
The major part of the Clink version number. For v1.2.3.a0f14d the major version is 1.
The minor part of the Clink version number. For v1.2.3.a0f14d the minor version is 2.
The patch part of the Clink version number. For v1.2.3.a0f14d the patch version is 3.
.console. up apis top
Returns the count of visible character cells that would be consumed if the text string were output to the console, accounting for any ANSI escape codes that may be present in the text.
Note: Backspace characters and line endings are counted as visible character cells and will skew the resulting count.
This returns an iterator function which steps through text one glyph at a time. Each call to the iterator function returns the string for the next glyph, the count of visible character cells that would be consumed when displaying it in the terminal, and a boolean indicating whether the string is an emoji.
Note: This only recognizes emojis if Clink recognizes that the terminal program supports emojis. The results are "best effort", and may differ from reality depending on the specific OS version, terminal program (and its version), and the input string. The width prediction is based on the Unicode emoji specification, with accommodations for how Windows Terminal renders certain emoji sequences.
-- UTF8 sample string:
-- Index by glyph: 12 3
-- Unicode character: A❤️ U+FE0F ZWJ 🔥 Z
local text = "A\xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x94\xa5Z"
-- Index by byte: 12 3 4 5 6 7 8 9 10 11 12 13 14 15
for str, width, emoji in console.cellcountiter(text) do
-- Build string showing byte values.
local bytes = ""
for i = 1, #str do
bytes = bytes .. string.format("\\x%02x", str:byte(i, i))
end
-- Print the cellcount substring and info about it.
clink.print(str, width, emoji, bytes)
-- Print the individual codepoints in the cellcount substring.
for s, value in unicode.iter(str) do
bytes = ""
for i = 1, #s do
bytes = bytes .. string.format("\\x%02x", s:byte(i, i))
end
clink.print("", s, string.format("U+%X", value), bytes)
end
end
-- The above prints the following:
-- A 1 false \x41
-- A U+41 \x41
-- ❤️🔥 2 true \xe2\x9d\xa4\xef\xb8\x8f\xe2\x80\x8d\xf0\x9f\x94\xa5
-- ❤ U+2764 \xe2\x9d\xa4
-- ️ U+FE0F \xef\xb8\x8f
-- U+200D \xe2\x80\x8d
-- 🔥 U+1F525 \xf0\x9f\x94\xa5
-- Z 1 false \x5a
-- Z U+5A \x5a
Checks whether input is available.
The optional timeout is the number of seconds to wait for input to be available (use a floating point number for fractional seconds). The default is 0 seconds, which returns immediately if input is not available.
If input is available before the timeout is reached, the return value is true. Use console.readinput() to read the available input.
In Clink v1.6.0 and higher, when timeout is negative, the timeout is infinite.
Note: Mouse input is not supported.
if console.checkinput() then
local key = console.readinput() -- Returns immediately since input is available.
if key == "\x03" or key == "\x1b[27;27~" or key == "\x1b" then
-- Ctrl-C or ESC was pressed.
end
end
Returns as much of text as fits in limit screen columns, truncated with either an ellipsis or the optional custom ellipsis string.
The optional mode can be any of the following:
Value | Description |
---|---|
"right" | Truncates from the right end of the input string. |
"left" | Truncates from the left end of the input string. |
"path" | Treats the input string as a file path and keeps any drive specifier, and truncates any directory portion from its left end. |
Note: Both text and/or ellipsis may include ANSI escape codes. When the "left"
or "path"
truncation modes are used, then any ANSI escape code to the left of the ellipsis are preserved, to ensure consistent styling regardless whether truncation occurs. Any ANSI escape codes in ellipsis are included as-is, which means it's possible for the caller to give the ellipsis string different styling from the rest of the string.
print(ellipsify("abcdef", 4))
-- abc…
print(ellipsify("abcdef", 4, "right", ".."))
-- ab..
print(ellipsify("abcdef", 4, "right", ""))
-- abcd
print(ellipsify("abcdef", 4, "left"))
-- …def
print(ellipsify("abcdefghijk", 8, "left", "[...]"))
-- [...]ijk
print(ellipsify("abcdefghijk", 4, "left", ""))
-- hijk
print(ellipsify("c:/abcd/wxyz", 8, "path"))
-- c:…/wxyz
print(ellipsify("c:/abcd/wxyz", 8, "path", "..."))
-- c:...xyz
print(ellipsify("c:/abcd/wxyz", 5, "path", ""))
-- c:xyz
Splits text on ANSI escape code boundaries and returns a table containing the substrings.
console.explodeansi("\x1b[7mReverse\x1b[0;1mBold\x1b[m\x1b[K")
-- returns the following table:
-- {
-- "\x1b[7m",
-- "Reverse",
-- "\x1b[0;1m",
-- "Bold",
-- "\x1b[m",
-- "\x1b[K",
-- }
Searches downwards (forwards) for a line containing the specified text and/or attributes, starting at line starting_line. The matching line number is returned, or 0 if no matching line is found.
This behaves the same as console.findprevline() except that it searches in the opposite direction.
Searches upwards (backwards) for a line containing the specified text and/or attributes, starting at line starting_line. The matching line number is returned, or 0 if no matching line is found, or -1 if an invalid regular expression is provided.
You can search for text, attributes, or both. Include the text argument to search for text, and include either the attr or attrs argument to search for attributes. If both text and attribute(s) are passed, then the attribute(s) must be found within the found text. If only attribute(s) are passed, then they must be found anywhere in the line. See console.linehascolor() for more information about the color codes.
The mode argument selects how the search behaves. To use a regular expression, pass "regex". To use a case insensitive search, pass "icase". These can be combined by separating them with a comma. The regular expression syntax is the ECMAScript syntax described here.
Any trailing whitespace is ignored when searching. This especially affects the $
(end of line) regex operator.
mask is optional and can be "fore" or "back" to only match foreground or background colors, respectively.
Note: Although most of the arguments are optional, the order of provided arguments is important.
For more information, see this example of using this in some luafunc: macros.
This returns a table containing the 16 predefined colors in the console's color theme.
Clink also tries to detect the terminal's background color. If it's able to, then the returned table also includes either a light = true
field or a dark = true
field.
The returned table also includes foreground
and background
fields which contain the index of the corresponding closest colors in the color table. If unable to determine the closest colors, then either of these fields may be missing.
**Note:** When using Windows Terminal, ConEmu, or other ConPty-based terminals it is currently not possible to get the current color theme until Terminal#10639 gets fixed. Until that's fixed, this can only return a default color table, which includes a default = true
field. When using the legacy conhost terminal then this is always able to report the current color theme.
Returns the current cursor column and row in the console screen buffer. The row is between 1 and console.getnumlines(). The column is between 1 and console.getwidth().
local x, y = console.getcursorpos()
Returns the number of visible lines of the console screen buffer.
Returns the text from line number line, from 1 to console.getnumlines().
Any trailing whitespace is stripped before returning the text.
Returns the total number of lines in the console screen buffer.
Returns the current top line (scroll position) in the console screen buffer.
Returns the width of the console screen buffer in characters.
Returns whether line number line uses only the default text color.
Returns whether line number line contains the DOS color code attr, or any of the DOS color codes in attrs (either an integer or a table of integers must be provided, but not both). mask is optional and can be "fore" or "back" to only match foreground or background colors, respectively.
The low 4 bits of the color code are the foreground color, and the high 4 bits of the color code are the background color. This refers to the default 16 color palette used by console windows. When 256 color or 24-bit color ANSI escape codes have been used, the closest of the 16 colors is used.
To build a color code, add the corresponding Foreground color and the Background color values from this table:
Foreground | Background | Color |
---|---|---|
0 | 0 | |
1 | 16 | |
2 | 32 | |
3 | 48 | |
4 | 64 | |
5 | 80 | |
6 | 96 | |
7 | 112 | |
8 | 128 | |
9 | 144 | |
10 | 160 | |
11 | 176 | |
12 | 192 | |
13 | 208 | |
14 | 224 | |
15 | 240 |
Returns the input text with ANSI escape codes removed, and the count of visible character cells that would be consumed if the text were output to the console.
Note: Backspace characters and line endings are counted as visible character cells and will skew the resulting count.
Reads one key sequence from the console input. If no input is available, it waits until input becomes available.
This returns the full key sequence string for the pressed key. For example, A is "A"
and Home is "\027[A"
, etc. Nil is returned when an interrupt occurs by pressing Ctrl-Break.
See Discovering Key Sequences for information on how to find the key sequence for a key.
In Clink v1.3.42 and higher, passing true for no_cursor avoids modifying the cursor visibility or position.
Note: Mouse input is not supported.
Uses the provided Lua string patterns to collect text from the current console screen and returns a table of matching text snippets. The snippets are ordered by distance from the input line.
For example candidate_pattern could specify a pattern that identifies words, and accept_pattern could specify a pattern that matches words composed of hexadecimal digits.
local matches = console.screengrab(
"[^%w]*(%w%w[%w]+)", -- Words with 3 or more letters are candidates.
"^%x+$") -- A candidate containing only hexadecimal digits is a match.
Scrolls the console screen buffer and returns the number of lines scrolled up (negative) or down (positive).
The mode specifies how to scroll:
Mode | Description |
---|---|
"line" | Scrolls by amount lines; negative is up and positive is down. |
"page" | Scrolls by amount pages; negative is up and positive is down. |
"end" | Scrolls to the top if amount is negative, or to the bottom if positive. |
"absolute" | Scrolls to line amount, from 1 to console.getnumlines(). |
.git. up apis top
getaction | getgitdir | hasstash |
getaheadbehind | getremote | isgitdir |
getbranch | getstashcount | loadconfig |
getcommondir | getstatus | makecommand |
getconflictstatus | getsystemname |
This checks for git actions in progress, and returns the action name. For certain actions it may also return the current step number and the total number of steps.
If unsuccessful, this returns nil.
The possible returned actions are:
"rebase-i"
: a rebase -i is in progress (includes step and total)."rebase-m"
: a rebase -m is in progress (includes step and total)."rebase"
: a rebase is in progress (includes step and total)."am"
: a "git am" is in progress (includes step and total)."am/rebase"
: a "git am" is in progress (includes step and total)."merge"
: a merge is in progress."cherry-pick"
: a cherry-pick is in progress."revert"
: a revert is in progress."bisect"
: a bisect is in progress.
local action, step, total = git.getaction()
if action then
print("current git action is '"..action.."'")
if step and total then
print(string.format("... step %d of %d", step, total))
end
else
print("no git action currently in progress")
end
Gets the number of commits ahead/behind from upstream.
In a git repo, it returns two strings:
- A string with the number commits ahead of upstream.
- A string with the number commits behind upstream.
Or when unsuccessful it returns nil.
Returns the current git branch for git_dir, or for the current working directory if git_dir is omitted.
If the workspace has a detached HEAD, then this returns two values: the short hash of the current HEAD commit, and true.
If unable to get the branch info, then nil is returned.
local branch, detached = git.getbranch()
Returns the common git dir for start_dir, or for the current working directory if git_dir is omitted.
When in a worktree, this returns the git dir for the main repo, rather than the git dir of the worktree itself.
Gets the conflict status for the repo or worktree associated with the current working directory.
Returns false if there are no conflicts, otherwise it returns true.
Tests whether dir is part of a git repo. If dir is omitted then it assumes the current working directory.
In a git repo, it returns three strings:
- The git dir.
- The workspace dir. If not in a workspace, then this matches the git dir.
- The original input dir.
Or when not in a git repo it returns nil.
See git.isgitdir() for examples (they return the same strings).
Gets the remote for the current branch for start_dir, or for the current working directory if git_dir is omitted.
Returns nil if the current branch cannot be found.
Returns the number of stashes that exist for the repo or worktree associated with the current working directory.
This runs git status
to collect status information for the repo or worktree associated with the current working directory.
If unsuccessful, this returns nil.
Otherwise it returns a table with the following scheme:
{
branch = ... -- branch name, or commit hash if detached
HEAD = ... -- HEAD commit hash, or "(initial)"
detached = ... -- true if HEAD is detached, otherwise nil
upstream = ... -- upstream name, other nil
dirty = ... -- true if working and/or staged changes, otherwise nil
ahead = ... -- number of commits ahead, otherwise nil
behind = ... -- number of commits behind, otherwise nil
unpublished = ... -- true if unpublished, otherwise nil
submodule = ... -- true if in a submodule, otherwise nil
onlystaged = ... -- number of changes only in staged files not in working files, otherwise nil
tracked = ... -- number of changes in tracked working files, otherwise nil
untracked = ... -- number of untracked files or directories, otherwise nil
conflict = ... -- number of conflicted files, otherwise nil
working = { -- nil if no working changes
add = ... -- number of added files
modify = ... -- number of modified files
delete = ... -- number of deleted files
conflict = ... -- number of conflicted files
untracked = ... -- number of untracked files or directories
}
staged = { -- nil if no staged changes
add = ... -- number of added files
modify = ... -- number of modified files
delete = ... -- number of deleted files
rename = ... -- number of renamed files
}
total = { -- nil if neither working nor staged
-- This counts files uniquely; if a file "foo" is deleted in working and
-- also in staged, it counts as only 1 deleted file. Etc.
add = ... -- total added files
modify = ... -- total modified files
delete = ... -- total deleted files
}
}
Example of checking whether the workspace is clean (no changes):
local status = git.getstatus()
if not status then
print("failed")
elseif status.dirty then
print("dirty (has changes)")
else
print("clean (no changes)")
end
**Compatibility Note:** This requires a version of git that supports git status --porcelain=v2
. Porcelain v2 format has existed for a long time, so that isn't expected to be a limitation in practice.
luacheck: pop
Checks whether dir is under git source control, and returns "git"
if it is. Otherwise returns nil.
Returns whether any stashes exist for the repo or worktree associated with the current working directory.
Tests whether dir is a git repo root, or a workspace dir, or a submodule dir. If dir is omitted then it assumes the current working directory.
In a git repo, it returns three strings:
- The git dir.
- The workspace dir. If not in a workspace, then this matches the git dir.
- The original input dir.
Or when not in a git repo it returns nil.
Examples:
-- In a repo c:\repo:
git.isgitdir("c:/repo")
-- Returns: "c:\repo\.git", "c:\repo\.git", "c:\repo"
-- In a submodule under c:\repo:
git.isgitdir("c:/repo/submodule")
-- Returns: "c:\repo\.git\modules\submodule", "c:\repo\.git", "c:\repo\submodule"
-- In a worktree under c:\repo:
git.isgitdir("c:/repo/worktree")
-- Returns: "c:\repo\.git\worktrees\worktree", "c:\repo\worktree\.git", "c:\repo\worktree"
-- In a worktree outside c:\repo:
git.isgitdir("c:/worktree")
-- Returns: "c:\repo\.git\worktrees\worktree", "c:\worktree\.git", "c:\worktree"
Loads a git config file and returns a table containing the data, or returns nil if unable to load the config file.
The function accepts either a git dir string or a boolean indicating whether to load the system config file. If neither is provided then it loads the repo config file.
The returned table has a :get(section, param)
function to make it convenient to look up config parameters.
local config = git.loadconfig()
print(config:get("core", "autocrlf"))
print(config:get("user", "name"))
Returns a command line for running the specified git command. The command line automatically prepends git
to the input command string, plus disables git's optional locks and advice messages. Unless include_stderr is true, it also includes 2>nul
to hide stderr output.
If command is missing or empty, it returns nil.
git.makecommand("rev-parse HEAD")
.io. up apis top
open |
popenrw |
popenyield |
sopen |
truncate |
This function opens a file named by filename, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message and error number.
The mode string can be any of the following:
"r"
: opens for read (the default);"w"
: opens for write, all previous data is erased;"wx"
: opens for write, but fail if the file already exists (requires v1.3.18 or higher);"a"
: opens for writing at the end of the file (append), creates the file if it doesn't exist;"r+"
: opens for read and write, all previous data is preserved;"w+"
: opens for read and write, all previous data is erased;"w+x"
: opens for read and write, all previous data is erased, but fail if the file already exists (requires v1.3.18 or higher);"a+"
: opens for reading and writing at the end of the file (append), writing is only allowed at the end of file, creates the file if it doesn't exist.
The mode string can also have a 'b'
at the end to open the file in binary mode.
The 'x'
modes are Clink extensions to Lua.
Runs command and returns two file handles: a file handle for reading output from the command, and a file handle for writing input to the command.
mode can be "t" for text mode (the default if omitted) or "b" for binary mode.
If the function fails it returns nil, an error message, and an error number.
local r,w = io.popenrw("fzf.exe --height 40%")
w:write("hello\n")
w:write("world\n")
w:close()
while (true) do
local line = r:read("*line")
if not line then
break
end
print(line)
end
r:close()
This behaves similar to io.popen() except that it only supports read mode and when used in a coroutine it yields until the command has finished.
The command argument is the command to run.
The mode argument is the optional mode to use. It can contain "r" (read mode) and/or either "t" for text mode (the default if omitted) or "b" for binary mode. Write mode is not supported, so it cannot contain "w".
This runs the specified command and returns a read file handle for reading output from the command. It yields until the command has finished and the complete output is ready to be read without blocking.
In v1.3.31 and higher, it may also return a function. If the second return value is a function then it can be used to get the exit status for the command. The function returns the same values as os.execute(). The function may be used only once, and it closes the read file handle, so if the function is used then do not use file:close()
. Or, if the second return value is not a function, then the exit status may be retrieved from calling file:close()
on the returned file handle.
Compatibility Note: when io.popen()
is used in a coroutine, it is automatically redirected to io.popenyield()
. This means on success the second return value from io.popen()
in a coroutine may not be nil as callers might normally expect.
Note: if the prompt.async
setting is disabled, or while a transient prompt filter is executing, or if used outside of a coroutine, then this behaves like io.popen() instead.
local file = io.popenyield("git status")
while (true) do
local line = file:read("*line")
if not line then
break
end
do_things_with(line)
end
file:close()
Here is an example showing how to get the exit status, if desired:
-- Clink v1.3.31 and higher return a pclose function, for optional use.
local file, pclose = io.popenyield("kubectl.exe")
if file then
local ok, what, code = pclose()
end
This is the same as io.open(), but adds an optional deny
argument that specifies the type of sharing allowed.
This function opens a file named by filename, in the mode specified in the string mode. It returns a new file handle, or, in case of errors, nil plus an error message and error number.
The mode string can be any of the following:
"r"
: opens for read (the default);"w"
: opens for write, all previous data is erased;"wx"
: opens for write, but fail if the file already exists (requires v1.3.18 or higher);"a"
: opens for writing at the end of the file (append), creates the file if it doesn't exist;"r+"
: opens for read and write, all previous data is preserved;"w+"
: opens for read and write, all previous data is erased;"w+x"
: opens for read and write, all previous data is erased, but fail if the file already exists (requires v1.3.18 or higher);"a+"
: opens for reading and writing at the end of the file (append), writing is only allowed at the end of file, creates the file if it doesn't exist.
The mode string can also have a 'b'
at the end to open the file in binary mode.
The deny string can be any of the following:
"r"
denies read access;"w"
denies write access;"rw"
denies read and write access;""
permits read and write access (the default).
This function truncates the file previously opened by io.open() or io.sopen(). When used on a pipe or other file handle that doesn't refer to an actual file, the behavior is undefined.
If successful, the return value is true. If an error occurs, the return value is false, an error message, and an error code.
.line_state: up apis top
getcommandoffset | getendwordoffset | getword |
getcommandwordindex | getline | getwordcount |
getcursor | getrangelength | getwordinfo |
getendword | getrangeoffset |
Returns the offset to the start of the delimited command in the line that's being effectively edited. Note that this may not be the offset of the first command of the line unquoted as whitespace isn't considered for words.
-- Given the following line; abc&123
-- ^
-- In the line_state for the second command;
line_state:getcommandoffset() == 5
The command offset points to the beginning of the command, but that might be a space character. Two spaces after a command separator is like one space at the beginning of a line; it disables doskey alias expansion. So, if the command offset points at a space, then you know the first word will not be treated as a doskey alias.
-- Given the following line; abc& 123
-- ^
-- In the line_state for the second command;
line_state:getcommandoffset() == 6
Returns the index of the command word. Usually the index is 1, but if a redirection symbol occurs before the command name then the index can be greater than 1.
-- Given the following line; >x abc
-- the first word is "x" and is an argument to the redirection symbol,
-- and the second word is "abc" and is the command word.
line_state:getcommandwordindex() == 2
Returns the last word of the line. This is the word that matches are being generated for.
Note: The returned word omits any quotes. This helps generators naturally complete "foo\"ba
to "foo\bar"
. The raw word including quotes can be obtained using the offset
and length
fields from line_state:getwordinfo() to extract a substring from the line returned by line_state:getline().
line_state:getword(line_state:getwordcount()) == line_state:getendword()
However: During generator:getwordbreakinfo()
functions the returned word includes quotes, otherwise word break offsets could be garbled.
Returns the offset of the last word of the line. This is the word that matches are being generated for.
Returns the current line in its entirety.
Each line_state describes a range of text in a line. This function returns the length of the range described by this line_state.
For all commands after the first command in a line, the first space (if any) is not part of the range. See [line_state:getcommandoffset](#line_state:getcommandoffset) for details.
-- Given a line_state for the 2nd command in; abc & ( @where >nul ) & xyz
line_state:getrangeoffset() == 9 -- ^
line_state:getcommandoffset() == 10 -- ^
line_state:getrangelength() == 15 -- <------------->
-- Given a line_state for the 2nd command in; abc & ( @ where >nul ) & xyz
line_state:getrangeoffset() == 9 -- ^
line_state:getcommandoffset() == 13 -- ^
line_state:getrangelength() == 18 -- <---------------->
Each line_state describes a range of text in a line. This function returns the offset to the start of the range described by this line_state.
For all commands after the first command in a line, the first space (if any) is not part of the range. See [line_state:getcommandoffset](#line_state:getcommandoffset) for details.
-- Given a line_state for the 2nd command in; abc & ( @where >nul ) & xyz
line_state:getrangeoffset() == 9 -- ^
line_state:getcommandoffset() == 10 - ^
line_state:getrangelength() == 15 -- <------------->
-- Given a line_state for the 2nd command in; abc & ( @ where >nul ) & xyz
line_state:getrangeoffset() == 9 -- ^
line_state:getcommandoffset() == 13 -- ^
line_state:getrangelength() == 18 -- <---------------->
Returns the word of the line at index.
Note: The returned word omits any quotes. This helps generators naturally complete "foo\"ba
to "foo\bar"
. The raw word including quotes can be obtained using the offset
and length
fields from line_state:getwordinfo() to extract a substring from the line returned by line_state:getline().
However: During generator:getwordbreakinfo()
functions the returned word includes quotes, otherwise word break offsets could be garbled.
Returns the number of words in the current line.
Returns a table of information about the Nth word in the line.
Note: The length refers to the substring in the line; it omits leading and trailing quotes, but includes embedded quotes. line_state:getword() conveniently strips embedded quotes to help generators naturally complete "foo\"ba
to "foo\bar"
.
The table returned has the following scheme:
local t = line_state:getwordinfo(word_index)
-- t.offset [integer] Offset where the word starts in the line_state:getline() string.
-- t.length [integer] Length of the word (includes embedded quotes).
-- t.quoted [boolean] Indicates whether the word is quoted.
-- t.delim [string] The delimiter character, or an empty string.
-- t.alias [boolean | nil] true if the word is a doskey alias, otherwise nil.
-- t.redir [boolean | nil] true if the word is a redirection arg, otherwise nil.
.log. up apis top
getfile |
info |
Returns the file name of the current session's log file.
Writes info message to the Clink log file. Use this sparingly, or it could cause performance problems or disk space problems.
In v1.4.10 and higher, the optional level number tells which stack level to log as the source of the log message (default is 1, the function calling log.info
).
.matches: up apis top
getcount |
getmatch |
getprefix |
gettype |
Returns the match text for the index match.
Returns the longest common prefix of the available matches.
Returns the match type for the index match.
.os. up apis top
This abbreviates parent directories in path to the shortest string that uniquely identifies the directory. The drive, if present, is never abbreviated. By default, the first and last names in the string are not abbreviated.
For performance reasons, UNC paths and paths on remote or removeable drives are never abbreviated.
The return value is the resulting path after abbreviation.
If an optional decide function is provided then it is called once for each directory name in path, and it can control which directories get abbreviated. The decide function receives one argument: the path to the directory that may be abbreviated. The function can return true to try to abbreviate the directory, or false to prevent abbreviating the directory, or nil to allow the default behavior (don't abbreviate the first or last directory names).
If an optional transform function is provided then it is called once for each directory name in the resulting string. The transform function receives two arguments: the string to be appended, and a boolean indicating whether it has been abbreviated. The function can adjust the string, and should return a string to appended. If it returns nil, the string is appended as-is. This is intended to be able to apply ANSI escape color codes, for example to highlight special directories or to show which directory names have been abbreviated.
This function can potentially take some time to complete, but it can be called in a coroutine and yields appropriately. It is the caller's responsibility to ensure that any decide or transform functions are either very fast, yield appropriately, or are not used from a coroutine.
-- Suppose only the following directories exist in the D:\xyz directory:
-- - D:\xyz\bag
-- - D:\xyz\bookkeeper
-- - D:\xyz\bookkeeping
-- - D:\xyz\box
-- - D:\xyz\boxes
-- - D:\xyz\nonrepo
-- - D:\xyz\repo
os.abbreviatepath("d:\\xyz") -- returns "d:\\xyz"
os.abbreviatepath("d:\\xyz\\bag") -- returns "d:\\xyz\\bag"
os.abbreviatepath("d:\\xyz\\bag\\subdir") -- returns "d:\\xyz\\ba\\subdir"
os.abbreviatepath("d:\\xyz\\bookkeeper") -- returns "d:\\xyz\\bookkeeper"
os.abbreviatepath("d:\\xyz\\bookkeeper\\subdir") -- returns "d:\\xyz\\bookkeepe\\subdir"
os.abbreviatepath("d:\\xyz\\bookkeeping\\file") -- returns "d:\\xyz\\bookkeepi\\file"
os.abbreviatepath("d:\\xyz\\box\\subdir") -- returns "d:\\xyz\\box\\subdir"
os.abbreviatepath("d:\\xyz\\boxes\\file") -- returns "d:\\xyz\\boxe\\file"
-- Examples with a `decide` function.
local function not_git_dir(dir)
if os.isdir(path.join(dir, ".git")) then
return false -- Don't abbreviate git repo directories.
end
end
os.abbreviatepath("d:\\xyz\\nonrepo\\subdir", not_git_dir) -- returns "d:\\xyz\\n\\subdir"
os.abbreviatepath("d:\\xyz\\repo\\subdir", not_git_dir) -- returns "d:\\xyz\\repo\\subdir"
-- Example with a `decide` function and a `transform` function.
local function do_all(dir)
return true
end
local function dim_abbrev(name, abbrev)
if abbrev then
return "\027[38m"..name.."\027[m" -- Use dark gray text.
else
return name
end
end
os.abbreviatepath("d:\\xyz\\bag", do_all, dim_abbrev)
-- returns "c:\\\027[38mx\027[m\\\027[38mba\027[m"
-- Relative paths work as well.
os.chdir("d:\\xyz")
os.abbreviatesetcurrentdir("bag\\subdir", true) -- returns "ba\\s" (if "subdir" is unique)
Changes the current directory to path and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
This returns the number of seconds since the program started.
Normally, Lua's os.clock() has millisecond precision until the program has been running for almost 25 days, and then it suddenly breaks and starts always returning -0.001 seconds.
Clink's version of os.clock() has microsecond precision until the program has been running for many weeks. It maintains at least millisecond precision until the program has been running for many years.
It was necessary to replace os.clock() in order for asynchronous prompt filtering to continue working when CMD has been running for more than 25 days.
Copies the src file to the dest file. If unsuccessful it returns false, an error message, and the error number.
Generates a 128-bit unique ID represented as 32 hexadecimal characters.
By default, this uses the OS `UuidCreate()` API to create a unique ID.
When the optional faster argument is true
then this uses `UuidCreateSequential()` instead, which is faster but can potentially be traced back to the ethernet address of the computer.
If successful, this returns a 32 digit hexadecimal string and a boolean value. When the boolean value is true then the ID is only locally unique, and cannot safely be used to uniquely identify an object that is not strictly local to your computer.
If an error occurs, this returns nil.
IMPORTANT: Not all of the 128 bits necessarily have the same degree of entropy on each computer. If you discard any bits from the string then you could accidentally greatly reduce the uniqueness of the ID (even on the same computer), or even completely remove all entropy.
Creates a uniquely named file, intended for use as a temporary file. The name pattern is "location \
prefix _
processId _
uniqueNum extension".
prefix optionally specifies a prefix for the file name and defaults to "tmp".
ext optionally specifies a suffix for the file name and defaults to "" (if ext starts with a period "." then it is a filename extension).
path optionally specifies a path location in which to create the file. The default is the system TEMP directory.
mode optionally specifies "t" for text mode (line endings are translated) or "b" for binary mode (untranslated IO). The default is "t".
When successful, the function returns a file handle and the file name. If unsuccessful it returns nil, an error message, and the error number.
Note: Be sure to delete the file when finished, or it will be leaked.
This returns an iterator function which steps through the share names available on the given server one name at a time. (This only enumerates SMB UNC share names.)
When hidden is true, special hidden shares like ADMIN$ or C$ are included.
The optional timeout is the maximum number of seconds to wait for shares to be retrieved (use a floating point number for fractional seconds). The default is 0, which means an unlimited wait (negative numbers are treated the same as 0).
Each call to the returned iterator function returns a share name, a boolean indicating whether it's a special share, and either nil or "canceled" (if it takes longer than timeout to retrieve the share names for the given server). When there are no more shares, the iterator function returns nil.
When called from a coroutine, the iterator function automatically yields when appropriate.
local server = "localhost"
local hidden = true -- Include special hidden shares.
local timeout = 2.5 -- Wait up to 2.5 seconds for completion.
for share, special, canceled in os.enumshares(server, hidden, timeout) do
local s = "\\\\"..server.."\\"..share
if special then
s = s.." (special)"
end
if canceled then
s = s.." ("..canceled..")"
end
print(s)
end
This expands any abbreviated directory components in path.
The return value is nil if path couldn't be expanded. It can't be expanded if it is a UNC path or a remote drive, or if it is already expanded, or if there are no matches for one of the directory components.
Otherwise three values are returned. First, a string containing the expanded part of path. Second, a string containing the rest of path that wasn't expanded. Third, a boolean indicating whether path was able to expand uniquely.
-- Suppose only the following directories exist in the D: drive:
-- - D:\bag
-- - D:\bookkeeper
-- - D:\bookkeeping
-- - D:\box
-- - D:\boxes
expanded, remaining, unique = os.expandabbreviatedpath("d:\\b\\file")
-- returns "d:\\b", "\\file", false -- Ambiguous.
expanded, remaining, unique = os.expandabbreviatedpath("d:\\ba\\file")
-- returns "d:\\bag", "\\file", true -- Unique; only "bag" can match "ba".
expanded, remaining, unique = os.expandabbreviatedpath("d:\\bo\\file")
-- returns "d:\\bo", "\\file", false -- Ambiguous.
expanded, remaining, unique = os.expandabbreviatedpath("d:\\boo\\file")
-- returns "d:\\bookkeep", "\\file", false -- Ambiguous; "bookkeep" is longest common part matching "boo".
expanded, remaining, unique = os.expandabbreviatedpath("d:\\box\\file")
-- returns "d:\\box", "\\file", false -- Ambiguous; "box" is an exact match.
expanded, remaining, unique = os.expandabbreviatedpath("d:\\boxe\\file")
-- returns "d:\\boxes", "\\file", true -- Unique; only "boxes" can match "boxe".
expanded, remaining, unique = os.expandabbreviatedpath("d:\\boxes\\file")
-- returns nil -- Is already expanded.
Returns value with any %name%
environment variables expanded. Names are case insensitive. Special CMD syntax is not supported (e.g. %name:str1=str2%
or %name:~offset,length%
).
Note: See os.getenv() for a list of special variable names.
Returns an object that can be used to get files and/or directories matching pattern.
Note: Any quotation marks ("
) in pattern are stripped.
Unlike os.globfiles, this only collects matching files or directories one at a time, instead of collecting all matches in a table.
The returned object has the following functions:
- next() - Returns the next file or directory, or nil where there are no more.
- files() - Returns a Lua iterator function which can be used in a for loop, returning the next file or directory each time.
- close() - Releases the OS resources used for the search. This is automatically called by the Lua garbage collector, but that may not happen quickly enough to avoid interfering with operations such as deleting a parent directory, so it's good to call
:close()
directly.
-- Print the first matching file, without wasting time collecting
-- the rest of the files, since they aren't needed here.
local ff = os.findfiles(pattern)
local name = ff:next()
print(name)
ff:close()
By default :next()
returns a string containing the name of the file or directory. The optional extrainfo argument can instead return a table corresponding to one file or directory, with the following scheme:
local ff = os.findfiles(pattern, extrainfo)
local t = ff:next()
-- Included when extrainfo is true or >= 1:
-- t.name -- [string] The file or directory name.
-- t.type -- [string] The match type (see below).
-- Included when extrainfo is 2:
-- t.size -- [number] The file size, in bytes.
-- t.atime -- [number] The access time, compatible with os.time().
-- t.mtime -- [number] The modified time, compatible with os.time().
-- t.ctime -- [number] The creation time, compatible with os.time().
ff:close()
The type string can be "file" or "dir", and may also contain ",hidden", ",readonly", ",link", and ",orphaned" depending on the attributes (making it usable as a match type for builder:addmatch()).
The optional flags argument can be a table with fields that select how finding files should behave. By default files, directories, hidden files/directories are included, system files/directories are omitted, and directories have a \
suffix.
local flags = {
files = true, -- True includes files, or false omits them.
dirs = true, -- True includes directories, or false omits them.
hidden = true, -- True includes hidden files (default), or false omits them.
system = false, -- True includes system files, or false omits them (default).
dirsuffix = true, -- True adds a \ suffix to directories, or false omits it.
}
local ff = os.findfiles(pattern, true, flags)
for t in ff:files() do
print(t.name.." ("..t.type..")")
end
ff:close()
Returns command string for doskey alias name, or nil if the named alias does not exist.
Returns doskey alias names in a table of strings.
Returns a table containing the battery status for the device, or nil if an error occurs. The returned table has the following scheme:
local t = os.getbatterystatus()
-- t.level [integer] The battery life from 0 to 100, or -1 if error or no battery.
-- t.acpower [boolean] Whether the device is connected to AC power.
-- t.charging [boolean] Whether the battery is charging.
-- t.batterysaver [boolean] Whether Battery Saver mode is active.
This returns the text from the system clipboard, or nil if there is no text on the system clipboard.
Returns the drive type for the drive associated with the specified path.
Relative paths automatically use the current drive. Absolute paths use the specified drive. UNC paths are always reported as remote drives.
The possible drive types are:
Type | Description |
---|---|
"unknown" | The drive type could not be determined. |
"invalid" | The drive type is invalid; for example, there is no volume mounted at the specified path. |
"removable" | Floppy disk drive, thumb drive, flash card reader, CD-ROM, etc. |
"fixed" | Hard drive, solid state drive, etc. |
"ramdisk" | RAM disk. |
"remote" | Remote (network) drive. |
local t = os.getdrivetype("c:")
if t == "remote" then
-- Network paths are often slow, and code may want to detect and skip them.
end
Returns the value of the named environment variable, or nil if it doesn't exist.
Note: Certain environment variable names receive special treatment:
Name | Special Behavior |
---|---|
"CD" | If %CD% is not set then a return value is synthesized from the current working directory path name. |
"CMDCMDLINE" | If %CMDCMDLINE% is not set then this returns the command line that started the CMD process. |
"ERRORLEVEL" | If %ERRORLEVEL% is not set and the cmd.get_errorlevel setting is enabled this returns the most recent exit code, just like the echo %ERRORLEVEL% command displays. Otherwise this returns 0. |
"HOME" | If %HOME% is not set then a return value is synthesized from %HOMEDRIVE% and %HOMEPATH%, or from %USERPROFILE%. |
"RANDOM" | If %RANDOM% is not set then this returns a random integer. |
Returns all environment variables in a table with the following scheme:
local t = os.getenvnames()
-- t[index].name [string] The environment variable's name.
-- t[index].value [string] The environment variable's value.
Returns the last command's exit code, if the cmd.get_errorlevel
setting is enabled. Otherwise it returns 0.
This tries to get a Windows file version info resource from the specified file. It tries to get translated strings in the closest available language to the current user language configured in the OS.
If successful, the returned table contains as many of the following fields as were available in the file's version info resource.
local info = os.getfileversion("c:/windows/notepad.exe")
-- info.filename c:\windows\notepad.exe
-- info.filevernum 10.0.19041.1865
-- info.productvernum 10.0.19041.1865
-- info.fileflags
-- info.osplatform Windows NT
-- info.osqualifier
-- info.comments
-- info.companyname Microsoft Corporation
-- info.filedescription Notepad
-- info.fileversion 10.0.19041.1 (WinBuild.160101.0800)
-- info.internalname Notepad
-- info.legalcopyright © Microsoft Corporation. All rights reserved.
-- info.legaltrademarks
-- info.originalfilename NOTEPAD.EXE.MUI
-- info.productname Microsoft® Windows® Operating System
-- info.productversion 10.0.19041.1
-- info.privatebuild
-- info.specialbuild
Note: The fileflags field may be nil (omitted), or it may contain a table with additional fields.
if info.fileflags then
-- info.fileflags.debug
-- info.fileflags.prerelease
-- info.fileflags.patched
-- info.fileflags.privatebuild
-- info.fileflags.specialbuild
end
Returns the full path name for path. If unsuccessful it returns nil, an error message, and the error number.
Returns the fully qualified file name of the host process. Currently only CMD.EXE can host Clink.
Returns the long path name for path. If unsuccessful it returns nil, an error message, and the error number.
Returns the remote name associated with path, or an empty string if it's not a network drive. If unsuccessful it returns nil, an error message, and the error number.
Returns the CMD.EXE process ID. This is mainly intended to help with salting unique resource names (for example named pipes).
Returns the depth of the pushd
directory stack, and a boolean indicating whether the depth is known.
Note: The depth is only known if the %PROMPT%
environment variable includes the $+
code exactly once.
Returns dimensions of the terminal's buffer and visible window. The returned table has the following scheme:
local info = os.getscreeninfo()
-- info.bufwidth [integer] Width of the screen buffer.
-- info.bufheight [integer] Height of the screen buffer.
-- info.winwidth [integer] Width of the visible window.
-- info.winheight [integer] Height of the visible window.
-- v1.4.28 and higher include the cursor position:
-- info.x [integer] Current cursor column (from 1 to bufwidth).
-- info.y [integer] Current cursor row (from 1 to bufheight).
Returns the 8.3 short path name for path. This may return the input path if an 8.3 short path name is not available. If unsuccessful it returns nil, an error message, and the error number.
Returns the path of the system temporary directory. If unsuccessful it returns nil, an error message, and the error number.
Collects directories matching globpattern and returns them in a table of strings.
Note: Any quotation marks ("
) in globpattern are stripped.
Starting in v1.3.1, when this is used in a coroutine it automatically yields periodically.
The optional extrainfo argument can return a table of tables instead, where each sub-table corresponds to one directory and has the following scheme:
local t = os.globdirs(pattern, extrainfo)
-- Included when extrainfo is true or >= 1 (requires v1.1.7 or higher):
-- t[index].name -- [string] The directory name.
-- t[index].type -- [string] The match type (see below).
-- Included when extrainfo is 2 (requires v1.2.31 or higher):
-- t[index].size -- [number] The file size, in bytes.
-- t[index].atime -- [number] The access time, compatible with os.time().
-- t[index].mtime -- [number] The modified time, compatible with os.time().
-- t[index].ctime -- [number] The creation time, compatible with os.time().
The type string is "dir", and may also contain ",hidden", ",readonly", ",link", and ",orphaned" depending on the attributes (making it usable as a match type for builder:addmatch()).
Starting in v1.4.16, the optional flags argument can be a table with fields that select how directory globbing should behave. By default hidden directories are included and system directories are omitted.
local flags = {
hidden = true, -- True includes hidden directories (default), or false omits them.
system = false, -- True includes system directories, or false omits them (default).
}
local t = os.globdirs("*", true, flags)
Collects files and/or directories matching globpattern and returns them in a table of strings.
Note: Any quotation marks ("
) in globpattern are stripped.
Starting in v1.3.1, when this is used in a coroutine it automatically yields periodically.
The optional extrainfo argument can return a table of tables instead, where each sub-table corresponds to one file or directory and has the following scheme:
local t = os.globfiles(pattern, extrainfo)
-- Included when extrainfo is true or >= 1 (requires v1.1.7 or higher):
-- t[index].name -- [string] The file or directory name.
-- t[index].type -- [string] The match type (see below).
-- Included when extrainfo is 2 (requires v1.2.31 or higher):
-- t[index].size -- [number] The file size, in bytes.
-- t[index].atime -- [number] The access time, compatible with os.time().
-- t[index].mtime -- [number] The modified time, compatible with os.time().
-- t[index].ctime -- [number] The creation time, compatible with os.time().
The type string can be "file" or "dir", and may also contain ",hidden", ",readonly", ",link", and ",orphaned" depending on the attributes (making it usable as a match type for builder:addmatch()).
Starting in v1.4.16, the optional flags argument can be a table with fields that select how file globbing should behave. By default hidden files are included and system files are omitted.
local flags = {
hidden = true, -- True includes hidden files (default), or false omits them.
system = false, -- True includes system files, or false omits them (default).
}
local t = os.globfiles("*", true, flags)
Collects files or directories matching pattern and returns them in a table of strings. This matches **
patterns the same as git does. When pattern ends with /
this collects directories, otherwise it collects files.
Note: any quotation marks ("
) in pattern are stripped.
When this is used in a coroutine it automatically yields periodically.
The optional extrainfo argument can return a table of tables instead, where each sub-table corresponds to one file or directory and has the following scheme:
local t = os.globmatch(pattern, extrainfo)
-- Included when extrainfo is true or >= 1:
-- t[index].name -- [string] The file or directory name.
-- t[index].type -- [string] The match type (see below).
-- Included when extrainfo is 2:
-- t[index].size -- [number] The file size, in bytes.
-- t[index].atime -- [number] The access time, compatible with os.time().
-- t[index].mtime -- [number] The modified time, compatible with os.time().
-- t[index].ctime -- [number] The creation time, compatible with os.time().
The type string can be "file" or "dir", and may also contain ",hidden", ",readonly", ",link", and ",orphaned" depending on the attributes (making it usable as a match type for builder:addmatch()).
The optional flags argument can be a table with fields that select how the globbing should behave. By default hidden files are included, system files are omitted, and comparisons are case insensitive.
local flags = {
hidden = true, -- True includes hidden files (default), or false omits them.
system = false, -- True includes system files, or false omits them (default).
period = false, -- True matches files beginning with period (.) if pattern has a corresponding
-- period, or false matches even without a corresponding period (default).
nocasefold = false, -- True is case-sensitive, or false is case-insensitive (default).
}
local t = os.globmatch("docs/**/*.md", true, flags)
Note: The returned table is built using a pre-order traversal, so files in a directory are listed before recursing into its subdirectories ("dir\xyzfile" precedes "dir\abcdir\abcfile").
Returns whether a
Returns true if running as an administrator account.
Creates the directory path and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
Moves the src file to the dest file. If unsuccessful it returns false, an error message, and the error number.
Identifies whether text begins with a doskey alias, and expands the doskey alias.
Returns a table of strings, or nil if there is no associated doskey alias. The return type is a table of strings because doskey aliases can be defined to expand into multiple command lines: one entry in the table per resolved command line. Most commonly, the table will contain one string.
Removes the directory path and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
Sets a doskey alias name to command. Returns true if successful, or returns false if not successful.
Note: For more information on the syntax of doskey aliases in Windows read documentation on the doskey
command, or run doskey /?
for a quick summary.
This sets the text onto the system clipboard, and returns whether it was successful.
Sets the name environment variable to value and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
Sleeps for the indicated duration, in seconds, with millisecond granularity.
os.sleep(0.01) -- Sleep for 10 milliseconds.
Sets the access and modified times for path, and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
The second argument is atime and is a time to set as the file's access time. If omitted, the current time is used. If present, the value must use the same format as os.time()
.
The third argument is mtime and is a time to set as the file's modified time. If omitted, the atime value is used (or the current time). If present, the value must use the same format as os.time()
. In order to pass mtime it is necessary to also pass atime.
Deletes the file path and returns whether it was successful. If unsuccessful it returns false, an error message, and the error number.
.path. up apis top
fnmatch | getname |
getbasename | isexecext |
getdirectory | join |
getdrive | normalise |
getextension | toparent |
This compares the two strings pattern and string and returns whether they are considered to match. This is like the Linux fnmatch
function, with an additional optional mode that can allow matching **
patterns the same as git does.
The optional flags string may contain any of the following characters to modify the behavior accordingly:
Flag | Mnemonic | Description |
---|---|---|
"e " | NoEscape | Treat backslash in pattern as a normal character, rather than as an escape character. |
"p " | PathName | Path separators in string are matched only by a slash / in pattern (unless the * flag is used; see below). |
". " | Period | A leading period . in string is matched only by a period . in pattern. A leading period is one at the beginning of string, or immediately following a path separator when the p flag is used. |
"l " | LeadingDir | Consider pattern to be matched if it completely matches string, or if it matches string up to a path separator. |
"c " | NoCaseFold | Match with case sensitivity. By default it matches case-insensitively, because Windows is case-insensitive. |
"* " | WildStar | Treat double-asterisks in pattern as matching path separators as well, the same as how git does (implies the p flag). |
"s " | NoSlashFold | Treat slashes / in pattern as only matching slashes in string. By default slashes in pattern match both slash / and backslash \ because Windows recognizes both as path separators. |
The pattern supports wildcards (?
and *
), character classes ([
...]
), ranges ([
.-
.]
), and complementation ([!
...]
and [!
.-
.]
).
The pattern also supports the following character classes:
- "
[[:alnum:]]
": Matches any alphabetic character or digit a - z, or A - Z, or 0 - 9. - "
[[:alpha:]]
": Matches any alphabetic character a - z or A - Z. - "
[[:blank:]]
": Matches 0x20 (space) or 0x09 (tab). - "
[[:cntrl:]]
": Matches 0x00 - 0x1F or 0x7F. - "
[[:digit:]]
": Matches any of the digits 0 - 9. - "
[[:graph:]]
": Matches any character that matches[[:print:]]
but does not match[[:space:]]
. - "
[[:lower:]]
": Matches any lower case ASCII letter a - z. - "
[[:print:]]
": Matches any printable character (e.g. 0x20 - 0x7E). - "
[[:punct:]]
": Matches any character that matches[[:print:]]
but does not match[[:alnum:]]
,[[:space:]]
, or[[:alnum:]]
. - "
[[:space:]]
": Matches 0x20 (space) or 0x09 - 0x0D (tab, linefeed, carriage return, etc). - "
[[:xdigit:]]
": Matches any of the hexadecimal digits 0 - 9, A - F, or a - f. - "
[[:upper:]]
": Matches any upper case ASCII letter A - Z.
Note: At this time the character classes and case-insensitivity operate on one byte at a time, so they do not fully work as expected with non-ASCII characters.
path.getbasename("/foo/bar.ext") -- returns "bar"
path.getbasename("") -- returns ""
This is similar to path.toparent() but can behave differently when the input path ends with a path separator. This is the recommended API for parsing a path into its component pieces, but is not recommended for walking up through parent directories.
path.getdirectory("foo") -- returns nil
path.getdirectory("\\foo") -- returns "\\"
path.getdirectory("c:foo") -- returns "c:"
path.getdirectory("c:\\") -- returns "c:\\"
path.getdirectory("c:\\foo") -- returns "c:\\"
path.getdirectory("c:\\foo\\bar") -- returns "c:\\foo"
path.getdirectory("\\\\foo\\bar") -- returns "\\\\foo\\bar"
path.getdirectory("\\\\foo\\bar\\dir") -- returns "\\\\foo\\bar"
path.getdirectory("") -- returns nil
-- These split the path components differently than path.toparent().
path.getdirectory("c:\\foo\\bar\\") -- returns "c:\\foo\\bar"
path.getdirectory("\\\\foo\\bar\\dir\\") -- returns "\\\\foo\\bar\\dir"
path.getdrive("e:/foo/bar") -- returns "e:"
path.getdrive("foo/bar") -- returns nil
path.getdrive("") -- returns nil
path.getextension("bar.ext") -- returns ".ext"
path.getextension("bar") -- returns ""
path.getextension("") -- returns ""
path.getname("/foo/bar.ext") -- returns "bar.ext"
path.getname("") -- returns ""
Examines the extension of the path name. Returns true if the extension is listed in %PATHEXT%. This caches the extensions in a map so that it's more efficient than getting and parsing %PATHEXT% each time.
path.isexecext("program.exe") -- returns true
path.isexecext("file.doc") -- returns false
path.isexecext("") -- returns false
If right is a relative path, this joins left and right.
If right is not a relative path, this returns right.
path.join("/foo", "bar") -- returns "/foo\\bar"
path.join("", "bar") -- returns "bar"
path.join("/foo", "") -- returns "/foo\\"
path.join("/foo", "/bar/xyz") -- returns "/bar/xyz"
Cleans path by normalising separators and removing "." and ".." elements. If separator is provided it is used to delimit path elements, otherwise a system-specific delimiter is used.
path.normalise("a////b/\\/c/") -- returns "a\\b\\c\\"
path.normalise("./foo/../bar") -- returns "bar"
path.normalise("") -- returns ""
Splits the last path component from path, if possible. Returns the result and the component that was split, if any.
This is similar to path.getdirectory() but can behave differently when the input path ends with a path separator. This is the recommended API for walking up through parent directories.
local parent,child
parent,child = path.toparent("foo") -- returns "", "foo"
parent,child = path.toparent("\\foo") -- returns "\\", "foo"
parent,child = path.toparent("c:foo") -- returns "c:", "foo"
parent,child = path.toparent("c:\\"]) -- returns "c:\\", ""
parent,child = path.toparent("c:\\foo") -- returns "c:\\", "foo"
parent,child = path.toparent("c:\\foo\\bar") -- returns "c:\\foo", "bar"
parent,child = path.toparent("\\\\foo\\bar") -- returns "\\\\foo\\bar", ""
parent,child = path.toparent("\\\\foo\\bar\\dir") -- returns "\\\\foo\\bar", "dir"
parent,child = path.toparent("") -- returns "", ""
-- These split the path components differently than path.getdirectory().
parent,child = path.toparent("c:\\foo\\bar\\"") -- returns "c:\\foo", "bar"
parent,child = path.toparent("\\\\foo\\bar\\dir\\") -- returns "\\\\foo\\bar", "dir"
.rl. up apis top
Certain Readline configuration variables need for ANSI escape codes to be bracketed with \1
and \2
. This function returns the prompt string with that bracketing applied.
Undoes Readline tilde expansion. See rl.expandtilde() for more information.
rl.collapsetilde("C:\\Users\\yourusername\\Documents")
-- The return value depends on the expand-tilde configuration variable:
-- When "on", the function returns "C:\\Users\\yourusername\\Documents".
-- When "off", the function returns "~\\Documents".
-- Or when force is true, the function returns "~\Documents".
This associates description with macro, to be displayed in the clink-show-help
and clink-what-is
commands.
This may be used to add a description for a luafunc: key binding macro, or for a keyboard macro.
The macro string should include quotes, just like in rl.setbinding(). If quotes are not present, they are added automatically.
rl.describemacro([["luafunc:mycommand"]], "Does whatever mycommand does")
rl.describemacro([["\e[Hrem "]], "Insert 'rem ' at the beginning of the line")
rl.setbinding([["\C-o"]], [["luafunc:mycommand"]])
rl.setbinding([["\C-r"]], [["\e[Hrem "]])
-- Press Alt-H to see the list of key bindings and descriptions.
Performs Readline tilde expansion.
When generating filename matches for a word, use the rl.expandtilde() and rl.collapsetilde() helper functions to perform tilde completion expansion according to Readline's configuration.
An optional whole_line argument selects whether to expand tildes everywhere in the input string (pass true), or to expand only a tilde at the beginning of the input string (pass false or omit the second argument). See the Compatibility Note below for more information.
Use rl.expandtilde() to do tilde expansion before collecting file matches (e.g. via os.globfiles()). If it indicates that it expanded the string, then use rl.collapsetilde() to put back the tilde before returning a match.
local result, expanded = rl.expandtilde("~\\Documents")
-- result is "C:\\Users\\yourusername\\Documents"
-- expanded is true
-- This dir_matches function demonstrates efficient use of rl.expandtilde()
-- and rl.collapsetilde() to generate directory matches from the file system.
function dir_matches(match_word, word_index, line_state)
-- Expand tilde before scanning file system.
local word = line_state:getword(word_index)
local expanded
word, expanded = rl.expandtilde(word)
-- Get the directory from 'word', and collapse tilde before generating
-- matches. Notice that collapsetilde() only needs to be called once!
local root = path.getdirectory(word) or ""
if expanded then
root = rl.collapsetilde(root)
end
local matches = {}
for _, d in ipairs(os.globdirs(word.."*", true)) do
-- Join the filename with the input directory (might have a tilde).
local dir = path.join(root, d.name)
table.insert(matches, { match = dir, type = d.type })
end
return matches
end
Returns the command or macro bound to key, and the type of the binding.
If nothing is bound to the specified key sequence, the returned binding will be nil.
The returned type can be "function"
, "macro"
, or "keymap"
(if key is an incomplete key sequence).
If an error occurs, only nil is returned.
The key sequence string is the same format as from clink echo
. See Discovering Clink key bindings for more information.
An optional keymap may be specified as well. If it is omitted or nil, then the current keymap is searched. Otherwise it may refer to one of the three built in keymaps:
Keymap | Description |
---|---|
"emacs" | The Emacs keymap, which is the default keymap. |
"vi" , "vi-move" , or "vi-command" | The VI command mode keymap. |
"vi-insert" | The VI insertion mode keymap. |
The return value can be passed as input to rl.setbinding() or rl.invokecommand().
local b,t = rl.getbinding([["\e[H"]], "emacs")
if b then
print("Home is bound to "..b.." ("..t..") in emacs mode.")
else
print("Home is not bound in emacs mode.")
end
Returns key bindings and info for command in a table with the following scheme:
local t = rl.getcommandbindings("complete")
-- t.desc [string] Description of the command.
-- t.category [string] Category of the command.
-- t.keys [table] Table of strings listing the key names that are bound to the command.
When raw is true, the key names are the literal key sequences without being converted to user-friendly key names.
If command is neither a command nor a macro string, then nil is returned.
local command = 'complete'
-- or for example '"luafunc:my_macro_function"' or '"some macro text"'
local info = rl.getcommandbindings(command)
if info then
local info = rl.getcommandbindings(command)
print("Info for '"..command.."':")
print("Description is: "..info.desc)
print("Category is: "..info.category)
if #info.keys > 0 then
print("Bound to:")
for _,key in ipairs(info.keys) do
print(" "..key)
end
else
print("Not bound to any keys.")
end
else
print("Command '"..command.."' not recognized.")
end
Returns a table of history items.
The first history item is 1, and the last history item is rl.gethistorycount(). For best performance, use start and end to request only the range of history items that will be needed.
Each history item is a table with the following scheme:
local h = rl.gethistoryitems(1, rl.gethistorycount())
-- h.line [string] The item's command line string.
-- h.time [integer or nil] The item's time, compatible with os.time().
Note: The time field is omitted if the history item does not have an associated time.
Returns the path and file name of the Readline init file that was loaded, if any. Also returns the path and file name of the default Readline init file, if any is present.
See [Init File](#init-file) for more info.
Returns key bindings in a table with the following scheme:
local t = rl.getkeybindings()
-- t[index].key [string] Key name.
-- t[index].binding [string] Command or macro bound to the key.
-- t[index].desc [string] Description of the command.
-- t[index].category [string] Category of the command.
When raw is true, the key names are the literal key sequences without being converted to user-friendly key names.
The optional mode specifies bit flags that control how the returned table is sorted, and whether it includes commands that are not bound to any key.
Mode | Description |
---|---|
0 | Key bindings, sorted by key (this is the default). |
1 | Key bindings, sorted by category and then key. |
4 | All commands, sorted by key. |
5 | All commands, sorted by category and then key. |
The following example demonstrates using this function in a luafunc: key binding to invoke clink.popuplist() to show a searchable list of key bindings, and then invoke whichever key binding is selected.
function luafunc_showkeybindings(rl_buffer)
local bindings = rl.getkeybindings()
if #bindings <= 0 then
rl_buffer:refreshline()
return
end
local items = {}
for _,kb in ipairs(bindings) do
table.insert(items, {
value = kb.binding, -- Return the binding when selected, so it can be invoked.
display = kb.key, -- Display the key name.
description = kb.binding.."\t"..kb.desc -- Also display the command and description.
})
end
-- Show a popup that lists the items from above.
local binding, _, index = clink.popuplist("Key Bindings", items)
rl_buffer:refreshline()
if binding then
-- Invoke the selected binding (a command or macro).
rl.invokecommand(binding)
end
end
Returns two values:
- The name of the last Readline command invoked by a key binding.
- The name of the last Lua function invoked by a key binding.
If the last key binding invoked a Lua function, then the first return value is an empty string unless the Lua function used rl.invokecommand() to also internally invoke a Readline command. If the last key binding did not invoke a Lua function, then the second return value is an empty string.
local last_rl_func, last_lua_func = rl.getlastcommand()
Returns the color string associated with the match.
The arguments are the same as in builder:addmatch().
Returns information about the current prompt and input line.
Note: The promptline and inputline fields may be skewed if any additional terminal output has occurred (for example if any print() calls have happened, or if rl.getpromptinfo()
is used inside a clink.onendedit() event handler, or any other output that the Readline library wouldn't know about).
The returned table has the following scheme:
local info = rl.getpromptinfo()
-- info.promptprefix [string] The prompt string, minus the last line of the prompt string.
-- info.promptprefixlinecount [integer] Number of lines in the promptprefix string.
-- info.prompt [string] The last line of the prompt string.
-- info.rprompt [string or nil] The right side prompt (or nil if none).
-- info.promptline [integer] Console line on which the prompt starts.
-- info.inputline [integer] Console line on which the input text starts.
-- info.inputlinecount [integer] Number of lines in the input text.
Returns the value of the named Readline configuration variable as a string, or nil if the variable name is not recognized.
Returns true when typing insertion mode is on.
When the optional insert argument is passed, this also sets typing insertion mode on or off accordingly.
Invokes a Readline command named command. May only be used within a luafunc: key binding.
count is optional and defaults to 1 if omitted.
Returns true if the named command succeeds, false if the named command fails, or nil if the named command doesn't exist.
Warning: Invoking more than one Readline command in a luafunc: key binding could have unexpected results, depending on which commands are invoked.
Returns whether the current input line exactly matches text. This can be useful in a coroutine that wants to know whether the current input line has already changed, before it starts a potentially slow operation to generate matches. If the optional to_cursor is true, then only the line up to the current cursor position is compared.
local function matches_func(word, index, line_state, builder)
-- Delay match generation briefly, to allow coalescing typed letters into
-- a single query. This can make auto-suggestions more responsive if the
-- match generation operation is slow, such as doing a network query.
local co, ismain = coroutine.running()
if not ismain then
local orig_line = line_state:getline()
orig_line = orig_line:sub(1, line_state:getcursor() - 1)
-- Yield for 0.2 seconds.
clink.setcoroutineinterval(co, 0.2)
coroutine.yield()
-- Reset the interval back to normal.
clink.setcoroutineinterval(co, 0)
-- If the input line changed during the 0.2 seconds, then don't generate
-- matches, and mark the matches as needing to be regenerated.
if not rl.islineequal(orig_line, true) then
builder:setvolatile()
return {}
end
end
-- Do something slow that generates matches.
local matches = {}
local f = io.popen("slow_operation.exe")
if f then
for l in f:lines() do
table.insert(matches, l)
end
end
return matches
end
Returns true when the current input line is a history entry that has been modified (i.e. has an undo list).
This enables prompt filters to show a "modmark" of their own, as an alternative to the modmark shown when the mark-modified-lines
Readline config setting is enabled.
The following sample illustrates a prompt filter that shows a "modified line" indicator when the current line is a history entry and has been modified.
local p = clink.promptfilter(10)
local normal = "\x1b[m"
local function get_settings_color(name)
return "\x1b[" .. settings.get(name) .. "m"
end
function p:filter(prompt)
prompt = os.getcwd()
if rl.ismodifiedline() then
-- If the current line is a history entry and has been modified,
-- then show an indicator.
prompt = get_settings_color("color.modmark") .. "*" .. normal .. " " .. prompt
end
prompt = prompt .. "\n$ "
return prompt
end
local last_modmark = false
local function modmark_reset()
-- Reset the remembered state at the beginning of each edit line.
last_modmark = rl.ismodifiedline()
-- Turn off `mark-modified-lines` to avoid two modmarks showing up.
rl.setvariable("mark-modified-lines", "off")
end
local function modmark_refilter()
-- If the modmark state has changed, refresh the prompt.
if last_modmark ~= rl.ismodifiedline() then
last_modmark = rl.ismodifiedline()
clink.refilterprompt()
end
end
clink.onbeginedit(modmark_reset)
clink.onaftercommand(modmark_refilter)
Returns a boolean value indicating whether the named Readline configuration variable is set to true (on), or nil if the variable name is not recognized.
Returns whether the text needs quotes to be parsed correctly in a command line.
Binds key to invoke binding, and returns whether it was successful.
The key sequence string is the same format as from clink echo
. See Discovering Clink key bindings for more information.
The binding is either the name of a Readline command, a quoted macro string (just like in the .inputrc config file), or nil to clear the key binding.
An optional keymap may be specified as well. If it is omitted or nil, then the current keymap is searched. Otherwise it may refer to one of the three built in keymaps:
Keymap | Description |
---|---|
"emacs" | The Emacs keymap, which is the default keymap. |
"vi" , "vi-move" , or "vi-command" | The VI command mode keymap. |
"vi-insert" | The VI insertion mode keymap. |
Using Lua's [[
..]]
string syntax conveniently lets you simply copy the key string exactly from the clink echo
output, without needing to translate the quotes or backslashes.
Note: This does not write the value into a config file. Instead it updates the key binding in memory, temporarily overriding whatever is present in any config files. When config files are reloaded, they may replace the key binding again.
local old_space = rl.getbinding('" "')
function hijack_space(rl_buffer)
rl.invokecommand("clink-expand-line") -- Expand envvars, etc in the line.
rl.invokecommand(old_space) -- Then invoke whatever was previously bound to Space.
end
rl.setbinding([[" "]], [["luafunc:hijack_space"]])
-- The [[]] string syntax lets you copy key strings directly from 'clink echo'.
-- [["\e[H"]] is much easier than translating to "\"\\e[H\"", for example.
rl.setbinding([["\e[H"]], [[beginning-of-line]])
Provides an alternative set of matches for the current word. This discards any matches that may have already been collected and uses matches for subsequent Readline completion commands until any action that normally resets the matches (such as moving the cursor or editing the input line).
The syntax is the same as for builder:addmatches() with one addition: You can add a "nosort"
key to the matches table to disable sorting the matches.
local matches = {}
matches["nosort"] = true
rl.setmatches(matches)
This function may (only) be used by a luafunc: key binding to provide matches based on some special criteria. For example, a key binding could collect numbers from the current screen buffer (such as issue numbers, commit hashes, line numbers, etc) and provide them to Readline as matches, making it convenient to grab a number from the screen and insert it as a command line argument.
Match display filtering is also possible by using clink.ondisplaymatches() after setting the matches.
Example .inputrc key binding:
M-n: "luafunc:completenumbers" # Alt+N
Example Lua function:
function completenumbers()
local _,last_luafunc = rl.getlastcommand()
if last_luafunc ~= "completenumbers" then
-- Collect numbers from the screen (minimum of three digits).
-- The numbers can be any base up to hexadecimal (decimal, octal, etc).
local matches = console.screengrab("[^%w]*(%w%w[%w]+)", "^%x+$")
-- They're already sorted by distance from the input line.
matches["nosort"] = true
rl.setmatches(matches)
end
rl.invokecommand("old-menu-complete")
end
Temporarily overrides the named Readline configuration variable to the specified value. The return value reports whether it was successful, or is nil if the variable name is not recognized.
Note: This does not write the value into a config file. Instead it updates the variable in memory, temporarily overriding whatever is present in any config files. When config files are reloaded, they may replace the value again.
Translates input to another format, according to the value of form: format.
1
converts from an input key sequence (as returned by console.readinput) to a friendly key name.2
converts from an input key sequence (as returned by console.readinput) to a bindable key sequence string suitable for use with rl.setkeybinding.3
converts from a key binding sequence (as understood by Readline key bindings) to a friendly key name.4
converts from a key binding sequence (as understood by Readline key bindings) to an input key sequence.
If the input key sequence string cannot be translated then nil is returned.
.rl_buffer: up apis top
beginoutput | getargument | insert | setcommentrow |
beginundogroup | getbuffer | insertsuggestion | setcursor |
ding | getcursor | refreshline | |
endundogroup | getlength | remove | |
getanchor | hassuggestion | setargument |
Advances the output cursor to the next line after the Readline input buffer so that subsequent output doesn't overwrite the input buffer display.
Starts a new undo group. This is useful for grouping together multiple editing actions into a single undo operation.
Dings the bell. If the bell-style
Readline variable is visible
then it flashes the cursor instead.
Ends an undo group. This is useful for grouping together multiple editing actions into a single undo operation.
Note: All undo groups are automatically ended when a key binding finishes execution, so this function is only needed if a key binding needs to create more than one undo group.
Returns the anchor position of the currently selected text in the input line, or nil if there is no selection. The value can be from 1 to rl_buffer:getlength() + 1. It can exceed the length of the input line because the anchor can be positioned just past the end of the input line.
Returns any accumulated numeric argument (Alt+Digits, etc), or nil if no numeric argument has been entered.
Returns the cursor position in the input line. The value can be from 1 to rl_buffer:getlength() + 1. It can exceed the length of the input line because the cursor can be positioned just past the end of the input line.
Note: In v1.1.20 through v1.2.31 this accidentally returned 1 less than the actual cursor position. In v1.2.32 and higher it returns the correct cursor position.
Returns true
if a suggestion is available (see Auto-Suggest). Otherwise returns false
.
Inserts text at the cursor position in the input line.
If no suggestion is available (see Auto-Suggest), this does nothing and returns false
.
If a suggestion is available, then this inserts the suggestion and returns true
.
The optional amount argument can change how much of the suggestion is inserted:
amount | Description |
---|---|
"all" | All of the suggestion is inserted (this is the default if amount is omitted). |
"word" | The next word in the suggestion is inserted, according to normal word breaks. |
"fullword" | The next full word in the suggestion is inserted, using spaces as word breaks. |
Removes text from the input line starting at cursor position from up to but not including to.
If from is greater than to then the positions are swapped before removing text.
Note: The input line is UTF8, and removing only part of a multi-byte Unicode character may have undesirable results.
When argument is a number, it is set as the numeric argument for use by Readline commands (as entered using Alt+Digits, etc). When argument is nil, the numeric argument is cleared (having no numeric argument is different from having 0 as the numeric argument).
Sets the cursor position in the input line and returns the previous cursor position. cursor can be from 1 to rl_buffer:getlength() + 1. It can exceed the length of the input line because the cursor can be positioned just past the end of the input line.
Note: The input line is UTF8, and setting the cursor position inside a multi-byte Unicode character may have undesirable results.
Note: In v1.1.20 through v1.6.0 this accidentally didn't return the previous cursor position. In v1.6.1 and higher it returns the the correct previous cursor position.
.settings. up apis top
add | get |
clear | parsecolor |
formatcolor | set |
Adds a setting to the list of Clink settings and includes it in clink set
. The new setting is named name and has a default value default when the setting isn't explicitly set.
The type of default determines what kind of setting is added:
- Boolean; a boolean value adds a boolean setting.
- Integer; an integer value adds an integer setting.
- Enum; a table adds an enum setting. The table defines the accepted string values, and the first value is the default value. The setting has an integer value which corresponds to the position in the table of accepted values. The first position is 0, the second position is 1, etc.
- String; a string value adds a string setting.
- Color; when name begins with
"color."
then a string value adds a color setting.
name can't be more than 32 characters.
short_desc is an optional quick summary description and can't be more than 48 characters.
long_desc is an optional long description.
settings.add("myscript.myabc", true, "Boolean setting")
settings.add("myscript.mydef", 100, "Number setting")
settings.add("myscript.myghi", "abc", "String setting")
settings.add("myscript.myjkl", {"x","y","z"}, "Enum setting")
settings.add("color.mymno", "bright magenta", "Color setting")
Clears the name Clink setting and reverts to its default value.
Note: This updates the settings file.
Formats an ANSI color code code into a color setting string suitable for use with clink set color.foo
.
Returns the formatted color setting string if successful, or nil if unsuccessful.
If compat is true, then the formatted string uses the most compatible format. This can be useful if the string needs to be usable by older versions of Clink.
See Color Settings for more information.
-- Fully defined color codes:
settings.formatcolor("0;1") -- Returns "bold"
settings.formatcolor("0;4;32") -- Returns "underline green"
settings.formatcolor("0;97;44") -- Returns "bright white on blue"
-- Partial color codes:
settings.formatcolor("1") -- Returns "sgr 1"
settings.formatcolor("4;32") -- Returns "sgr 4;32"
settings.formatcolor("97;44") -- Returns "sgr 97;44"
Returns the current value of the name Clink setting or nil if the setting does not exist.
The return type corresponds to the setting type:
- Boolean settings return a boolean value.
- Integer settings return an integer value.
- Enum settings return an integer value corresponding to a position in the setting's table of accepted values. The first position is 0, the second position is 1, etc.
- String settings return a string.
- Color settings return a string.
Color settings normally return the ANSI color code, suitable for use in an ANSI escape sequence. If the optional descriptive parameter is true then the friendly color name is returned.
print(settings.get("color.doskey")) -- Can print "1;36"
print(settings.get("color.doskey", true)) -- Can print "bold cyan"
Parses a color setting string color into an ANSI color code, suitable for use in an ANSI escape sequence. The string is parsed the same way as clink set color.foo string
would parse it.
Returns the ANSI color code if successful, or nil if unsuccessful.
See Color Settings for more information.
settings.parsecolor("bold") -- Returns "0;1"
settings.parsecolor("underline green") -- Returns "0;4;32"
settings.parsecolor("bri whi on blu") -- Returns "0;97;44"
Sets the name Clink setting to value and returns whether it was successful.
The type of value depends on the type of the setting. Some automatic type conversions are performed when appropriate.
- Boolean settings convert string values
"true"
/"false"
,"yes"
/"no"
, and"on"
/"off"
into a booleantrue
/false
. Any numeric values are converted totrue
, even0
(Lua considers 0 to be true, unlike some other languages). - Integer settings convert string values starting with a digit or minus sign into an integer value.
- Enum settings convert the allowed string values into an integer value corresponding to the position in the table of allowed values. The first position is 0, the second position is 1, etc.
- String settings convert boolean or number values into a corresponding string value.
- Color settings convert boolean or number values into a corresponding string value.
Note: Beginning in Clink v1.2.31 this updates the settings file. Prior to that, it was necessary to separately use clink set
to update the settings file.
.string. up apis top
comparematches |
equalsi |
explode |
hash |
matchlen |
Returns true if a sorts as "less than" b.
The a_type and b_type are optional, and affect the sort order accordingly when present.
This produces the same sort order as normally used for displaying matches. This can be used for manually sorting a subset of matches when a match builder has been told not to sort the list of matches.
local files = {
{ match="xyzFile", type="file" },
{ match="abcFile", type="file" },
}
local other = {
{ match="abc_branch", type="arg" },
{ match="xyz_branch", type="arg" },
{ match="mno_tag", type="alias" },
}
local function comparator(a, b)
return string.comparematches(a.match, a.type, b.match, b.type)
end
-- Sort files.
table.sort(files, comparator)
-- Sort branches and tags together.
table.sort(other, comparator)
match_builder:setnosort() -- Disable automatic sorting.
match_builder:addmatches(files) -- Add the sorted files.
match_builder:addmatches(other) -- Add the branches and tags files.
-- The overall sort order ends up listing all the files in sorted
-- order, followed by branches and tags sorted together.
Performs a case insensitive comparison of the strings with international linguistic awareness. This is more efficient than converting both strings to lowercase and comparing the results.
Splits text delimited by delims (or by spaces if not provided) and returns a table containing the substrings.
The optional quote_pair can provide a beginning quote character and an ending quote character. If only one character is provided it is used as both a beginning and ending quote character.
Returns how many characters match at the beginning of the strings, or -1 if the entire strings match. This respects the match.ignore_case
and match.ignore_accent
Clink settings.
string.matchlen("abx", "a") -- returns 1
string.matchlen("abx", "aby") -- returns 2
string.matchlen("abx", "abx") -- returns -1
.unicode. up apis top
fromcodepage |
isnormalized |
iter |
normalize |
tocodepage |
This converts text from the codepage encoding to UTF8.
When codepage is omitted, the current Active Code Page is used.
If the text cannot be converted, nil is returned.
Note: Clink uses UTF8 internally, and conversion to/from other encodings is intended for use with file input/output or network input/output.
Returns whether text is already normalized according to the Unicode normalization form:
1
is Unicode normalization form C, canonical composition. Transforms each base character + combining characters into the precomposed equivalent. For example, A + umlaut becomes Ä.2
is Unicode normalization form D, canonical decomposition. Transforms each precomposed character into base character + combining characters. For example, Ä becomes A + umlaut.3
is Unicode normalization form KC, compatibility composition. Transforms each base character + combining characters into the precomposed equivalent, and transforms compatibility characters into their equivalents. For example, A + umlaut + ligature for "fi" becomes Ä + f + i.4
is Unicode normalization form KD, compatibility decomposition. Transforms each precomposed character into base character + combining characters, and transforms compatibility characters to their equivalents. For example, Ä + ligature for "fi" becomes A + umlaut + f + i.
If successful, true or false is returned.
If unsuccessful, false and an error code are returned.
This returns an iterator function which steps through text one Unicode codepoint at a time. Each call to the iterator function returns the string for the next codepoint, the numeric value of the codepoint, and a boolean indicating whether the codepoint is a combining mark.
-- UTF8 sample string:
-- Index by codepoint: 1 2 3 4 5
-- Unicode character: à é ᴆ õ û
local text = "\xc3\xa0\xc3\xa9\xe1\xb4\x86\xc3\xb5\xc3\xbb"
-- Index by byte: 1 2 3 4 5 6 7 8 9 10 11
for str, value, combining in unicode.iter(text) do
local bytes = ""
for i = 1, #str do
bytes = bytes .. string.format("\\x%02x", str:byte(i, i))
end
clink.print(str, value, combining, bytes)
end
-- The above prints the following:
-- à 224 false \xc3\xa0
-- é 233 false \xc3\xa9
-- ᴆ 7430 false \xe1\xb4\x86
-- õ 245 false \xc3\xb5
-- û 373 false \xc3\xbb
Transforms the text according to the Unicode normalization form:
1
is Unicode normalization form C, canonical composition. Transforms each base character + combining characters into the precomposed equivalent. For example, A + umlaut becomes Ä.2
is Unicode normalization form D, canonical decomposition. Transforms each precomposed character into base character + combining characters. For example, Ä becomes A + umlaut.3
is Unicode normalization form KC, compatibility composition. Transforms each base character + combining characters into the precomposed equivalent, and transforms compatibility characters into their equivalents. For example, A + umlaut + ligature for "fi" becomes Ä + f + i.4
is Unicode normalization form KD, compatibility decomposition. Transforms each precomposed character into base character + combining characters, and transforms compatibility characters to their equivalents. For example, Ä + ligature for "fi" becomes A + umlaut + f + i.
If successful, the resulting string is returned.
If unsuccessful, both the original string and an error code are returned.
This converts text from UTF8 to the codepage encoding.
When codepage is omitted, the current Active Code Page is used.
If the text cannot be converted, nil is returned.
Note: Clink uses UTF8 internally, and conversion to/from other encodings is intended for use with file input/output or network input/output.
.word_classifications: up apis top
applycolor |
classifyword |
Applies an ANSI SGR escape code to some characters in the input line.
start is where to begin applying the SGR code.
length is the number of characters to affect.
color is the SGR parameters sequence to apply (for example "7"
is the code for reverse video, which swaps the foreground and background colors).
By default the color is applied to the characters even if some of them are already colored. But if overwrite is false
each character is only colored if it hasn't been yet.
See Coloring the Input Text for more information.
Note: An input line can have up to 100 different unique color strings applied, and then this stops applying new colors. The counter gets reset when the onbeginedit event is sent.
This classifies the indicated word so that it can be colored appropriately.
The word_class is one of the following codes:
Code | Classification | Clink Color Setting |
---|---|---|
"a" | Argument; used for words that match a list of preset argument matches. | color.arg or color.input |
"c" | Shell command; used for CMD command names. | color.cmd |
"d" | Doskey alias. | color.doskey |
"f" | Flag; used for flags that match a list of preset flag matches. | color.flag |
"x" | Executable; used for the first word when it is not a command or doskey alias, but is an executable name that exists. | color.executable |
"u" | Unrecognized; used for the first word when it is not a command, doskey alias, or recognized executable name. | color.unrecognized |
"o" | Other; used for file names and words that don't fit any of the other classifications. | color.input |
"n" | None; used for words that aren't recognized as part of the expected input syntax. | color.unexpected |
"m" | Prefix that can be combined with another code (for the first word) to indicate the command has an argmatcher (e.g. "mc" or "md" ). | color.argmatcher or the other code's color |
By default the classification is applied to the word even if the word has already been classified. But if overwrite is false
the word is only classified if it hasn't been yet.
See Coloring the Input Text for more information.
.[other] up apis top
CLINK_EXE |
pause |
Breaks into the Lua debugger, if the lua.debug
setting is enabled.
If pause()
is used by itself, the debugger breaks on the line after the pause call.
The message argument can be a message the debugger will display, for example to differentiate between multiple pause calls.
The lines argument indicates how many lines to step further before breaking into the debugger. The default is nil, which breaks on the line immediately following the pause call. Passing an integer value will step some number of lines before breaking (this will produce confusing results and is discouraged).
When the force argument is true
then it will break into the debugger even if the poff
debugger command has been used to turn off the pause command.
.Deprecated. up apis top
Deprecated; don't use this. See _argmatcher:addarg for more information.
Adds one argument slot per table passed to it (as v0.4.9 did).
Note: v1.3.10 and lower :add_arguments()
mistakenly added all arguments into the first argument slot.
Deprecated; don't use this. See _argmatcher:addflags for more information.
Deprecated; don't use this. See _argmatcher:nofiles for more information.
Deprecated; don't use this. See _argmatcher:addarg for more information.
Sets one argument slot per table passed to it (as v0.4.9 did).
Note: v1.3.10 and lower :add_arguments()
mistakenly set all arguments into the first argument slot.
Deprecated; don't use this. See _argmatcher:addflags for more information.
Note: The new API has no way to remove flags that were previously added, so converting from :set_flags()
to :addflags()
may require the calling script to reorganize how and when it adds flags.
Deprecated; don't use this. See builder:addmatch for more information.
This is a shim that lets clink.register_match_generator continue to work for now, despite being obsolete.
Deprecated; don't use this. See clink.setcoroutineinterval for more information.
Prior to v1.3.1 this was undocumented, and coroutines had to be manually added in order to be scheduled for resume while waiting for input. Starting in v1.3.1 this is no longer necessary, but it can still be used to override the interval at which to resume the coroutine.
Deprecated; don't use this. See clink.argmatcher for more information.
Creates a new parser and adds ... to it.
-- Deprecated form:
local parser = clink.arg.new_parser(
{ "abc", "def" }, -- arg position 1
{ "ghi", "jkl" }, -- arg position 2
"--flag1", "--flag2" -- flags
)
-- Replace with form:
local parser = clink.argmatcher()
:addarg("abc", "def") -- arg position 1
:addarg("ghi", "jkl") -- arg position 2
:addflags("--flag1", "--flag2") -- flags
Deprecated; don't use this. See clink.argmatcher for more information.
Adds parser to the argmatcher for cmd.
If there is already an argmatcher for cmd then the two argmatchers are merged. It is only a simple merge; a more sophisticated merge would be much slower and use much more memory. The simple merge should be sufficient for common simple cases.
Note: In v1.3.11, merging parsers should be a bit improved compared to how v0.4.9 merging worked. In v1.0 through v1.3.10, merging parsers doesn't work very well.
-- Deprecated form:
local parser1 = clink.arg.new_parser():set_arguments({ "abc", "def" }, { "old_second" })
local parser2 = clink.arg.new_parser():set_arguments({ "ghi", "jkl" }, { "new_second" })
clink.arg.register_parser("foo", parser1)
clink.arg.register_parser("foo", parser2)
-- In v0.4.9 that syntax only merged the first argument position, and "ghi" and
-- "jkl" ended up with no further arguments. In v1.3.11 and higher that syntax
-- ends up with "ghi" and "jkl" having only "old_second" as a second argument.
-- Replace with new form:
clink.argmatcher("foo"):addarg(parser1)
clink.argmatcher("foo"):addarg(parser2)
-- In v1.3.11 and higher this syntax ends up with all 4 first argument strings
-- having both "old_second" and "new_second" as a second argument.
Deprecated; don't use this. See os.chdir for more information.
Deprecated; don't use this.
This is no longer supported, and always returns an empty string.
Returning an empty string works because in Clink v1.x and higher match generators are no longer responsible for filtering matches. The match pipeline itself handles that internally now.
Deprecated; don't use this. See os.globdirs for more information.
The case_map argument is ignored, because match generators are no longer responsible for filtering matches. The match pipeline itself handles that internally now.
Deprecated; don't use this. See os.globfiles for more information.
The case_map argument is ignored, because match generators are no longer responsible for filtering matches. The match pipeline itself handles that internally now.
Deprecated; don't use this. See os.getaliases for more information.
Deprecated; don't use this. See os.getcwd for more information.
Deprecated; don't use this. See os.getenvnames for more information.
Deprecated; don't use this.
Always returns "clink"; this corresponds to the "clink" word in the $if clink
directives in Readline's .inputrc file.
Deprecated; don't use this.
This is no longer supported, and always returns an empty string. If a script needs to access matches it added, the script should keep track of the matches itself.
Deprecated; don't use this. See rl.getvariable for more information.
Deprecated; don't use this. See os.getscreeninfo for more information.
Note: The field names are different between os.getscreeninfo()
and the v0.4.9 implementation of clink.get_screen_info
.
Deprecated; don't use this. See settings.get for more information.
Deprecated; don't use this. See settings.get for more information.
Deprecated; don't use this. See clink.generator for more information.
This returns true if needle is a prefix of candidate with a case insensitive comparison.
Normally in Clink v1.x and higher the needle will be an empty string because match generators are no longer responsible for filtering matches. The match pipeline itself handles that internally now.
Deprecated; don't use this. See rl.isvariabletrue for more information.
Deprecated; don't use this.
This is no longer supported, and always returns false.
Deprecated; don't use this.
This is no longer supported, and always returns 0. If a script needs to know how many matches it added, the script should keep track of the count itself.
Deprecated; don't use this. See clink.ondisplaymatches for more information.
A match generator can set this varible to a filter function that is called before displaying matches. It is reset every time match generation is invoked. The filter function receives table argument containing the matches that are going to be displayed, and it returns a table filtered as required by the match generator.
See Filtering the Match Display for more information.
Deprecated; don't use this. See clink.filematches for more information.
Globs files using pattern and adds results as matches. If full_path is true then the path from pattern is prefixed to the results (otherwise only the file names are included). The last argument find_func is the function to use to do the globbing. If it's unspecified (or nil) Clink falls back to clink.find_files.
Note: This exists for backward compatibility but malfunctions with some inputs, in the same ways it did in v0.4.9.
Deprecated; don't use this. See builder:addmatches for more information.
This adds words that match the text.
Deprecated; don't use this. See builder:addmatch for more information.
This is only needed when using deprecated APIs. It's automatically inferred from the match types when using the current APIs.
Deprecated; don't use this. See clink.promptfilter for more information.
Registers a prompt filter function. The capabilities are the same as before but the syntax is changed.
-- Deprecated form:
function foo_prompt()
clink.prompt.value = "FOO "..clink.prompt.value.." >>"
--return true -- Returning true stops further filtering.
end
clink.prompt.register_filter(foo_prompt, 10)
-- Replace with new form:
local foo_prompt = clink.promptfilter(10)
function foo_prompt:filter(prompt)
return "FOO "..prompt.." >>" --,false -- Adding ,false stops further filtering.
end
Deprecated; don't use this. See string.explode for more information.
This function takes the string str which is quoted by ql (the opening quote character) and qr (the closing character) and splits it into parts as per the quotes. A table of these parts is returned.
Deprecated; don't use this. See clink.generator for more information.
Registers a generator function for producing matches. This behaves similarly to v0.4.8, but not identically. The Clink schema has changed significantly enough that there is no direct 1:1 translation; generators are called at a different time than before and have access to more information than before.
-- Deprecated form:
local function match_generator_func(text, first, last)
-- `text` is the word text.
-- `first` is the index of the beginning of the end word.
-- `last` is the index of the end of the end word.
-- `clink.add_match()` is used to add matches.
-- return true if handled, or false to let another generator try.
end
clink.register_match_generator(match_generator_func, 10)
-- Replace with new form:
local g = clink.generator(10)
function g:generate(line_state, match_builder)
-- `line_state` is a line_state object.
-- `match_builder:addmatch()` is used to add matches.
-- return true if handled, or false to let another generator try.
end
Deprecated; don't use this.
This is no longer supported, and does nothing.
Deprecated; don't use this. See clink.translateslashes for more information.
Controls how Clink will translate the path separating slashes for the current path being completed. Values for type are;
- -1 - no translation
- 0 - to backslashes
- 1 - to forward slashes
Deprecated; don't use this. See string.explode for more information.
Splits the string str into pieces separated by sep, returning a table of the pieces.
Deprecated; don't use this. See builder:setsuppressappend for more information.
Deprecated; don't use this. See builder:setsuppressquoting for more information.
Deprecated; don't use this. See os.globfiles for more information.
Returns whether path has the hidden attribute set.
Deprecated; don't use this. See line_state for more information.
This is an obsolete global variable that was set while running match generators. It has been superseded by the line_state type parameter passed into match generator functions when using the new clink.generator() API.
.Changes top
.Releases from chrisant996/clink fork up top
.v1.7.5 up top
- Added new Lua API console.ellipsify() to truncate an input string in various ways.
- Added new rl_buffer:setcommentrow() to let
"luafunc:"
commands immediately show text in the comment row. - Adjusted some character width measurements based on analysis from wcwidth-verifier on Win8.1, Win10 with conhost, Win10 with Windows Terminal 1.22, Win11 with conhost, and Win11 with Windows Terminal 1.22.
- The Headline, Pure, and Bureau clinkprompt files now consider unpublished branches as being "ahead", even in cases where git doesn't report a specific "ahead by" count.
- Internal changes to the right side prompt implementation, to disentangle unnecessary internal dependencies.
.v1.7.4 up top
- Changed searching for color themes and custom prompts to always include
themes\
directories under the Clink program directory and Clink profile directory, even when theclink.path
setting has been used to remove them from the list of script directories. - Improved emoji width measurements.
- Unqualified emojis are counted as a single cell now. Windows Terminal intentionally renders these as a single cell for compatibility with the behavior of the first terminal programs on Linux that began to support emoji characters (an important compatibility detail for the Windows Subsystem for Linux, for example).
- Country flag emoji character pairs are recognized.
- Skin tone variant selectors are recognized.
- The zero width joiner is recognized when it joins two emoji characters, or an emoji and a male or female symbol.
- NOTE: A given OS version and terminal program version will only recognize certain combinations of joined emojis as valid sequences. And Windows Terminal is one of the only terminal programs on Windows that can draw color emoji characters. Clink has no way to know how a given terminal will actually render sequences of Unicode emoji characters. If a terminal program renders a particular emoji sequence differently than Clink predicts, then the display may become garbled. If that happens, don't use that emoji sequence. But if a terminal program renders an emoji sequence as a single glyph and Clink predicts the width incorrectly, then please open an issue with details about the emoji.
- The pure.clinkprompt now also supports virtualenv's
VIRTUAL_ENV_DISABLE_PROMPT
andVIRTUAL_ENV_PROMPT
environment variables. - Added console.cellcountiter() so scripts can iterate over Unicode character sequences in a string. Using
unicode.iter()
returns one codepoint at a time, but emojis can have multiple codepoints andconsole.cellcountiter()
groups them together for easy processing and accurate overall width measures (measuring the width of each codepoint in an emoji sequence is not the same as measuring the width of the emoji sequence as a whole). - Fixed the right side transient prompt so it shows up even when identical to the right side normal prompt.
- Fixed the
demo
callback in .clinkprompt files. - Fixed potential for incomplete input of Unicode surrogate pairs. An easy way to encounter the problem was using the Windows emoji picker to input an emoji that's a sequence of other emojis joined together -- for example, the pride flag emoji is a flag emoji joined with a rainbow emoji, and the rainbow emoji uses a surrogate pair.
- Fixed an edge case where if a .clinkprompt file calls
require()
to load a module, and later on a different script also callsrequire()
for the same module, then any event handlers or prompt filters registered by the required module accidentally only worked inside the .clinkprompt that originally required it. Now required modules behave the same regardless whether they are first required by a .clinkprompt file or by some other script file. - Fixed #685; CTRL-L while input text is present redraws the input line wrong.
- Fixed #686;
clink config -h
shows inaccurate info. - Fixed #696; console width length off-by-one on certain characters (in particular U+26A1).
- Fixed #698; script error when using
clink config prompt show pure
. - Fixed #701; issues in Antares prompt (missing tag and error when truncation is needed).
.v1.7.3 up top
- Added the missing Tomorrow* color themes.
- Fixed #682; the
clink config theme use
andclink config prompt use
commands had no effect if there is noclink_settings
file yet.
.v1.7.2 up top
- Fixed an error when the updater tried to install the new
themes\
subdirectory and files.
.v1.7.0 up top
Clink now supports color theme files and custom prompt files. These enable packaging Clink color settings or Clink custom prompts into shareable files. This finally makes it easy to download and apply themes or prompts shared by other people, or copy them and modify them. The new clink-themes repo is a site where .clinktheme and .clinkprompt files can be shared (see Contributing for details on how to contribute your own themes and prompts).
- Added support for
*.clinktheme
color theme files; see Color Themes for more information.- Added several
clink config theme
commands for color themes (runclink config theme --help
). - The famous Dracula, Solarized (light and dark), and Tomorrow (1 light, 4 dark) themes are included.
- Use
clink config theme use name
to apply a color theme, or set theCLINK_COLORTHEME
environment variable to the color theme name.
- Added several
- Added support for
*.clinkprompt
custom prompt files; see Custom Prompts for more information. This makes it easy to share custom prompts, and to have a library of many different custom prompts and switch between them quickly and easily. One .clinkprompt can be active at a time; activating one deactivates any others.- Added several
clink config prompt
commands for custom prompts (runclink config prompt --help
). - Oh-My-Posh support is included.
- Also included are ports of Agnoster, Pure, Headline, Antares, and a few others (all ported from zsh to Clink).
- Use
clink config prompt use name
to activate a custom prompt module, or set theCLINK_CUSTOMPROMPT
environment variable to the custom prompt name.
- Added several
- Added the ability to show input hints in the comment row (below the input line).
- Input hints are off by default, and can be enabled with
clink set comment_row.show_hints true
. - Argmatchers can provide input hints; see Show a Usage Hint for more information.
- Lua scripts can create custom hinters; see Showing Input Hints for more information.
- Input hints are off by default, and can be enabled with
- Enhanced the syntax for setting colors; added
italic
andreverse
, and added#XXXXXX
and#XXX
shortcuts for specifying 24-bit color values. - Added more popup list colors:
color.popup_border
,color.popup_header
,color.popup_footer
,color.popup_select
, andcolor.popup_selectdesc
. - Changed phrasing from "Accept Suggestion" to "Insert Suggestion" in the documentation and in the auto-suggestions usage hint text.
- Changed the Lua
print()
function to support UTF8 output and terminal escape codes. Now the only reasons for a script to useclink.print()
instead ofprint()
are (1) background compatibility or (2) usingNONL
to suppress printing a line ending. - Improved terminal output logging when the
debug.log_terminal
setting is enabled (the setting is only for diagnostic use).- Now it captures all WriteConsoleW and WriteFile output sent to stdout or stderr (instead of only capturing output from the Readline library).
- Added a
debug.log_output_callstacks
setting which includes callstacks for each output reported by thedebug.log_terminal
setting.
- Added a workaround for Unicode limitations in legacy console windows and legacy terminals (improves cursor position accuracy when Unicode surrogate pairs are present).
- Added several new Lua APIs for color themes and custom prompts: clink.getprompts(), clink.applyprompt(), clink.getclinkprompt(), clink.getthemes(), clink.readtheme(), clink.applytheme(), settings.clear(), settings.parsecolor(), settings.formatcolor(), os.createguid().
- Added git Lua APIs for use by custom prompts.
- Added optional
cookie
argument to clink.promptcoroutine() to make it simple for *.clinkprompt files to allow customization that makes use of asynchronous prompt filtering without needing modifications to the main *.clinkprompt file. - Fixed detecting file associations (some file extensions weren't detected as having file associations, causing executable completion to omit them, and causing input line coloring to be inaccurate).
- Fixed a case where updating the right side prompt could leave stray characters behind.
- Fixed a case where the
match.coloring_rules
setting could have no effect. - Fixed delay when typing
X:
and it's a remote drive. - Fixed coloring
2>&1
; the1
wasn't colored. - Fixed color of leading blank lines in a prompt string (use the terminal's default color, not the
color.prompt
color). - Fixed
rl.collapsetilde()
which just didn't do its job. - Fixed
%clink_dummy_capture_env%
to stop accidentally leaking into the environment variables collection. - Fixed an infinite loop when
prompt.async
was false. - Fixed F9 to stop jumping one past the actual entered history number.
- Fixed various edge case bugs in the input line display, which were uncovered while adding the ability to show input hints.
.v1.6.21 up top
- Reduced the performance overhead of hooked APIs from about 20 microseconds to about 2 microseconds.
- Enhanced the executable recognition to avoid flickering red (or
color.unrecognized
) for an executable name that was already recognized in a recent previous input line. - Enhanced the
srcmap
command in the Lua debugger so thatsrcmap dir
automatically sets up source mappings for Clink's built in scripts usingdir
as the repo root. - Fixed when
history.expand_mode
isoff
; it didn't fully turn off all of the history expansion syntax forms (for example the^
syntax). - Fixed input line coloring when the first word is a device name (e.g.
nul
orcom1:
); it should usecolor.unrecognized
for the color. - Fixed #651; completion doesn't work for
./
and../
anymore in the first word of a command line. Now when thematch.translate_slashes
setting issystem
orbackslash
then completing./
and../
can complete the word as a path, even though CMD does not consider it to be a path. - Fixed #653;
clink_start.cmd
gets run twice if the binaries directory is the same as the profile directory. - Fixed #654; input line coloring doesn't treat
^
correctly inside quotes (and related quirks).
.v1.6.20 up top
- Fixed #652; error when trying to update again after updating to v1.6.20 (regression introduced in v1.6.19).
.v1.6.19 up top
- Fixed truncated descriptions with
clink set exec.
and thenclink-select-complete
(Ctrl-Space) (regression introduced in v1.6.11). - Fixed fully qualified paths from a different local drive accidentally being colored with
color.unrecognized
. - Fixed #648; on Windows 8.1 the title bar can get changed to "Windows PowerShell" for the rest of the CMD session.
.v1.6.18 up top
- Added a new callback function that can be assigned to an argument position in the table given to
:addarg()
viaonalias=
(see Responding to Arguments in Argmatchers for more information). The git argmatcher in the clink-completions repo uses this to support git aliases. - When a doskey alias doesn't include any
$
tokens then CMD is guaranteed to ignore the rest of the command line after the alias, so now argmatcher parsing also ignores the rest of the command line and colors it usingcolor.unexpected
. - Suppress the ANSICON warning in the log file and diagnostics output on Windows 8.1. The performance problem in ANSICON exists, but apparently there isn't a better alternative before Windows 10.
.v1.6.17 up top
- Added warning in the log file and in
clink-diagnostics
(Ctrl-X,Ctrl-Z) when ANSICON is detected on Windows 8.1 or greater (it's unnecessary, less functional, and greatly degrades performance). - Added language info in
clink-diagnostics
when the code page is not 1252 (for easier troubleshooting). - Fixed finding argmatchers registered with exact names (typing
foo
couldn't find an argmatcher registered asc:\dir\foo.exe
because it accidentally looked forc:\dir\foo.EXE
). - Fixed #631; script error after
cmd
when the current language is German.
.v1.6.16 up top
- Added a workaround for how scoop tries to control app versions and updates (#615; scoop causes
clink autorun install
to use a wrong path). - Added an
auto
mode for thematch.translate_slashes
setting. This mode makes completion translate all slashes in the completed word to match whichever kind occurs first in the word, or to the system path separator if there are no slashes yet (e.g. when completing a directory name). - Changed the default to
auto
for thematch.translate_slashes
setting. - Updated the
clink.slash_translation()
function. - UNC share name completion works with forward slashes now (e.g.
//localhost/
). - Added a
clink-toggle-slashes
bindable command, bound by default to Ctrl-/. The command toggles between forward and backslashes in the word at the cursor point, or in the Nth word if a numeric argument is provided (e.g. by the Alt-Digit keys). - Fixed the
off
mode for thematches.translate_slashes
setting (regression introduced in v1.1.23). - Fixed input line coloring of
@
infor %a in (*) do @whatever
. - Fixed crash in
glob-list-expansions
when used on an empty word (regression introduced in v1.3.36). - Fixed wildcard completions when
match.wild
is on andmatch.substring
is off. - Fixed obscure edge case where match filtering with wildcards could potentially yield inaccurate results immediately after an auto-suggestion was offered.
.v1.6.15 up top
- Fixed hiding internal script names in the
clink-diagnostics
output (regression introduced in v1.6.11). - Fixed #613; wrong input line coloring for
cmd /c "command line"
.
.v1.6.14 up top
- Fixed
menu-complete
to respectcompletion-auto-query-items
. - Fixed missing line break before
dump-macros
,dump-variables
,clink-dump-functions
, andclink-dump-macros
(regression introduced in v1.6.3). - Fixed
rl.getbinding()
to returnclink-select-complete
instead ofclink-popup-complete
(the latter is just an alias; the real command name isclink-select-complete
).
.v1.6.13 up top
- Popup lists can now be filtered.
- Press F4 in a popup list to toggle the search mode between "find" and "filter".
- The
clink.popup_search_mode
setting controls the default search mode. - The
clink.popuplist()
function can be told to start in a specific search mode.
- Added
os.findfiles()
to allow getting files/directories one at a time (versusos.globfiles()
which collects the entire set all at once into a table). - Added
exec.associations
setting to let Executable Completion include files with registered file associations as matches (e.g. launchable documents such as "*.pdf" files). - Fixed Ctrl-C in a popup list copying the wrong entry after having used Del to delete an entry.
- Fixed input line coloring to use
color.executable
also for files included by theexec.path
setting, if the files have registered file associations.
.v1.6.12 up top
- Fixed #597; prompt shows leftover text sometimes (regression introduced in v1.6.10).
- Fixed #596; it's easy to forget whether Enter in history list executes or inserts.
.v1.6.11 up top
- Added
os.setalias()
for setting a doskey alias without needing to invoke the doskey.exe program. - Fixed a case where match descriptions could be displayed with incorrect padding and truncation.
- Lua debugging enhancements:
- Changed the built-in embedded scripts to include debug info, which allows some Lua error messages to be more useful for troubleshooting.
- Added
srcmap
command in the Lua debugger to override where to find source files.
.v1.6.10 up top
- Added an optimization to further reduce flicker when re-drawing the prompt.
- Added a
user_data.shared_user_data
table to allow linked argmatchers to share data with each other while an input line is being parsed (see Responding to Arguments in Argmatchers for details). - Fixed #579; popup lists could accidentally truncate text in the first column when there's only one column.
- Fixed #576; setup exe doesn't remove old uninstall exe files.
- Fixed #575; error when
color.executable
is set andcolor.unrecognized
is not (regression introduced in v1.6.2).
.v1.6.9 up top
- Fixed #574;
prompt.spacing
"eats" lines containing Unicode Surrogate Pairs such as for some nerdfont icons (Windows Terminal accidentally returns that such lines are empty). - Fixed #573; C# was unable to read Clink's version resource.
- Fixed #555; security advisory CVE-2020-24370 for a Lua bug.
.v1.6.8 up top
- Fixed #571; error in clink.bat under some circumstances (regression introduced in v1.6.7).
.v1.6.7 up top
- Recognize the little-known
cmd /r
as a synonym forcmd /c
so that Clink can optimize and skip injecting into acmd /r
process. - Fixed displaying descriptions when they're left-justified (regression introduced in v1.6.6).
- Fixed
argmatcher:chaincommand("run")
to not find argmatchers for builtin CMD command names (since CMD doesn't get invoked in that case, so it won't get interpreted as a CMD command). - Fixed
argmatcher:chaincommand()
to find an argmatcher for a builtin CMD command even if a directory exists with the same name (since CMD interprets that case as a CMD command). - Fixed
argmatcher:chaincommand("cmd")
so whenexec.aliases
is enabled it can include aliases as completions. - Fixed
argmatcher:addarg({loopchars="+", etcetc})
so that-Q:+x
still gets parsed into two input words-Q:
and+x
. - Fixed to parse
foo^ bar
as two words "foo" and "bar". - Fixed to recognize
^echo
(etc) as a builtin CMD command name despite embedded^
characters. - Fixed #570; fixed #569 more thoroughly, and
cd /d
cannot be used anywhere because it also requires command extensions.
.v1.6.6 up top
- Added
clink history --no-show-time
to allow omitting history timestamps even when thehistory.time_stamp
setting isshow
. - Fixed match display to not right justify descriptions when the screen isn't wide enough or when descriptions contain aligned columns (like
clink set
completions do since v1.6.3). - Fixed
clink history
when output is redirected; strip any escape codes that might be embedded in the time format. - Fixed #569;
cmd /e:off
causes syntax error in clink.bat script. - Fixed #567;
clink history compact
accidentally deletes all timestamps. - Fixed documentation error in Lua API Reference about
"w"
mode inio.open()
andio.sopen()
(the behavior was correct, but the documentation was inaccurate/unclear).
.v1.6.5 up top
- Added all match fields in the table of matches passed to the
clink.onfiltermatches()
callback function. - Fixed stripping colors from strings (e.g. when displaying in popup lists); it didn't strip 8-bit and 24-bit colors correctly.
.v1.6.4 up top
- Added
rl_buffer:hassuggestion()
andrl_buffer:insertsuggestion()
for direct access to inserting suggestions without invoking Readline commands. - Added
clink.dirmatchesexact()
andclink.filematchesexact()
which are the same as the non-exact
variants, except these don't append a*
to the search pattern. For example,clink.filematchesexact("*.zip")
can collect exactly "*.zip" file matches instead of "*.zip*". - Added OS version info to
clink info
. - Added UNC share name completion when using Executable Completion (the
exec.enable
setting). - Fixed completing input
.
or..
when theexec.enable
setting is enabled. - Fixed applying
colored-completion-prefix
when match display filtering is active or a match has a customdisplay
field. - Fixed the
exec.path
setting so it doesn't accidentally include directories if their names end with an executable extension such as.exe
. - Fixed finding an argmatcher registered with a full path (e.g.
c:\foo\bar.exe
) when a full path is entered without a drive letter (e.g. enter\foo\bar.exe
). - Fixed #562;
clink autorun install
strips quotes by mistake.
.v1.6.3 up top
- Breaking Change: For the four Ctrl-- key combinations, Clink got the Shift key backwards and generated inaccurate input codes. And that broke the Readline/bash default key binding for
undo
(the Windows default key binding of Ctrl-z works fine). If your .inputrc file has bindings for any of the Ctrl-- key combinations then you can keep the keys working the same by updating the key bindings. You can even use the$if clink_version >= 1.6.3
syntax in your .inputrc file to make it define the key bindings differently in different versions of Clink.Key Combination Old Code New Code Ctrl-- "\C-_"
orC-_
"\e[27;5;189~"
Ctrl-Shift-- "\e[27;6;189~"
"\C-_"
orC-_
Ctrl-Alt-- "\e\C-_"
or"\M-\C-_"
orM-C-_
or etc"\e[27;7;189~"
Ctrl-Alt-Shift-- "\e[27;8;189~"
"\e\C-_"
or"\M-\C-_"
orM-C-_
or etc - Completions for all
clink set
settings include the current value in the description field (e.g. typeclink set
Alt-= to see Clink settings and their current values). - Fixed to differentiate between
undo
andvi-undo
commands again (they do the same thing, but are technically different commands). - Fixed
execute-named-command
to also accept Ctrl-- forundo
(the emacs binding for undo). - Fixed redisplaying multi-line prompts after using completion during
execute-named-command
. - Fixed accidentally loading the history file twice on each prompt; now it loads once, as intended.
- Fixed another double-free and potential crash in the Readline library; after navigating through history entries and then editing a history entry, pressing Ctrl-c or Ctrl-Break could cause a crash or memory corruption (regression exposed by changes in Readline 8.2).
- Applied fixes for 6 Lua bugs, curated by @goodusername123 (thank you!) from Lua.org:
- "Dead keys with nil values can stay in weak tables."
- "Expression list with four or more expressions in a 'for' loop can crash the interpreter."
- "Label between local definitions can mix-up their initializations."
- "Return hook may not see correct values for active local variables when function returns."
- "Suspended __le metamethod can give wrong result."
- "Wrong code generated for a 'goto' followed by a label inside an 'if'."
- Fixed the Lua debugger so 5-digit line numbers don't break indentation when showing source code lines.
.v1.6.2 up top
- Added optional argument
argmatcher:chaincommand(aliases)
to let the argmatcher know that the chained command will have doskey aliases expanded. - Fixed match display potentially missing some matches (regression introduced in v1.6.1). In particular, git command completions were affected.
- Fixed command line input parsing so that the first word (the command word)
foo/
is interpreted as two wordsfoo
and/
just like CMD does. - Fixed #549;
cd -
intercept interferes withcd
doskey alias. - Fixed #546; in Windows 10 when "Wrap text output on resize" is unchecked or the Window Width is different from the Screen Buffer Width, then the display becomes garbled. The root cause is a limitation in how Windows 10 implements support for ANSI escape codes, but Clink now has workaround code that tries to compensate for the problems as much as possible (the terminal display will be a bit jittery, though; there's nothing that can be done about that).
- Fixed updating the display after using
clink-popup-show-help
to invoke a command that changes only the cursor position. - Fixed a case where a custom strategy for auto-suggestions could accidentally skip inserting part of the suggestion.
- Fixed a race condition where
clink-diagnostics
could encounter an error while printing information about coroutines.
Important pre-release changes in Readline:
Readline 8.2 introduced a crash in the undo
command after navigating through history and making edits in history entries. The following pre-release updates in Readline fix the crash and several related issues. They also fix many other edge-case stability issues, and add a couple of new features.
- Fixed crashes due to memory corruption in the undo information for editing operations.
- Fixed many issues found by Address Sanitizer (ASAN); these are edge cases where crashes or memory corruption or malfunctions or memory leaks occurred.
- Added new
execute-named-command
bindable command which reads a command name from the input and executes it (default is Alt-x). - Allow
quoted-insert
into search strings. - Repeated invocations of
vi-yank-pop
now cycle through the kill ring. - Fixed when
do-lowercase-version
is bound to something that's not an uppercase letter. - Fixed getting the value of the
active-region-start-color
config variable.
.v1.6.1 up top
Features:
- Improved input line parsing and coloring:
- Commands starting with
@
are supported, and completion correctly ignores the@
. - Each of the following CMD syntax errors are recognized: lines starting with
&
or@2>
, and lines containing& &
or2>&file
. - The whole redirections
2>file
or>file
or2>&1
are colored instead of only the>
or>&
.
- Commands starting with
- Completions for
clink set
color settings include a color sample in the description field (e.g. typeclink set color
Alt-= to see the color settings and their current color samples). - The
clink-reload
bindable command now reverts key bindings and config variables before reloading the inputrc file, so that old bindings and values don't linger in the current session if they've been removed from the inputrc file. - Added
clink-dump-functions
andclink-dump-macros
bindable commands. These behave similar todump-functions
anddump-macros
, but they show user-friendly key names andluafunc:
macros are listed as functions instead of as macros. - Added some new "bigword" cursor movement commands for moving to the next or previous space delimited word;
clink-backward-bigword
,clink-forward-bigword
,cua-backward-bigword
,cua-forward-bigword
. - Added a new conditional directive
$if clink_version
in the inputrc file (e.g.$if clink_version >= 1.6.1
). - Added a new
prompt.spacing
setting which can control blank lines before the prompt (it was a clink-flex-prompt feature which has now been incorporated into Clink itself). - Added a new
match.coloring_rules
setting and%CLINK_MATCH_COLORS%
environment variable, both of which supersede Readline's%LS_COLORS%
definitions when displaying match completions. - Internal changes.
Lua:
- Added
line_state:getrangeoffset()
andline_state:getrangelength()
to get the beginning offset and length of the range in the input line described by the line_state. - Added
console.explodeansi()
to split a string into substrings on ANSI escape code boundaries. - Added
rl.getinputrcfilename()
to get the loaded inputrc file name. - Added
rl.translatekey()
to translate between key sequence formats (input key, key binding, and friendly key name). - Added
rl.bracketpromptcodes()
to apply\1
and\2
codes as needed by Readline in certain inputrc config variables. - Document the
CLINK_EXE
global variable which has existed since v1.0.0 but was accidentally undocumented.
Fixes:
- Removed superfluous
;39
and/or;49
from color setting escape codes in some cases. - Fixed
console.readinput()
repeatedly returning nil afterconsole.checkinput()
returns true (regression introduced in v1.5.12). - Fixed loading the
default_inputrc
file if it exists (introduced in v1.3.5, and it never worked properly until now). - Fixed the
history-size
config variable to be completely ignored (it interfered with Clink's history database and settings, which were meant to supersede it). - Fixed the
clink-popup-show-help
command when including unbound commands (numeric argument of 4) so it doesn't double-list the boundluafunc:
macros. - Fixed updating column text in
clink.popuplist()
when Del is pressed (e.g. history timestamps in theclink-popup-history
command). - Fixed the width of
clink.popuplist()
to take the title into account. - Fixed Lua argument errors for some objects (the argument # in the error message was one lower than it should have been in some messages).
- Fixed the return value from
rl_buffer:setcursor()
. - Fixed
console:getnumlines()
between onendedit and onbeginedit. - Fixed erasing the "History expansion for" preview when the transient prompt is enabled.
- Fixed the transient prompt sometimes not erasing properly (regression introduced in v1.5.17).
- Fixed the color of flags for
clink set
(e.g.--help
). - Fixed the
clink-reload
command so any inputrc file parse errors are printed on new lines. - Fixed the
lua.break_on_error
setting so it works properly in released builds of Clink.
.v1.6.0 up top
- Updated the Readline library to v8.2 patch 7 (the list here omits changes that were contributed to Readline from Clink, or which do not affect Clink).
- New features:
- History expansion better understands multiple history expansions that may contain strings that would ordinarily inhibit history expansion (e.g.,
abc!$!$
). - There is a new
fetch-history
bindable command that retrieves the history entry corresponding to its numeric argument. Negative arguments count back from the end of the history. - There is a new option:
enable-active-region
. This separates control of the active region and bracketed-paste. It has the same default value asenable-bracketed-paste
, and enabling bracketed paste enables the active region. Users can now turn off the active region while leaving bracketed paste enabled. (Note that bracketed paste is currently ignored in Clink.) - Readline looks in
%LS_COLORS%
for a custom filename extension (*.readline-colored-completion-prefix
) and uses that as the default color for the common prefix displayed whencolored-completion-prefix
is set, superseding theso
type if both are present. - Two new bindable string variables:
active-region-start-color
andactive-region-end-color
. The first sets the color used to display the active region; the second is unused and unnecessary in Clink, but exists anyway for compatibility. If set, these are used in place of terminal standout mode.
- History expansion better understands multiple history expansions that may contain strings that would ordinarily inhibit history expansion (e.g.,
- Fixes:
- Fixed a problem with cleaning up active marks.
- Fixed a problem with arithmetic comparison operators checking the version in the inputrc file.
- Fixed a bug that could cause readline to crash if the application removed the callback line handler before readline read all typeahead.
- Added additional checks for read errors in the middle of readline commands.
- Fixed a problem with
unix-filename-rubout
that caused it to delete too much when applied to a pathname consisting only of one or more slashes. - Fixed a couple problems where
transpose-words
could corrupt the end of the input line. - Fixed an issue that caused a history line's undo list to be cleared when it should not have been.
- Fixed leaked memory from undo lists.
- When replacing a history entry, make sure the existing entry has a non-NULL timestamp before copying it; it may have been added by the application, not the history library.
- New features:
- The
blink-matching-paren
setting works in Clink now. - Completion works for UNC share names now (share names like
\\server\share
, not server names like\\server
). - Improved undo grouping for consecutive inserted text.
- Added
os.enumshares()
to enumerate the SMB UNC shares on a given server. - Fixed Lua error messages from custom Lua libraries that report errors using table objects instead of strings.
- Fixed issue with the
autosuggest.hint
setting where it could apply incorrect input line coloring when the Right key isn't bound to one of the usual commands for that key. - Internal changes and optimizations.
.v1.5.18 up top
- Fixed #524 and #523; garbled display in wide terminal windows (regression introduced in v1.5.14, which exacerbated and revealed a bug that's existed since Clink v1.0.0 alpha and which could intermittently garble Unicode text or escape sequences).
- Fixed the transient prompt sometimes not displaying properly (regression introduced in v1.5.17).
.v1.5.17 up top
- Reduced flicker when async prompt filtering redraws the prompt.
- When
_argmatcher:addarg()
or_argmatcher:addflags()
is passed a table containingnowordbreakchars="chars"
then the chars are not treated as word breaks for that argument index or for flags (see Overcoming Word Breaks for more information). - Added a
user_data
argument to the custom classifier function for an argmatcher (set via_argmatcher:setclassifier()
). - Improved input line coloring for
clink set
so thatcolor.unexpected
is only used for a completed word that isn't a match. - Fixed reading lines from stdin in Lua scripts (e.g.
io.stdin:read()
). - Fixed accidentally showing matches in a single column sometimes even when there are no descriptions.
- Fixed an incomplete
clink inject
if an explicit or implicitendlocal
happens afterclink inject
but before the prompt is shown (the injection didn't finish successfully until the next time an environment variable was set, but now it finishes immediately).
.v1.5.16 up top
- Fixed #522; garbled display in JetBrains WebStorm terminal (regression introduced in v1.5.15).
- Fixing this required reverting the change that automatically chose a default for
color.suggestion
based on the current console colors.
- Fixing this required reverting the change that automatically chose a default for
- Fixed
:chaincommand()
so that generators and classifiers that come after argmatchers in the priority order receive the sameline_state
objects as ones that come before argmatchers in the priority order. - Fixed
:setdelayinit()
with linked argmatchers; the callback function was only called for registered argmatchers (e.g.clink.argmatcher("foo"):setdelayinit(func)
) and it wasn't called for linked argmatchers (e.g."-x" .. clink.argmatcher():setdelayinit(func)
). - Fixed the word parser to recognize a single digit as a word when followed by punctuation.
- Fixed
loopchars
for characters like-
or*
that are also Lua pattern characters.
.v1.5.15 up top
- Added localized descriptions for flag completions in
cmd
,cd
, andrd
. - Added partial ability to detect light/dark console color themes:
- Added
console.getcolortable()
which returns a table with the console's current 16 predefined colors. When possible, the table includes a field indicating whether the current console color theme is a light or dark theme. - At this time, the colors can be accurately retrieved only when using the legacy conhost terminal. When using Windows Terminal, ConEmu, or other ConPty-based terminals there is currently no way to accurately retrieve the colors. Once the Terminal#10639 issue is fixed then Clink will also detect the background color in these terminal programs.
- Changed the default for
color.suggestion
so that it attempts to detect light themes (bright background colors) when possible, and it attempts to automatically choose a default color for suggestions that is faint but has sufficient contrast to be readable.
- Added
- Fixed the
onlink
callback function in:addflags()
so that thearg_index
parameter is correctly0
instead of1
. - Fixed the upper bound line number for Lua console line API functions.
- Fixed
console.getlinetext()
when emojis are present.
.v1.5.14 up top
- Added a visible usage hint for Auto-Suggestions to help make the feature more discoverable and usable. The usage hint can be hidden by turning off the
autosuggest.hint
setting. - Added new callback functions that can be assigned to an argument position in the table given to
:addarg()
viaonadvance=
andonlink=
(see Responding to Arguments in Argmatchers for more information). - Fixed displaying match descriptions containing embedded color codes.
- Fixed finding argmatchers for doskey alias names containing quotes.
- Fixed parsing the input line when a doskey alias references a command with an argmatcher that uses the
:chaincommand()
function (e.g. an aliasfoo=sudo dir $*
with an argmatcher likeclink.argmatcher("sudo"):chaincommand()
so that completions and input line coloring work properly for the rest of the input line). - Fixed the
exec.commands
setting with an argmatcher that uses the:chaincommand()
function. - Fixed
_argmatcher:setclassifier()
so the custom classifier is called for flags as well as for arguments.
.v1.5.13 up top
- Added
clink.onhistory()
to register a function to be called when the input line has been accepted and is about to be added to history (and optionally cancel adding it). - Fixed
history delete
with a negative number so it indexes backwards from the end, as advertised. - Fixed calling
clink.refilterprompt()
from a coroutine, and related fixes to ensure various Lua functions coexist properly with coroutines. - Fixed #520; add a link to the Releases page in the updater dialog box.
.v1.5.12 up top
- Fixed updating the input line display after using
clink-popup-history
orwin-popup-history
(regression introduced in v1.5.3; the fix in v1.5.4 was incomplete). - Fixed
console.checkinput()
so it doesn't eat whatever pending input it detects. - Fixed the updater to be more specific about what PowerShell cmdlet it invokes, in case a module replaces the built-in
Expand-Archive
cmdlet.
.v1.5.11 up top
- Fixed prompt filters and other Lua coroutines when
color.executable
andcolor.unrecognized
are both empty (regression introduced in v1.5.10).
.v1.5.10 up top
- Changed
clink update
to consider "up-to-date" as a successful case. - Fixed a case where the
completion
auto-suggest strategy could be temporarily prevented from providing a suggestion (regression introduced in v1.4.22). - Fixed leaked memory when showing history expansion previews.
- Fixed #511;
!
doesn't need to be treated as a word break character. - Internal changes.
.v1.5.9 up top
- Added default key binding Alt-Ctrl-Up for
clink-popup-history
. - Fixed the
match.max_rows
setting to control the number of rows of items (instead of the total number of rows including description rows). - Fixed #509; crash when using
clink-popup-history
ifhistory.time_stamp
isoff
(regression introduced in v1.5.7).
.v1.5.8 up top
- Fixed #504; the
clink.autoupdate
setting behaves likeauto
even when it's set tocheck
(regression introduced in v1.5.5). - Fixed #503; the updater could hang if any additional CMD instances were started while the "Clink Update" prompt window was open (regression introduced in v1.5.5).
.v1.5.7 up top
- Added vertical scrollbars in
clink-select-complete
and in popup lists. - Added
terminal.scrollbars
setting which can disable the vertical scrollbars (e.g. according to preference, or if a terminal or font is incompatible with extended Unicode box drawing characters). - Added
clink set --info
flag. - Added language-related diagnostic info in
clink info
. - Added minor optimization when displaying prompt text.
- Added enhancements in the pager used when displaying help or matches; Tab or Space or Y print the next page, D prints the next half-page, Enter prints the next line, N or Q stop printing, and ? shows the available keys in the
-- More --
pager prompt (the enhancements were accidentally lost in v1.1.1-alpha). - Horizontal scrolling in popup lists works for all columns, if text doesn't fit in the column.
- Fixed crash in
rl.getmatchcolor(match, type)
; when the optionaltype
parameter was passed in, the API could crash. - Fixed #498; when
autosuggest.enable
is False, cycling or searching through history and then pressing Right does nothing (regression introduced in v1.5.4). - Internal improvements.
.v1.5.6 up top
- Added
os.getpushddepth()
, which works when%PROMPT%
contains exactly one$+
. - The
clink-popup-history
andwin-history-list
commands show timestamps whenhistory.time_stamp
is set toshow
. - Fixed
os.geterrorlevel()
whencmd /u
was used. - Fixed word break parsing in the input line when certain Unicode characters are present.
- Fixed Unicode string conversions to disallow translating to "similar" characters (which could be problematic in filenames).
- Fixed a crash in
rl.getkeybindings()
if it's called by a Lua script running insideclink set
. - Fixed Lua debugger input if a script error occurs inside
clink set
. - Fixed a width quirk in
clink-select-complete
where typing to narrow the list to a single item accidentally made the column width at least 3 characters, even if the item was only 1 or 2 characters width. - Fixed
clink history
to handle escape codes embedded in thehistory.time_format
setting. - Fixed a potential crash after using
remove-history
at the beginning of the history list. - Fixed #494; Lua error when using
unicode.fromcodepage()
(reported and fixed before the bug was published). - Fixed #493;
clink-select-complete
displays the selected item incorrectly if bothcolored-stats
andcolored-completion-prefix
areoff
(regression introduced in v1.5.5).
.v1.5.5 up top
- Changed the
clink.autoupdate
setting to allowoff
,check
(the default),prompt
, andauto
for more control over how and when updating happens. When set toprompt
orauto
Clink can trigger updates automatically, so you don't need to even runclink update
. - Enhanced
debug.log_terminal
to include low level console keyboard and mouse input events. - Fixed
debug.log_terminal
to capture all input (regression introduced in v1.5.2). - Fixed slowness during
clink-select-complete
while typing, caused by excessive match generation. - Fixed selection highlight in
clink-select-complete
when the whole match text has been typed. - Fixed #486; window title escape code doesn't work properly if it contains emojis or UTF8 content.
- Internal changes.
.v1.5.4 up top
- Further contrast improvements for default colors to be readable in both Dark and Light terminal themes.
- Added
arginfo
field inbuilder:addmatches()
and in match display filtering. - Auto-suggestions are no longer shown while searching history; it was too distracting and confusing.
- Fixed updating the input line display after using
clink-popup-history
orwin-popup-history
(regression introduced in v1.5.3). - Fixed
old-menu-complete
andmenu-complete
when there's only one match. The first time it should insert the match, and subsequent times should ding instead of cycling through the same match over and over and requiring an equal number ofundo
to undo. - Fixed match display filtering to support the
match.substring
setting. - Fixed match display filtering to support the
files.system
setting. - Fixed the cursor position if match display filtering happens the first time
clink-select-complete
is used in a session. - Fixed a case where two
undo
were required to fully undo whatmenu-complete
inserted. - Fixed Esc during incremental history search mode so it cancels the search.
- Fixed input line coloring after
non-incremental-reverse-search-history
ornon-incremental-forward-search-history
finds an exact match for the search text (since v1.1.5). - Internal changes and optimizations.
.v1.5.3 up top
- Added
builder:setfullyqualified()
to force completions to be inserted as fully qualified path names. - Completions for
clink set setting_name input
use fully qualified path names for input. This helps avoid accidentally setting relative paths in global settings; since the current directory changes frequently, setting relative paths usually leads to unintended consequences. - Only load a script from a
completions\
directory if the associated command exists in the file system. Also, pass the fully qualified file name as input to the script (in Lua, use...
to get script arguments, e.g.local command = ...
). clink info
now reports whether Clink is injected.- Improve efficiency of updating the input line display. This eliminates some redundant processing in the Readline library and in Clink.
- Fixed input line parsing and coloring when the
doskey.enhanced
setting is off or when doskey macro expansion is suppressed. - Fixed
line_state:getwordinfo()
to accurately set the.alias
field when thedoskey.enhanced
setting is off or when doskey macro expansion is suppressed. - Fixed coloring the command word in the command line when queued keys select and accept a command line from history instantly (it could accidentally continue without applying the appropriate coloring).
- Fixed script error in
clink.filematches(nil)
andclink.dirmatches(nil)
; they were meant to behave the same as passing an empty string.
.v1.5.2 up top
- Adjusted the colors in "Use enhanced defaults" to have sufficient contrast to be readable in both Dark and Light terminal themes.
- More reliably detect whether hosted in Windows Terminal, and even when Windows Terminal is set as the default terminal application.
- Fixed crash in
clink.popuplist()
when thecurrent
argument is past the end of the list of items. - Fixed cursor location when the input line contains embedded CTRL characters.
- Fixed #474; pasting is slow in Windows Terminal and ConEmu.
- Fixed #470; typo in help text.
.v1.5.1 up top
- Added
rl.getcommandbindings()
to get info about a command, including the key(s) bound to it, if any. - Changed to also allow
clink.popuplist()
inside a function registered byclink.onfiltermatches()
. - Changed console input mode handling to more aggressively clear
ENABLE_VIRTUAL_TERMINAL_INPUT
since it interferes with input (especially Ctrl key combinations) and some console programs set it but accidentally neglect to clear it when they're finished.
.v1.5.0 up top
- Added code-signing.
- Added note after successful
clink update
to clarify that the update will take effect in new Clink windows. - Fixed order of running the autostart script (from the
clink.autostart
setting) vs loading Lua; the autostart script should run before Lua so that Lua scripts can query environment variables set by it. Otherwise Lua scripts may behave differently on initial load versus after invoking theclink-reload
command (e.g. Ctrl-X,Ctrl-R). - Fixed precedence of match colors; readonly should be lower precedence than executable.
- Fixed #469; incorrect usage of
memset()
.
.v1.4.28 up top
- Added
console.getcursorpos()
to get the cursor position. - Updated
os.getscreeninfo()
to include the cursor position. - Changed character width measurements in Windows Terminal to accommodate certain fully qualified color emoji variants such as "✔️" vs "✔". The former is U+2714 U+FE0F and Windows Terminal draws a double-width color emoji; the latter is U+2714 and Windows Terminal draws a single-width character in the current font. Note that Windows Terminal draws the characters; Clink just tries to make the best prediction it can about how Windows Terminal will draw the characters.
- Fixed display glitch where auto-suggest caused the display to scroll up an extra line at the bottom of the screen.
- Fixed display glitch where cursor position was wrong when the input line ends with a history expansion directive that ends exactly at the right edge of the terminal.
- Fixed
cmd.ctrld_exits
so Ctrl-D always exits with return code 0, so that terminal programs allow the shell window to close gracefully. - Fixed mouse input when the
horizontal-scroll-mode
inputrc variable ison
. - Fixed missing prompt text when a prompt filter encounters an unhandled Lua error; now a placeholder prompt string is used so it's clear where the prompt is.
- Fixed #467; On-Screen Keyboard in Swedish keyboard layout can't type
\
. - Internal improvements.
.v1.4.27 up top
- Fixed when the
terminal.emulate
setting isauto
on Windows 8.1 and earlier (regression introduced in v1.4.26).
.v1.4.26 up top
- Added built-in support for shell integration with Windows Terminal v1.18 and higher. Note: Windows Terminal gets confused about the command line text when the transient prompt is enabled.
- Changed
clink.getansihost()
to return two strings; the first string is the mode in use, and the new second string is what Clink detected (and will use when theterminal.emulation
setting isauto
). - Fixed to use terminal emulation when the
terminal.emulate
setting isauto
and ANSICON is present. Clink's output is no longer able to be intercepted by ANSICON, so bypass it and use Clink's own terminal emulation. - Fixed #461; crash due to invalid RVA in ANSI32.DLL or ANSI64.DLL (ANSICON).
.v1.4.25 up top
- Now
os.issignaled()
works duringonendedit
andonfilterinput
events. - Improve emulation for F7 history popup (the
win-history-popup
command); Left or Right replace the input text with the selected line. - Transient prompt filters can suppress the transient prompt on a case by case basis by returning
nil, false
. - Fixed typo in
clink set --help
text. - Fixed where the prompt prefix (from v1.4.24) is inserted in the prompt string, so that shell integration escape codes can work properly.
- Fixed #457; unrecognized OSC escape codes accidentally stripped from prompt string.
.v1.4.24 up top
- Added
path.fnmatch()
which behaves like the Linuxfnmatch(3)
function. - Added
os.globmatch()
which performs recursive file pattern globbing the same as git does. - Added support for
%CLINK_PROMPT_PREFIX%
,%CLINK_PROMPT_SUFFIX%
,%CLINK_RPROMPT_PREFIX%
, and%CLINK_RPROMPT_SUFFIX%
to provide prefix/suffix strings to surround the prompt strings, and for prompt filters to define a:surround()
function to add their own prefix/suffix strings if needed. - Fixed
~
by itself to change directories, the same as~\
. - Fixed horizontal scrolling in popup lists (is possible whenever the item doesn't fit and no items contain control codes).
- Fixed #452;
history delete #
doesn't work (regression introduced in v1.1.43). - Fixed #448; completion malfunction with
..\does_not_exist
(regression introduced in v1.4.1).
.v1.4.23 up top
- Added help message in
clink-select-complete
: when descriptions are shown below the matches, this adds text to mention that F1 toggles showing descriptions inline with the matches. - Added
clink update --check
to only check for an update without installing it.
.v1.4.22 up top
- Fixed
clink-select-complete
to use per-matchappendchar
when present. - Fixed repetitive unnecessary work in the background when the
completion
auto-suggest strategy encounters afromhistory
argument slot in an argmatcher. - Fixed the installer
/S
flag (silent install) so it returns exit code 0 on success.
.v1.4.21 up top
- The
clink-diagnostics
command can report merged argmatchers. When a numeric arg of 2 or greater is given (e.g. Alt-2,Ctrl-x,Ctrl-z) then it includes a list of defined argmatchers. The list now also reports any merging of argmatchers that occurred. - Fixed
clink update
sowinget
doesn't get confused about whether an update is available for Clink. Oncewinget update clink
performs an update, or once a Clink v1.4.21 or greater .exe installer is run, thenwinget
should stop getting confused.
.v1.4.20 up top
- Fixed
os.isfile()
andos.isdir()
when the specified name contains<
or>
or"
, which are special wildcard characters for MS-DOS compatibility. This caused an error when typing"<
, which then mistakenly thought a completion script named<.lua
existed. - Fixed
rl.expandtilde()
to omit a trailing backslash when expanding~
by itself. This is to avoid running afoul of the\"
parsing rules forargv[]
for programs. - Fixed potential crash when the
clink
command line takes more bytes as UTF8 than it does as UTF16.
.v1.4.19 up top
- Added
builder:setforcequoting()
to force quoting rules to be applied to matches even if they aren't filenames. This also reverts "quoting for non-filename completions" in v1.4.13; there isn't a safe and backward-compatible way to automatically deduce when non-filenames matches need quoting, so a match generator needs to turn it on explicitly when desired.
.v1.4.18 up top
- Added
clink.oninputlinechanged()
to register a function to be called whenever the input line is changed.
.v1.4.17 up top
- Added
os.isuseradmin()
to get whether CMD is running as an admin account. - Added
os.getfileversion()
to get a table with version information if the file contains a Windows version info resource. - The
clink-diagnostics
command now reports costs for Lua event callback functions when a numeric arg is given (e.g. Alt-1,Ctrl-x,Ctrl-z) or when thelua.debug
setting is enabled.
.v1.4.16 up top
- Added
history.show_preview
setting that controls whether to show a preview of history expansions (previously it was inferred by whethercolor.histexpand
was set). - Added detection for problematic codes in the prompt string. The
clink-diagnostics
Ctrl-X,Ctrl-Z command reports problem codes in the prompt string. When certain problem codes exist in the prompt string, then Clink compensates by reprinting the entire input line after printing the prompt string. Ideally, the prompt string should be fixed by the user, but sometimes that's difficult if the prompt string was generated by a tool. - Potential Breaking Change: Fixed how hidden and system files are handled by
os.globdirs()
andos.globfiles()
(it had never worked properly). It worked fine with the default modes of thefiles.hidden
andfiles.system
settings andmatch-hidden-files
config variable. But if any of those were changed from the default values then malfunctions could occur. With the fix, in backward compatibility mode thefiles.hidden
andfiles.system
settings andmatch-hidden-files
config variable control whetheros.globdirs()
andos.globfiles()
find hidden or system files, as before, and things can potentially malfunction. When the optionalextrainfo
argument is non-zero or when a new optionalflags
table is passed to them, they now default to including hidden files and omitting system files, but theflags
table can override that. This change was necessary because some scripts were unable to detect git repositories when thefiles.hidden
setting was false. Excluding hidden files never worked properly in the past. Clink v1.4.16 does its best to be as backward-compatible and forward-compatible as possible, but in some cases scripts may need to be updated to work properly when the settings or config variable are changed from their default values. - Fixed the
match-hidden-files
config variable to work again (regression introduced in v1.0.0). Also, when off, now it hides files and directories whose names begin with.
. - Fixed #421;
clink.bat
errors with quoted arguments (regression introduced in v1.3.47). - Updated documentation with more cross-referencing links for Clink settings, Readline commands, Readline config variables, and standard Lua APIs.
.v1.4.15 up top
- Added
log.getfile()
to get the current log file path. - Fixed match display to better accommodate escape codes for italics and underline, if present and supported by the terminal.
- Fixed #414; argument color doesn't reset for values in multi-column layout when
colored-stats
isoff
. - PR #418; Fix crash caused by destruction of non detached threads.
- PR #417; Fix buffer overread caused by usage of strcmp on non null-terminated char arrays.
.v1.4.14 up top
- Fixed autosuggest to update again if matches are marked as volatile and the input line changed while matches were generated in the background (related to clink-completions#164).
.v1.4.13 up top
- Added more status information in
clink-diagnostics
Ctrl-X,Ctrl-Z. - Fixed quoting in the
insert-completions
Alt-* command. - Fixed quoting for non-filename completions.
- Fixed a CPU busy-loop after
match_builder:setvolatile()
was called during an autosuggest strategy. - Fixed #411; setting
%CLINK_HISTORY_LABEL%
after Clink started didn't take effect (regression introduced in v1.3.18).
.v1.4.12 up top
- Additional improvements and logging for East Asian ambiguous width characters.
- Running
clink inject
no longer empties the log file, so that AutoRun doesn't result in the log file being cleared over and over, which interferes with diagnostic efforts. - Fixed #407; the
complete
command gets confused by.
prefix on files.
.v1.4.11 up top
- Fixed #406; the "lambdagenerated.omp.json" theme for Oh-My-Posh has problems in CJK codepages. The East Asian Ambiguous support has been rewritten to solve multiple subtle issues; the fix in v1.4.9 exposed other inaccuracies.
.v1.4.10 up top
- Added optional
level
argument tolog.info()
to facilitate more accurate reporting about the calling code. - Fixed extra duplicate log entry when the updater finds that Clink is already up to date.
- Fixed #405; vi search gives unexpected results (regression introduced in v1.4.7).
- Fixed #402; for convenience, print the Clink Releases page URL after a successful update (takes effect on the next upgrade after v1.4.10).
.v1.4.9 up top
- Improved the problematic character reporting in the
clink-diagnostics
command. - Fixed measurements for the East Asian ambiguous width characters (this should solve the Cmder problems with lambda in the CMD.exe prompt text, including the space after the lambda).
.v1.4.8 up top
- Added
rl.needquotes()
function to check whether text needs quotes in a command line. - Changed the
terminal.color_emoji
settingauto
mode to more broadly support accurate width measurements for color emojis (regardless whether the terminal program is capable of actually drawing the color emoji). - Now
clink-diagnostics
Ctrl-X,Ctrl-Z automatically analyzes the prompt text for problematic characters, reports them, and offers suggestions for how to solve problems they might be causing. - Fixed the
completion
autosuggest strategy so it doesn't provide a suggestion that requires quoting if the command line input is not currently quoted. - Fixed overly aggressive detection of color emojis (regression introduced in v1.4.7).
.v1.4.7 up top
- Clink now supports ARM64.
- Clink now recognizes when the terminal host is WezTerm.
- Clink now supports color emojis in Windows Terminal and WezTerm, according to the Unicode v15.0 standard. The new
terminal.color_emoji
setting controls when Clink assumes the terminal supports color emojis (color emojis are rendered using double-width characters, which can interfere with cursor positioning math, so Clink needs to know whether the terminal supports color emojis). - Enabled Readline's support for non-incremental vi-mode search (N, n) to search for a shell pattern using
fnmatch()
, as Posix specifies. - Fixed obscure issue when a "luafunc:" macro modifies the input line and then invokes a completion command.
- Fixed
line_state:getword()
andline_state:getendword()
to not strip quotes duringgenerator:getwordbreakinfo()
functions (regression introduced in v1.1.24). - Fixed #393; backward compatibility issue when
clink.arg.register_parser()
is passed something that is not a parser at all. - Fixed #111 again;
cd ..
Tab didn't complete to..\
(regression introduced in v1.3.1).
.v1.4.6 up top
- Added a more informative exit code from
clink inject
. It returns 0 if successful, 2 if a fatal error occurred, or 1 if a non-fatal error occurred (such as Clink was already present; related to cmderdev/cmder#2800). - Fixed #382;
%CLINK_PROFILE%
doesn't supersede--profile
(regression introduced in v1.0.0).
.v1.4.5 up top
- Improved debug Lua messages; Clink's built-in Lua scripts reported "?" as the filename, and now they report "{filename.lua}".
- Fixed potential for a crash in
clink-help
when including unbound "luafunc:" macros for which custom descriptions have been provided (e.g. Alt-4 then Alt-H).
.v1.4.4 up top
- Fixed the screen width in the Help commands and Completion commands (regression introduced in v1.3.43).
- Fixed to not load the same Lua script more than once from a completions directory when the Lua script doesn't define an argmatcher.
- Fixed architecture reported by
clink-diagnostics
Ctrl-X,Ctrl-Z (regression introduced in v1.3.49).
.v1.4.3 up top
- Added backward compatibility for obsolete
clink.quote_split()
,clink.split()
, andclink.get_screen_info()
. - Fixed empty completion list when typing two letters in rapid succession when both the
autosuggest.enable
andautosuggest.async
settings are enabled.
.v1.4.2 up top
- Fixed path abbreviation in some cases.
.v1.4.1 up top
- Added
os.abbreviatepath()
andos.expandabbreviatedpath()
. - Invoking completion expands abbreviated paths when the new
match.expand_abbrev
setting is enabled. - Fixed displayed matches for
c:
orc:dir\
.
.v1.4.0 up top
- Added
clink.getpopuplistcolors()
to get the default popup list colors. - Added
clink.refilterafterterminalresize()
to enable automatic prompt refilter after terminal resize. Prompt filters should only enable this if they're designed to refilter very quickly, otherwise they may cause responsiveness problems. - The
clink.popuplist()
function allows theitems
table to include fields to override the height, width, colors, and direction of the list. - The
clink_settings
file format has been relaxed slightly to accept trailing whitespace after a Boolean setting's value. Note that manually modifying theclink_settings
file is not supported; always useclink set
to query or change Clink settings. - Fixed an obscure crash in the Readline library inside the
reverse-search-history
command when pressing the first key of a multikey binding (e.g. Ctrl-X) and then pressing any key that does not follow the first key in any of the corresponding multikey bindings (e.g. Esc). - Fixed leaked file handle when
history.save
is False. - Fixed #370; Tab inside
set /p var=
mistakenly discards any previous input.
.v1.3.51 up top
- Fixed
:setendofflags()
; it made--
work correctly for input line coloring, but it didn't work correctly when generating match completions. - Fixed obscure edge cases where matches returned by Lua scripts could display incorrectly in
clink-select-complete
, or could potentially even crash if Lua scripts returned invalid results from theondisplaymatches
oronfiltermatches
events.
.v1.3.50 up top
- Fixed the prefix highlighting when displaying matches.
.v1.3.49 up top
- Autorun detects non-interactive CMD process earlier, before injecting the Clink DLL. This can improve performance somewhat, and may be able to reduce spurious problems with antivirus tools (such as described in #367).
- Updater deletes zip file if it fails to unzip. This can help automatically recover from a damaged zip download.
.v1.3.48 up top
- Fixed another #356 case; trailing spaces at end of display were sometimes optimized away by mistake (regression introduced in v1.3.43).
.v1.3.47 up top
- Removed the message "Clink autorun is disabled by CLINK_NOAUTORUN".
- Fixed #361; detect
%CLINK_NOAUTORUN%
faster. - Fixed another #356 case; end of display line not cleared sometimes (regression introduced in v1.3.43).
.v1.3.46 up top
- Fixed right-side prompts on Windows 8.1 (they never worked correctly on Windows 8.1).
- More fixes for #356; input line display garbled on Windows 8.1 (regression introduced in v1.3.43).
.v1.3.45 up top
- Fixed the history expansion preview when the input line grows or shrinks to use a different number of screen rows.
- Fixed
"cd"
so it doesn't match thecd
argmatcher, because CMD commands cannot be quoted. - Fixed #356; input line display garbled on Windows 8.1 (regression introduced in v1.3.43).
.v1.3.44 up top
- Fixed #348; pasting in ConEmu or Windows Terminal duplicates the 2nd character (regression introduced in v1.3.43).
.v1.3.43 up top
- Added
clink.max_input_rows
setting that limits the number of screen rows to use for displaying the input line, scrolling as appropriate if the input line exceeds the limit. - Added
color.histexpand
setting. When this is configured with a color, then Clink highlights history expansions in the input line and shows a preview of the expansion that will be applied near the current cursor position. - Added
history.auto_expand
setting. When this is set to false, history expansions will not be performed automatically upon Enter, but they may still be performed by invoking expansion commands such asclink-expand-history
Alt-^, orclink-expand-line
Alt-Ctrl-E. - When a coroutine error happens, write a Lua traceback to the log file.
- The
clink-diagnostics
command now reports costs for prompt filters and input line coloring classifiers when a numeric arg is given (e.g. Alt-1,Ctrl-x,Ctrl-z). - Fixed the input line color when the command word is an alias and a directory and has an argmatcher (regression introduced in v1.3.40).
- Fixed how the inserted completion is highlighted while using
clink-select-complete
with thematch.substring
setting enabled. - Fixed Readline bugs in the numeric arg input state;
- Numeric arg overflow check was missing in certain cases.
- Numeric arg input state could accidentally empty the prompt string.
- Numeric arg input state accidentally continued showing the arg input message after using Alt-- while already in numeric arg input state.
- Fixed some minor input line coloring and completion mistakes for
clink set
. - Fixed
quoted-insert
followed by Esc, so that it inserts the raw ESC character. - Fixed how Esc is handled in isearch mode (e.g. Ctrl-r); it should terminate isearch without reverting the input line.
- Fixed
what-is
to consistently reset the color afterward. - Fixed vi insertion mode when
terminal.raw_esc
is enabled, so that Esc changes to vi command mode. - Fixed
clink.refilterprompt()
to report an error upon invalid usage (it cannot be used inside a prompt filter, as that could cause infinite recursion and a crash). - Fixed #344;
history
prints UTF8 text incorrectly. - Fixed #342; typing
foo.abc
doesn't recognizefoo.abc.cmd
. - Fixed #340; various display glitches in the Readline library (Clink now uses custom display routines instead of the Readline display routines).
- Fixed #339;
%CD%
doesn't expand.
.v1.3.42 up top
- Added
console.checkinput()
to check whether input is available. - Changed
console.readinput()
to accept an optional no_cursor argument to avoid changing cursor visibility or position. - Fixed #320; resizing the terminal can garble the prompt (
bash
has the same problem, so Clink now uses custom code to handle resizing the terminal).
.v1.3.41 up top
- Added
io.truncate()
to truncate a file. - Added
string.comparematches()
to compare two matches; this is normally not needed because Clink automatically sorts matches, but some match generators may prefer to disable the automatic sorting and perform custom sorting. - Added
rl.describemacro()
to associate descriptions withluafunc:
macros (or any macro), to be shown in theclink-show-help
andclink-what-is
commands. - The
clink.popuplist()
function now accepts a callback function to be invoked when Del is pressed. - The
colored-completion-prefix
configuration variable now works with match display filtering, provided the display strings only prepend or append to the match strings. - Removed the obsolete
clink.gui_popups
setting. - Fixed the
completion-prefix-display-length
configuration variable in various cases. - Fixed timing condition that could potentially crash (regression introduced in v1.3.40).
.v1.3.40 up top
- Clink now has an icon, and also includes some colored icons for color-coding your shortcut files, terminal tabs, and etc.
- Avoid mis-coloring a directory name as though it is an argmatcher (uses a background thread to stay responsive).
- Fixed command word completion after
:chaincommand()
. Nowcmd /c
Tab works properly. - Fixed
:chaincommand()
to work properly in a nested argmatcher; it should imply:nofiles()
otherwise it can pop out to the previous argmatcher instead of chaining. - Fixed
cmd
argmatcher to only chain after the/c
and/k
flags, to more accurately match actual cmd.exe syntax. - Fixed backward compatibility for argmatchers using the old v0.4.9 APIs with functions as argument options (regression introduced in v1.2.7).
- Fixed the
clink-select-complete
command with match display filtering.
.v1.3.39 up top
- "Use enhanced defaults" now includes history timestamps.
- Fixed delay while loading the history file when history timestamps are enabled (regression introduced in v1.3.18).
- Fixed suggestions to resume after fully accepting an input line suggestion and then changing the text (regression introduced in v1.3.29).
- Fixed reporting unbound commands in
clink-show-help
when arg is 4 (Alt-4,Alt-H) (regression introduced in v1.3.9). - Fixed to normalize path separators in a fully qualified pathname when using
clink.argmatcher(full_path)
. - The documentation now shows a link icon when hovering over any heading or API name, to make it easy to copy and share links.
.v1.3.38 up top
- Added
clink.recognizecommand()
function that input line coloring classifiers can use to find whether to color a word as executable. This is the same mechanism Clink uses internally, and the analysis is asynchronous. - Now
clink.argmatcher(command)
may be passed a fully qualified pathname for command to enable different argmatchers for programs with the same name. - Fixed argmatcher lookup to favor doskey aliases, so that e.g. "
dir
" can be aliased to an alternative program but "dir
" can invoke the built-in dir command, and they can each have separate argmatchers. - Fixed the
oncommand
event to also fire when the command word offset changes, because adding/removing a leading space can change whether the command is an alias, which can make the typed command word resolve to a different file or program to invoke. - Fixed
line_state:getcommandoffset()
when the first word is quoted. - Fixed
line_state
parsing for input lines such asfoo.exe&
, so that theexec.enable
setting can generate matches properly. - Fixed completion so that CMD command names are not among the completions when preceded by a quote.
- Fixed
color.argmatcher
color to not overwrite custom colors that may have already been applied. - Fixed
^
to not be a word break character when parsing the input line.
.v1.3.37 up top
- When
argmatcher:addarg()
is passed a table containingloopchars="chars"
then the chars are treated as delimiters for a single argument, and they do not move on to the next argument slot in the parser. - Added
clink.parseline()
to parse a string into one or moreline_state
objects. - Added
os.getdrivetype()
to get the drive type for a path; especially useful if your code needs to skip network paths. - Added
match_builder:setvolatile()
to force the matches to be used only once. This makes it possible for match generators to produce different kinds of matches based on what has been typed, e.g. an email address match generator could list user names until@
is typed, and then list domain names. - The
clink-diagnostics
command now lists registered argmatchers when the numeric arg > 1 (Alt-2,Ctrl-x,Ctrl-z). - Rewrote the path parsing routines to properly respect UNC paths and
\\?\
syntax and\\?\UNC\
syntax. - Fixed
clink.print(NONL, etc)
to not print a TAB character after aNONL
that is the first argument. - Fixed #329; file completions may be mistakenly marked as directories (regression introduced in v1.2.36; affects only backward compatibility mode).
- Fixed #326;
rl.expandtilde()
doesn't have a way to expand tildes everywhere in an input line string. - Fixed #325; potential hangs while typing if
%PATH%
contains a UNC path.
.v1.3.36 up top
- Incremental search in
clink-popup-history
now centers the found item if it is scrolled out of view. - Tilde expansion is supported for all Lua script directory names and for the
%CLINK_PROFILE%
environment variable (but there is a quirk, and for the profile directory tilde expands to%LOCALAPPDATA%
for backward compatibility purposes). - Fixed some tilde expansion issues; quotes weren't always recognized, and embedded tildes could in some cases result in malformed paths.
- Fixed semicolon delimiter in
%CLINK_COMPLETIONS_DIR%
. - Fixed stack exhaustion crash when using
inject --profile nul
. - Fixed detection of device names when coloring command words; a device name anywhere in a path is not a valid executable.
.v1.3.35 up top
- Fixed finding a
completions
directory under the profile directory. - Fixed finding a
completions
directory under script directories set viaclink installscripts
. - Fixed
clink.refilterprompt()
when the prompt wraps past the edge of the screen and a right-sided prompt string is present. - Fixed
rl.getpromptinfo()
when the prompt wraps past the edge of the screen (thepromptline
andinputline
fields were inaccurate). - Fixed consistent sort order for completion matches that differ only by case.
- Fixed
undo
(Ctrl-z) after usingclink-reload
(Ctrl-x,Ctrl-r). This also fixesrl.ismodifiedline()
afterclink-reload
, which was causing clink-flex-prompt to show a modmark afterclink-reload
. - Fixed #321; incremental search not working in the
clink-popup-history
command (regression introduced in v1.3.19). - Fixed #320; prompt becomes garbled when prompt is updated by async prompt filters and wraps past the edge of the screen and a right-sided prompt string is present.
.v1.3.34 up top
- Improved error reporting in
lua.debug
mode for coroutine failures. - Fixed argmatcher flag definitions that begin with
+
(regression introduced in v1.3.11). - Fixed the updater when there are PowerShell configuration problems that cause internal errors unrelated to Clink's use of PowerShell.
- Fixed potential coroutine failure if a
delayinit
argmatcher is still running after a new input line begins (regression introduced in v1.3.29). - Fixed
os.getfileattributes()
,os.isfile()
, andos.isdir()
to fail as intended when the input includes a wildcard (regression introduced in v1.1.0). - Fixed potential Lua error when typing a command name that included a wildcard, if the wildcard matched a file in a
completions
directory (regression introduced in v1.3.23, due to theos.getfileattributes()
issue above).
.v1.3.33 up top
- The
io.popenyield()
function now also returns a function that can be used to get the exit status from the command. - Fixed
io.popenyield()
for some programs (such as FC and XCOPY) that fail to start if the stdin handle is empty. - Fixed #312; slow startup due to inefficiency in the updater check at startup (regression introduced in v1.3.26).
.v1.3.31 up top
- Reverted the v1.3.29 change to
file:close()
that returned the process exit state even afterio.popen()
orio.popenyield()
in a coroutine. It had subtle negative side effects.
.v1.3.30 up top
- Fixed the
menu-complete
family of commands forfromhistory
argmatchers whenautosuggest.enable
is enabled. - Fixed #311; "The handle is invalid." (regression introduced in v1.3.29).
.v1.3.29 up top
- Fixed how Right and etc work after fully accepting an input line suggestion. It shouldn't immediately show a new suggestion when the current suggestion is fully accepted (until the cursor is moved or the text changes), and
win-cursor-forward
shouldn't append characters from the previous command (e.g. whenclink.default_bindings
iswindows
). Otherwise holding or double-pressing Right can accidentally turn into something the user didn't intend. - Fixed double-loading completion script when a command word includes a path component (e.g. "c:\clink_dir\program.exe" mistakenly attempted to load "c:\clink_dir\program.lua" instead of loading "program.lua" from the completions directories).
- Fixed delayinit argmatchers so they don't get orphaned if a new input line starts before they finish.
- Fixed
file:close()
to be able to return the process exit state even afterio.popen()
orio.popenyield()
in a coroutine.
.v1.3.28 up top
- Fixed #309; some locales fail to parse the PowerShell version number.
.v1.3.27 up top
- Added more detailed logging when the updater fails.
- Added check to make sure PowerShell v5 is present when using
clink update
. - Added
unicode.fromcodepage()
andunicode.tocodepage()
for UTF8 conversions. One of the cases where this can be useful is when handling redirected output from programs that product output using the current Active Code Page.
.v1.3.26 up top
- Added
unicode.iter()
,unicode.isnormalized()
, andunicode.normalize()
for more precise UTF8 string manipulation. - The updater now includes an HTTP header to request no caching, in an effort to work around an issue on Win8.x.
- The updater now updates the version number displayed in the "Apps & features" section of Settings in Windows (or "Add or Remove Programs" in Control Panel in older versions of Windows).
- Fixed the
directories.dupe_mode
setting inclink set
. - Fixed the
remove-history
command when trying to remove a history entry added by theadd-history
command that hasn't yet been saved. - Fixed the
/D=
flag in the setup program. - Fixed potential double-load of scripts in the profile or binaries directories, due to an issue while searching
completions
directories (regression introduced in v1.3.24). - Fixed potential infinite loop when merging an argmatcher with itself.
- Fixed potential accidental resume of an orphaned coroutine.
- Fixed potential double-reporting of coroutine errors when the
lua.debug
setting is enabled. - Internal maintenance to the coroutine management system.
.v1.3.25 up top
- Fixed updater when
%TEMP%
contains spaces. - Fixed executable file detection to color device names (such as nul, aux, con, lpt1, and com1) as neither recognized nor unrecognized.
- Fixed #304; hang when typing device names (such as aux, con, lpt1, and com1) (regression introduced in v1.3.23).
- Fixed #303; downloading latest update doesn't work on Windows 8.x.
.v1.3.24 up top
- Standardized the order in which
completions
directories are searched. - Fixed the second return value from
clink.popuplist()
, which was backwards by mistake.
.v1.3.23 up top
- Automatically loads Lua completion scripts from
completions
directories. This allows you to optionally store completion scripts (argmatcher scripts) in a separate directory from your other Lua scripts, so that completion scripts are only loaded when needed. This can speed up Clink start time, if you have a large volume of argmatcher scripts. See Completion Directories for more information. - Fixed
clink.oncommand()
when redirection appears on the command line before the command name (e.g.>somefile command
). - Fixed both parts of #300; unable to find latest release zip file (incomplete fix in v1.3.22 by mistake).
.v1.3.22 up top
- When the
lua.debug
setting is enabled, any uncaught errors in coroutines are reported (and logged). - Fixed edge case that could cause Windows Terminal to temporarily stop responding mouse input.
- Fixed #300; unable to find latest release zip file.
.v1.3.21 up top
- Improved the auto-updater when there are multiple copies of Clink on a computer; it no longer needs to download the .zip update file multiple times.
- Fixed mouse input when the console is scrolled.
- Fixed #299; update shown even though up to date.
.v1.3.20 up top
- Fixed potential crash in popup lists if there are only a few items (regression introduced in v1.3.18).
- Fixed #296; on some computers closing CMD reports it's taking too long to close (the fix works around external issue).
.v1.3.19 up top
- Added
directories.dupe_mode
setting that controls how duplicates are handled in the directory history list for theclink-popup-directories
command. - Added Del to delete a directory entry in the
clink-popup-directories
command. - Fixed obscure intermittent problem with
delayinit
argmatchers. - Fixed Ctrl-C and Ctrl-Break in CMD built-in commands (regression introduced in v1.3.14).
.v1.3.18 up top
- Added a built-in updater for Clink, which is enabled by default. When enabled, Clink reports when an update is available. Run
clink update
to apply the update. - Added
clink-insert-suggested-line
,clink-insert-suggested-word
,clink-insert-suggested-full-word
, andclink-accept-suggested-line
commands (see #280). - Added optional timestamps in the history file. The new
history.time_stamp
andhistory.time_format
settings control whether timestamps are saved and whether/how timestamps are shown. - Added
cmd.altf4_exits
setting to control whether Alt-F4 makes cmd.exe exit. This is so that when theterminal.raw_esc
setting is enabled pressing EscEsc behaves the same as Alt-Ctrl-[ as expected, while still allowing Alt-F4 to work. - Added horizontal scrolling in the history popup list.
- Added
clink.onprovideline()
so scripts can register a function to be called afteronbeginedit
but before any input is processed. The function can return a string to be executed as a command line, in which case the line editor is not invoked and theonendedit
andonfilterinput
events happen immediately (see #263). - Added
rl.gethistorycount()
andrl.gethistoryitems()
to access the history items. - Added
os.gettemppath()
to get the system temporary directory. - Added
io.sopen()
to control sharing access when opening or creating a file. - Both
io.open()
andio.sopen()
support the"x"
file mode modifier (combined with"w"
or"w+"
), which makes the function fail if the file already exists. - Improved the
what-is
command to apply word wrapping to the command description. - Fixed generating matches from history (
fromhistory=true
) in argmatchers (regression introduced in v1.3.13). - Fixed executable file detection for file names that contain
+
characters. - Fixed some input keys accidentally handled by the OS sometimes (regression introduced in v1.3.6; original fix was introduced in v1.2.10).
- Fixed timing conditions where other console programs could accidentally override Clink's mouse input mode.
- Fixed left mouse click in popup lists when
terminal.mouse_input
is enabled. - Fixed alternate key bindings for copy (Ctrl-Ins) and paste (Shift-Ins).
- Fixed description column alignment in
clink.popuplist()
. - Fixed keyboard driver for Alt-Ctrl-[ when the
terminal.raw_esc
setting is enabled. - Fixed keyboard driver for Alt-Ctrl-] and Alt-Ctrl-</kbd>.
.v1.3.17 up top
- Fixed coloring executable files in the input line (some file types weren't detected correctly, and missing files were considered executable if their extension had a file type association).
- Fixed a potential crash when coloring executable files in the input line (regression introduced in v1.3.16).
- Fixed #281; screen height detected incorrectly (regression introduced in v1.3.16).
.v1.3.16 up top
- Added
os.sleep()
. - Revised the Clink documentation to directly include the Readline documentation.
- Fixed executable file detection for file extensions that point at Progids instead of having a shell command.
- Fixed double help message from
history
command when invalid flags are used. - Fixed crash when file permissions block accessing the history file, and the
history
command reports an error message accordingly. - Fixed #262; changing the terminal width between prompts (while a different program is running) caused Readline to start displaying the input line incorrectly.
.v1.3.15 up top
- Fixed #269; reverse video could get confused (regression introduced in v1.3, and incompletely fixed in v1.3.4).
.v1.3.14 up top
- Ctrl+Break can now interrupt some operations, including match display and match generators and the
os.globfiles()
andos.globdirs()
functions in Lua scripts. - Added
os.issignaled()
so Lua scripts can cooperatively interrupt themselves. - Improved responsiveness of completion commands when an async prompt filter is still running in the background (
io.popen()
andos.execute()
are serialized in prompt filter coroutines, and are serialized separately in match generator coroutines, but are not serialized in other coroutines). - Fixed displaying pasted lines.
- Fixed doskey aliases in pasted lines.
- Fixed #268; crash when
copy
command prompts whether to overwrite a file (regression introduced in v1.3.13).
.v1.3.13 up top
- Argmatchers can use
:chaincommand()
to treat the rest of the command line as another command.- Added an argmatcher for
cmd
that uses:chaincommand()
. - E.g. so that completion after
cmd program
can be parsed by an argmatcher forprogram
instead ofcmd
.
- Added an argmatcher for
- Argmatchers can be more involved in parsing the command line, if they wish. See Responding to Arguments in Argmatchers for more information.
- A callback function can be assigned to an argument position by including
onarg=your_callback_function
in the table given to:addarg()
. - The
onarg
callback and match functions receive an additionaluser_data
parameter. When parsing begins, theuser_data
is an empty table, and your functions can set or get data from the table. Each time a flag or argument links to another argmatcher, the new argmatcher gets a separate new emptyuser_data
table. - The built-in
cd
andpushd
argmatchers use this to influence match completion for the rest of the input line. E.g.pushd \foo & program
Tab uses\foo
as the current directory when generating possible completions.
- A callback function can be assigned to an argument position by including
- Functions registered with
clink.onfilterinput()
may optionally return multiple lines in a table. - Fixed completions for words that contain
.
, such asclink set color.
Tab (regression introduced in v1.3.11). - Fixed doskey macros that use
echo off $T ...
. - Fixed input line coloring for a drive letter by itself.
- Fixed input line coloring for a file that exists but is not executable.
- Fixed obscure edge case with delayinit argmatchers and
operate-and-get-next
. - Fixed potentially inconsistent input line coloring when
classifier:applycolor()
is given an escape code that sets only the foreground or background color.
.v1.3.12 up top
- Improved
clink-select-complete
to show inline descriptions as long as they don't require more than 9 rows to display the matches. - Added second argument to the
delayinit
function for an argmatcher. - Added
argmatcher:setflagsanywhere()
andargmatcher:setendofflags()
to control where flags are recognized. - Added
clink.getargmatcher()
to find the argmatcher for a command name or command line (line_state
). - Added
os.resolvealias()
to expand doskey alias(es) in a line of text. - Added
clink.oncommand()
to register a function to be called when a command is entered in the edit line. - Improved support for argmatcher non-flag argument values that end with
=
: now they can have a linked argmatcher, and input line coloring is applied correctly. - Fixed quotes during completion (regression introduced in v1.3.11).
- Fixed
cd /d dir
argmatcher (regression introduced in v1.3.11). - Fixed input line coloring for
"echo"
and other CMD commands; quotes disqualify a word from being a CMD command. - Fixed redundant argmatcher delayinit for flags.
- Various minor backward compatibility fixes.
.v1.3.11 up top
- Updated the list of recognized CMD command names.
- Better support for
(
and)
when expanding doskey macros (e.g. now( macro foo ) & ( macro bar )
works). - Fixed word break characters during completion. Only
=
;
had ever worked before, and now the normal CMD completion word break characters work (including,
!
+
(
and many others). - Fixed match display to not force a single column unless there are descriptions present.
- Fixed backward compatibility for
_argmatcher:add_arguments()
and_argmatcher:set_arguments()
(they were mistakenly adding all the arguments into the first argument position). - Fixed backward compatibility for merging argmatchers.
- Merging argmatchers works again. It is still a simple merge similar to v0.4.9, but it should be sufficient for common cases.
- Fixed some bugs in how Clink v0.4.9 merged argmatchers (the unit tests for merging fail in v0.4.9).
- Added support for some merging cases that weren't implemented yet in v0.4.9.
- And other obscure minor backward compatibility fixes.
.v1.3.10 up top
- An argmatcher can extend itself on the fly, when needed. For example, if it needs to parse arguments and flags from
--help
text, or if the available command arguments change based on the current directory, or etc. See Adaptive Argmatchers for more information. - Recognizes
^
and environment variables when coloring the command word, and when navigating by typing a directory name by itself. - Added input line coloring for the
rem
command. - Fixed memory corruption (regression introduced in v1.3.1).
- Fixed input line coloring for
clink set setting value & another command
. - Fixed argmatcher input line coloring for matches using the
{ match="abc" }
syntax. - Fixed finding an argmatcher after
(
at the beginning of the line. - Fixed mouse clicks in
clink-select-complete
to insert the clicked match, in addition to highlighting it. - Fixed #252;
md
andrd
should complete more than 1 argument.
.v1.3.9 up top
- When
argmatcher:addarg()
is passed a table containingfromhistory=true
then additional matches are generated by parsing the history file to find values for that argument slot from commands in the history file. - Added
clink.reclassifyline()
which triggers input line coloring and redisplays the input line. This is intended for use by a coroutine that has made changes that will affect input line coloring. - Added
match_builder:isempty()
. - Added mouse horizontal wheel support in
clink-select-complete
. - Added back the
_argmatcher:setflagprefix()
function. - Loading Lua scripts now reports any syntax errors when the
lua.debug
setting is enabled. - Incorporate Lua 5.2.4 (minor patches to the Lua language).
- Report a warning if the profile directory is configured to point at a file.
- AutoRun is selected by default again in the installer (reverted change from v1.3.5).
- The
terminal.raw_esc
setting now also address the same kind of problem with Alt+[ and Alt+Shift+O as with the Esc key. - Fixed when an argmatcher adds nested tables of matches using the
{ match="abc" }
syntax, so that the nested matches are added recursively and properly suppress adding a space after argument matches that end with:
or=
. - Fixed when
match_builder:addmatch()
andmatch_builder:addmatches()
add nested tables of matches using the{ match="abc" }
syntax, so that the nested matches are added recursively. - Fixed when
match_builder:addmatch()
andmatch_builder:addmatches()
add an"arg"
match type, so that they automatically suppress appending a space after matches that end with:
or=
(the behavior was documented, but did not work correctly). - Fixed
remove-history
so that it updates the history offset correctly and subsequent editing operations affect the correct undo list. - Fixed obscure issues in how certain key binding patterns were reported by
clink-show-help
anddump-functions
. - Fixed how
clink echo
reports Ctrl+Backspace and Ctrl+Alt+Backspace. - Fixed #249; sending keystrokes from WScript does nothing for some keys.
- Fixed #244; installer did not detect previous installation directory (regression introduced in v1.3.5; the fix takes effect on the next install after an install with the fix).
.v1.3.8 up top
- Added
terminal.mouse_modifier
setting and%CLINK_MOUSE_MODIFIER%
environment variable; these can override the modifier keys that activate Clink mouse input. - Added
%CLINK_SETTINGS%
environment variable; this can override the directory where theclink_settings
file is located. This can be used to put it in a directory that syncs between computers, for example. - During
clink-select-complete
Ctrl+Home or Ctrl+End select the first or last match. - When
argmatcher:addarg()
is passed a table containingnosort=true
then the matches are unsorted (displayed in the order listed in the table). - The .zip file now contains
_default_settings
and_default_inputrc
so that they do not take effect unless manually renamed to remove the_
name prefix. This avoids changing the defaults unexpectedly. - Fixed mouse click+drag in the input line (it accidentally behaved like double click+drag).
- Fixed the selection highlight width in
clink-select-complete
when some matches have descriptions but some do not. - Fixed
argmatcher:addargunsorted()
to turn off sort. - Fixed #239; crash when F7 and Del.
.v1.3.7 up top
- Mouse click+drag now works.
- Mouse click below
clink-select-complete
list expands the list instead of dismissing it. - Fixed responding to mouse clicks when the terminal's scrollback buffer is not empty (it only worked in Windows Terminal).
- Fixed #237; installer does not maintain previously selected "Autorun when cmd.exe starts" (regression introduced in v1.3.5).
.v1.3.6 up top
- Added
terminal.mouse_input
setting; the default isauto
.auto
lets mouse input work in ConEmu, or in the default Conhost terminal when Quick Edit mode is unchecked in the console Properties dialog. See the documentation for more information. - Added
cua-select-word
command that selects the word at the cursor. - Ctrl+X,Ctrl+Z with a numeric argument always includes registered Lua match generators, prompt filters, etc even when the
lua.debug
setting is off. - Fixed potential for a coroutine to have extra delays sometimes when continuing past the end of one edit line, and into the next edit line.
- Fixed a potential busy loop when the command word is unrecognized.
- Fixed Quick Edit mode in plain Conhost windows; it had always been disabled (I never noticed because I always configure console windows to disable it anyway).
.v1.3.5 up top
- Raised default
history.max_lines
to 10000. - Added an optional
default_inputrc
file:- It is loaded from the profile directory, or from the binaries directory.
- It uses the same format as the
.inputrc
file, and is loaded immediately before the.inputrc
files. - It has the effect of superseding built-in default values for Readline configuration variables and key bindings; any settings in the
.inputrc
supersede those in thedefault_inputrc
file.
- The installer has a new "Use enhanced default settings" option which installs
default_settings
anddefault_inputrc
files to provide default values that activate more of the Clink enhancements (to give a more enhanced experience "out of the box"). - The installer no longer defaults to installing AutoRun.
- The installer no longer has an option to use versioned install directory; files are installed directly in the install directory.
- Added
clink.runcoroutineuntilcomplete()
which allows a coroutine to keep running past the end of one edit line, and into the next edit line. - Fixed
os.execute()
return values when run in a coroutine (regression introduced in v1.3.2). - Fixed the selection color in
clink-select-complete
whencolored-stats
is off. - Fixed problems when displaying matches that exceed the screen width.
- Fixed #231; installer fails sometimes when uncheck "Use versioned install directory".
.v1.3.4 up top
- Pressing Del or Ctrl+D in a command history popup deletes the selected history entry.
- Changed the default color for directory match completions to bright yellow (bright blue is hard to see).
- Added an argmatcher for
history
. - Added an optional
default_settings
file:- It is loaded from the profile directory, or from the binaries directory.
- It uses the same format as the
clink_settings
file, and the values in it supersede the built-in default values for settings. - Settings are now saved if they are set (vs cleared by
clink set setting.name clear
), even if the set value matches the default value.
- Minor performance improvement when calculating columns widths when
match.fit_columns
is enabled. - Fixed accidentally using only one column in
clink-select-complete
when there are 9 or fewer matches and none of them have description text (regression introduced in v1.3.3). - Fixed Shift+Right to accept the next full word of the suggestion without clearing the rest of the suggestion (regression introduced in v1.3.3).
- Fixed terminal emulation for the reverse video escape codes (this also fixes the right border color of the selected item in popup lists).
- Fixed buffer overrun in Readline
yank-last-arg
when the previous command ends in a backslash. - Fixed the Readline History library to not apply Unix style backslash escaping in CMD (e.g. in
program subdir\ text
there are 3 arguments; the\
is not an escaped space). - Fixed crash when displaying matches and
match.fit_columns
is enabled and the terminal width is greater than 150 characters. - Fixed potential busy loop during idle (until a key is pressed) in certain cases (regression introduced in v1.3.3).
- Fixed the emulated terminal color conversions from 8-bit and 24-bit.
- Fixed cursor style when using
clink
to start a new command window from inside a Windows Terminal window. - Fixed quirk when using Clink file completion to complete a directory name for
clink --profile \foo\
, so that the path doesn't end up malformed. - Fixed a memory leak.
.v1.3.3 up top
- Match completion display calculates column widths to fit the most columns on the screen. Can be controlled by the
match.fit_columns
andmatch.limit_fitted_columns
settings. - Match descriptions are right-justified when more than one column is displayed, to help more columns fit.
- When multiple columns of matches are displayed with descriptions, the descriptions are bracketed with parentheses for readability and accessibility purposes.
- F1 in
clink-select-complete
toggles between showing descriptions at the bottom vs with the matches. - Added
match.substring
setting that uses a substring search for completions if none are found with a prefix search. - Added
color.executable
andcolor.unrecognized
settings. When set, these cause the command word (the first word) to be colored if it is recognized as an executable file, or is not recognized as a command, doskey macro, directory, argmatcher, or executable file. Lookups are asynchronous for optimum responsiveness while typing. - Argmatchers can hide certain flags (e.g. synonyms) by using
argmatcher:hideflags()
. - Argmatchers can disable sorting matches by using
argmatcher:addargunsorted()
orargmatcher:addflagsunsorted()
. - Generators can disable sorting matches by using
match_builder:setnosort()
. - Fixed duplicated closing quote in
clink-select-complete
. - Fixed display of non-directory matches that contain slashes, such as git branch names (regression introduced in v1.3.1).
- Fixed match display filtering in
clink-select-complete
(regression introduced in v1.3.1). - Fixed the
insert-comment
command (regression introduced in v1.2.44). - Fixed sorting flag completions so that all
-
flags precede any--
flags. - Fixed a couple of memory leaks, and added memory tracking system to more easily catch leaks.
- Various minor fixes in
clink-select-complete
.
.v1.3.2 up top
- Added Shift+Space as a recognized key. By default it is bound to
clink-shift-space
, which invokes whatever is bound to the normal Space key, so that it continues to behave as before unless you specifically bind something else to the Shift+Space key. - Added
clink-magic-suggest-space
command which inserts the next full suggested word (if any) up to a space, and then inserts a space. Binding this to Shift+Space can be very handy. - Added
cmd.admin_title_prefix
setting that can replace the "Administrator: " console title prefix. - When loading settings, if there is no setting file yet then Clink looks for a
default_settings
file in the binaries directory and uses that to initalize the settings. - Added
CLINK_TERM_VE
andCLINK_TERM_VS
environment variables that can be set to override the normal (insert mode) and enhanced (overwrite mode) cursor styles, respectively. - Various minor fixes to how the cursor style is updated; the visible bell now works in Windows Terminal.
- When
os.execute()
is used in a coroutine, it automatically yields until complete. - Fixed async match generators (during autosuggest) to be allowed to finish, instead of getting canceled on every keystroke if they hadn't finished yet.
- Fixed cursor blink, which was accidentally disabled (regression introduced in v1.2.44).
- Fixed the
win-cursor-forward
command so it doesn't trigger generating a new suggestion if there isn't already one.
.v1.3.1 up top
- Added
autosuggest.async
setting (on by default) that lets suggestions generate matches asynchronously to stay responsive while typing. - Added
match.max_rows
setting that limits the number of rowsclink-select-complete
can use. - Added
match.preview_rows
setting that makesclink-select-complete
show the specified number of rows of matches as a preview, and expands to show the full set of matches when the selection moves past the preview rows (similar to completion in the fish shell). - Added
color.comment_row
setting that chooses the color for the comment row inclink-select-complete
. The comment row shows the "and N more matches" or "rows X to Y of Z" messages. - Changed arrow keys in
clink-select-complete
to wrap on both horizontal and vertical edges (similar to the fish shell). - Changed arrow keys in
clink-select-complete
at the beginning and end of the list to wrap to the other end based on themenu-complete-wraparound
config variable. - Match generators can now specify an append character (or suppress appending) on a per-match basis.
- The
clink-diagnostics
command lists prompt filters, generators, classifiers, and suggesters when a numeric argument is given (e.g. Alt+1 then Ctrl+X,Ctrl+Z). - The
os.globdirs()
andos.globfiles()
functions now automatically yield periodically if used inside a coroutine. - The
io.popen()
function now automatically yields periodically if used in read mode (the default) inside a coroutine. - The
io.popenyield()
function now automatically falls back toio.popen()
if used outside a coroutine. - Fixed input line coloring to operate on only the input line, not including the suggestion.
- Fixed display when typing to filter
clink-select-complete
(regression introduced in v1.2.49). - Fixed display of
clink-select-complete
when the current match changes the number of visible lines in the edit buffer. - Fixed displaying matches when only a drive letter is entered.
- Fixed #216; Long escaped URLs do not display correctly in a prompt.
.v1.3 up top
- Added back
mark-modified-lines
support (was removed in v1.2.36). - Added
rl.ismodifiedline()
function so prompt filters can show a modified line indicator if they wish. - Added
autosuggest.original_case
setting (on by default) that controls whether parts of the line are updated to use the suggestion's original capitalization, or to keep the typed capitalization. - Added
terminal.east_asian_ambiguous
setting that controls how the width is determined for the East Asian Ambiguous range of characters (which includes the lambda character). This may help with working around display issues in some terminal hosts. - Added help descriptions for many vi mode commands.
- Improved relevance of
completion
suggestions by suppressing them when the word at the cursor is empty. - The
:suggest()
function on suggesters can now return a suggestion string and an offset where the suggestion begins in the input line. - Fixed a limitation in Readline so that
completion-prefix-display-length
andcolored-completion-prefix
can coexist. - Fixed when temp files from
io.popenyield()
get deleted. They were lingering until Lua garbage collection, but they can be deleted almost immediately. - Fixed the order of initialization: first the Readline .inputrc config file is loaded, and then Lua scripts are loaded. This enables Lua scripts to reliably override Readline config variables if they wish (for example so a prompt filter can clear
emacs-mode-string
and print its own keymap indicator as part of the prompt). - Fixed transient prompt to not show keymap mode strings or the modified line mark.
- Fixed vi mode key bindings that can accept suggestions.
- Fixed missing
vi-undo
command; it was pre-bound to some keys but could not be bound to any other keys. - Fixed the "show help" commands when listing unbound commands: unbound vi mode commands should not be listed in emacs mode because the vi mode commands are only meant to be used in vi mode, and are not meant to be bound to custom keys.
- Fixed memory leak in suggestions.
.v1.2.50 up top
- Added
rl.insertmode()
function to get or set whether insert mode is active. - Added
clink.onaftercommand()
so scripts can register a function to be called after every input command (key binding). - Added additional failure logging during
clink inject
.
.v1.2.49 up top
- Added
cua-previous-screen-line
andcua-next-screen-line
, bound to Shift+Up and Shift+Down, to extend the text selection up/down by one screen line. - Updated match generator for
clink set autosuggest.strategy
to list the available suggestion generators. - The
clink-show-help
andclink-popup-show-help
commands can include commands that aren't bound to any key, when the numeric argument is 4 (e.g. Alt+4 then Alt+H). - The
rl.getkeybindings()
function takes an optionalmode
argument to control sorting and whether to include commands that aren't bound to any key. - Generating suggestions skips generating match completions when the current word looks like a UNC path. This avoids pauses while typing that would otherwise occur when accessing networked drives.
- Fixed Alt+Right so it accepts the next word of the suggestion, just like Ctrl+Right does.
- Fixed the
clink-paste
command so it sets the mark to the cursor point prior to pasting. - Fixed when
history.dupe_mode
is "erase_prev" andhistory.shared
starts true but changes to false; subsequent commands were not added to the history properly anymore in that session (regression introduced in v1.1.0). - Fixed #210;
clink-select-complete
drawing bug with RPROMPT.
.v1.2.48 up top
- Ctrl+Right now inserts the next word of the suggestion the same way it would move to the next word, and Shift+Right inserts the next full word of the suggestion up to a space.
- Keys like Home/End, Shift+Left/Right, and Ctrl+Left/Right work in VI mode.
- Fixed input line coloring glitch when color settings use the
sgr
syntax.
.v1.2.47 up top
- Added autosuggestions similar to the Fish shell.
- Turn on by running
clink set autosuggest.enable true
. See theautosuggest.enable
andautosuggest.strategy
Clink settings for details. - Added
clink.suggester()
function to create new suggestion generators that can be used in theautosuggest.strategy
setting.
- Turn on by running
- The
clink-diagnostics
command also lists match generators registered byclink.generator()
. - Fixed the color when the
horizontal-scroll-mode
config variable ison
. - Fixed the transient prompt when using Help commands.
- Fixed the
clink autorun
commands when paths contain Chinese characters and the system code page isn't UTF8. - Fixed #209;
clink-popup-show-help
command fails. - Fixed #208; orphaned symlinks are colored wrong.
- Fixed #203; unable to inject when Clink binary directory contains Chinese characters (regression introduced in v1.0.0).
.v1.2.46 up top
- Added a
magic-space
command that performs history expansion on the text before the cursor point and then inserts a space. Note: this is slightly different than one in bash, which performs history expansion on the whole line and can end up inserting the space in a wrong spot. - Added
rl.getbinding()
andrl.setbinding()
functions to query or override key bindings. - Added a
clink.refilterprompt()
function to invoke prompt filtering on demand. - The
clink-popup-directories
command is now bound by default to Ctrl+Alt+PgUp. - The
clink-select-complete
command is now bound by default to Ctrl+Space. - Fixed the
clink-popup-history
command so incremental search works again (regression introduced in v1.2.36). - Fixed messages sometimes not being erased when finished, e.g. when using Alt+digits (regression introduced in v1.1.11).
- Fixed potential for prompt to redraw incorrectly after showing help when the
prompt.transient
setting is enabled. - Fixed settings defined by Lua scripts so that the Lua scripts can reliably see the current values even while the Lua scripts are being loaded or reloaded.
.v1.2.45 up top
- Clarified description of the
match.wild
Clink setting. - Fixed #196; installer checkboxes not working properly.
.v1.2.44 up top
- Fixed
clink.ondisplaymatches()
so it receives the right match strings (regression introduced in v1.2.39). - Fixed #194; argmatcher not found when command name contains a dash (regression introduced in v1.1.5).
- Fixed #176; use current installation dir when upgrading clink. Now the installer remembers the chosen installation directory and defaults to the same place when installing an upgrade (all of the checkbox states are remembered, in fact).
- Fixed #171; have a way to override install directory. Now the installer has a checkbox whether to install to a versioned directory (recommended). Unchecking the box installs program files to a
bin
subdirectory, instead of the usual versioned subdirectory.
.v1.2.43 up top
- Fixed lingering issues with non-ASCII characters in path names in Clink (follows up on the preceding fixes for non-ASCII user name characters).
.v1.2.42 up top
- Fixed potential for history file to get corrupted during compacting, if multiple Clink instances are running concurrently.
- Fixed
clink inject
when the user account name contains non-ASCII characters (regression introduced in v1.0.0). - Fixed #193; consider removing the 50K history limit: The
history.max_lines
Clink setting once again supports 0 to mean unlimited. Note that as the history file grows larger, it takes longer to load. If the size becomes a problem, you can useclink history compact <n>
to prune the history file to N items as well as compacting it (removing deleted items). - Fixed #192; completing
~
by itself does nothing: Completing~
by itself now inserts the %USERPROFILE% directory. This is different than bash, because on Windows it doesn't make sense for ~ by itself to complete other user accounts. This is a convenient way to expand tilde into a path that Windows understands. - Fixed #191;
cd /d -
isn't supported: Thecd -
feature now supportscd /d -
as well. It also supportscd -
even if there is a doskey macro defined forcd
.
.v1.2.41 up top
- Fixed #187 differently:
doskey.enhanced
istrue
by default again, but if a macro contains$*
or$1
...$9
tags within quotes then|
and&
symbols are part of the arguments, not command separators (and expansion stops after that macro). - Fixed compatibility when
doskey.enhanced
isfalse
;alias|whatever
should not expandalias
because there is no space after it. - Fixed doskey expansion when
>&
redirection symbol is present;command >& alias
should not attempt to expandalias
because it's a redirection file name, not a command.
.v1.2.40 up top
- Fixed display quirks when an empty
display
ordescription
string is provided by a match generator. - Fixed #187; the
doskey.enhanced
setting interferes with some macros (regression introduced in v1.0.0). The setting is nowfalse
by default, because of the incompatibilities it can cause.
.v1.2.39 up top
- Fixed regression in match display filtering when listing possible completions (regression introduced in v1.2.38).
- Fixed display quirks in the
clink-select-complete
command when descriptions are at the bottom.
.v1.2.38 up top
- Enhancements for match descriptions (which are displayed when listing possible completions):
- Argmatchers can provide description strings for flags and/or args (e.g. "Verbose output" for
-v
, or "Do nothing" for-n
, etc). - Argmatchers can also provide argument info strings for flags and/or args. These are hint strings, and not part of the completion match itself. E.g. "linenum" for
--line
, which gets displayed as "--line linenum" when listing possible completions, but only "--line" is inserted. - Match generators can provide
display
anddescription
strings when adding matches (match_builder:addmatch()
andmatch_builder:addmatches()
) -- it is no longer necessary to useclink.ondisplaymatches()
. - The
clink-select-complete
command now shows match descriptions in a single line at the bottom (instead of in a second column) when there are more than 9 matches. - Added
color.arginfo
Clink setting for the arguments for a flag or argument when listing possible completions. - Added
color.description
Clink setting for the default match description color when listing possible completions. - Truncate descriptions when a line will wrap (or has wrapped) when listing possible completions.
- Argmatchers can provide description strings for flags and/or args (e.g. "Verbose output" for
- Command separators (
&
,|
) and redirection symbols (<
,>
,>&
) are colored in the input line, using colors from the newcolor.cmdsep
andcolor.cmdredir
Clink settings. - Fixed Backspace in
clink-select-complete
; it had sometimes missed expanding the set of matches accordingly. - Fixed the
clink-popup-history
command to respect thesearch-ignore-case
setting. - Fixed
:nofiles()
to dead-end an argmatcher (regression introduced in v1.0.0). - Fixed
clink.ondisplaymatches()
andclink.onfiltermatches()
when there's only 1 match. - Fixed incremental find, find next, and find previous in console text popup lists.
- Fixed backward compatibility for the old matching filtering API.
- Fixed several other minor issues with match display filtering.
- Fixed intermittent incorrect match generation for
/flag:
or/flag=
flags. - Fixed duplicate removal with deprecated match generators.
- Fixed when nested deprecated argmatchers are exhausted (regression introduced in v1.2.36).
- Fixed deprecated match generators to not infer whether matches are filenames, to match the behavior of the v0.4.9 API.
- Fixed how
match.wild
works with deprecated match generators; e.g. arg completions for z.lua weren't working (regression introduced in v1.1.5). - Fixed argmatcher for
clink --profile
so it produces directory matches. - Fixed
%CLINK_RPROMPT%
alignment whencolor.prompt
is set.
.v1.2.37 up top
- Fixed #180;
rl.collapsetilde()
behaves erratically. - Fixed #179; incorrect handling for certain keys on some keyboard layouts.
- Fixed #178; OneDrive folders mistakenly show up as symlinks.
- Fixed #177; be silent about autorun injection into TCC.
.v1.2.36 up top
- Added
win-history-list
command bound to F7 by default. This shows the history list, and executes the selected history entry. - Changed all of the popup list commands to show popups using console text rather than GUI windows.
- Added a
color.popup
Clink setting for the popup colors. If not set, the console's popup colors are used. - Added a
color.popup_desc
Clink setting for the popup colors for the description column(s). If not set, a color is chosen to complement the console's popup colors. - Added a
clink.gui_popups
Clink setting that can be set to use GUI popup windows as before (thecolor.popup
settings have no effect on GUI popup windows).
- Added a
- Key bindings now support Enter plus combinations of the Ctrl, Shift, or Alt modifier keys.
- Added more backward compatibility shims.
- Fixed the
clink-select-complete
command whenprint-completions-horizontally
is on (and also minor issues when it is off). - Fixed the
clink-select-complete
command when a Lua script has usedrl.setmatches()
to provide a custom list of matches. - Fixed the
clink-menu-complete-numbers
family of commands (regression introduced in v1.2.32). - Fixed a situation where the scrolling keys could stop working (regression introduced in v1.2.24).
- Fixed flags at the end of a linked parser, and fixed args at the end of two or more nested linked parsers (regression introduced in v1.0.0).
- Fixed #172; add a choice in the installer to not add Start menu shortcuts.
- Fixed #129; Bug completing files with - or _ characters (regression introduced in v1.0.0).
.v1.2.35 up top
- Added
rl_buffer:getanchor()
to get the text selection anchor (there is no set function; userl.invokecommand()
to invoke commands to set/extend the selection if needed). - Reverted back to using IAT hooking (see issue #169).
- Fixed CUA selection commands invoked by
rl.invokecommand()
. - Fixed #170; directory symlink completion is truncated when
mark-directories
isoff
in the .inputrc file. - Fixed #169; incompatibility between AutoHotkey, AnsiCon, and Clink when all three are used in CMD's AutoRun regkey (regression introduced in v1.2.33).
.v1.2.34 up top
- Changed "luafunc:" macro functions to receive the
line_state
as a second argument. - Fixed Right when
clink.default_bindings
iswindows
. - Fixed
exec.files
setting so completion works when a path is specified (e.g.subdir\foo
) (regression introduced in v1.2.33). - Fixed #158; crash when a keyboard macro contains
\015
(regression introduced in v1.0.0).
.v1.2.33 up top
- Rewrote how Clink hooks APIs in CMD.EXE; it no longer uses any IAT hooking, and exclusively uses Detours.
- Added
clink.default_bindings
Clink setting to choose betweenbash
orwindows
default key bindings.bash
key bindings are still the default, for compatibility with existing Clink installations. - Added
exec.aliases
,exec.commands
, andexec.files
Clink settings to further customize how matches are generated for the first word when theexec.enable
Clink setting is enabled. - Small performance optimization in the hooked
WriteConsoleW()
system API. - Added logging for rare error case during inject.
- Added default key bindings for F1 through F9 that mimic the default Windows console function key inputs.
- Added
clink-selectall-conhost
command that mimics the default Windows console Select All command. - Fixed
clink-select-complete
to remove duplicate matches if generators try to add duplicate matches. - Fixed script error when
%PATH%
is not set andexec.enable
andexec.path
are both enabled. - Fixed some quirks when using the
quoted-insert
command.
.v1.2.32 up top
- Added
rl_buffer:setargument()
function for a "luafunc:" macro to be able to set Readline's numeric argument. - Added
os.getclipboardtext()
andos.setclipboardtext()
functions. - Added extra defense against antivirus interference (if it interferes when Clink inspects the target process, but permits Clink to inject into the target process).
- Fixed cooperation between "luafunc:" macros and CUA selection commands (e.g. Shift+End).
- Fixed
rl_buffer:getcursor()
and the return value fromrl_buffer:setcursor()
; both returned one less than the actual cursor position. - Fixed #162; clink completion shows script error (regression introduced in v1.2.31).
.v1.2.31 up top
- Added
clink uninstallscripts --all
to clear all script paths installed byclink installscripts
. - Added
os.touch()
function to set the access and modified times for a file. - Added more fields in
os.globdirs()
andos.globfiles()
whenextrainfo
is requested. - Potential Breaking Change: Fixed
os.globdirs()
andos.globfiles()
to only return extra info when actually requested (regression introduced in v1.1.8).- This unfortunately changes the scheme and may break some scripts if they requested no extra info, but used the extra info anyway.
- Fixed crash in
clink-select-complete
when a match display filter returns nil. - Fixed
ondisplaymatches()
which was receiving one fewer matches than it should (related to #124). - Fixed
ondisplaymatches()
which was not using the word break info correctly (from generators':getwordbreakinfo()
functions). - Fixed
word_classifications:applycolor()
; the input line didn't necessarily refresh correctly after a custom classifier applied custom colors. - Fixed potential stray inaccurate colorations when coloring the input for
clink set color.something some_value
. - Fixed #161;
clink installscripts
garbles previously-installed script paths when installing a new one. - Fixed #155;
settings.set()
doesn't update the settings file.
.v1.2.30 up top
- Replaced the built-in Lua implementation of
os.clock()
so it doesn't stop working after the program has been running for more than 24 days (which caused asynchronous prompt filtering to stop working). As a side effect, the newos.clock()
has microsecond precision instead of millisecond precision. - Fixed coroutine throttling. It was meant to prevent running more than once per 5 seconds, but accidentally forced running every 5 seconds, even if the coroutine was registered to run less often.
.v1.2.29 up top
- Added
prompt.transient
Clink setting which can collapse prior prompts to a condensed form. The new%CLINK_TRANSIENT_PROMPT%
and%CLINK_TRANSIENT_RPROMPT%
environment variables supply the initial prompt strings, and prompt filters can define:transientfilter()
and:transientrightfilter()
functions to filter the transient prompt. - Added
clink.logo
Clink setting to globally control what startup logo is shown (full copyright logo by default, or a short version logo, or no startup logo). - Added
console.readinput()
function which waits for one key input, and returns the key sequence string for the key. - Added
clink.reload()
function which reloads Lua scripts and the Readline config file at the next prompt. - Added logging for more possible failure points while injecting Clink into the host process.
- Added default key bindings for Ctrl+Up and Ctrl+Down to scroll the screen one line, like conhost normally does.
- Now
clink set cl*
lists all settings that begin withcl
(the star wildcard is only supported at the end of the string). - Documentation includes a link to the new clink-flex-prompt.
- Fixed the Lua debugger to support printing UTF8 text, and to escape string variable contents to avoid escape code side effects.
- Fixed #154; crash when
settings.set("some_setting", false)
is used. - Fixed #153; ESC key problem. Clink migrated the old
esc_clears_line
setting backwards, causing Esc to behave opposite from what was expected. - Fixed #152; LUA debugger breaks on the wrong line, and fails to execute expressions.
.v1.2.28 up top
- Added
rl.getpromptinfo()
function. - Fixed loading .inputrc so that only one is loaded (regression introduced in v1.0.0a0 by the fix for mridgers #258). If similar behavior is still desired, consider using the
$include
directive in the Readline init file, to load additional files. - Fixed
clink-select-complete
to respect whenmark-directories
in .inputrc file isoff
. - Fixed crash in
console.findline()
when no attributes are passed. Callers using v1.2.27 and earlier can work around the crash by passing{}
for attributes. - Fixed an off-by-1 bug in
console.scroll("absolute", top)
. This will fix edge case malfunctions in some callers, but some callers could experience this as a breaking change.
.v1.2.27 up top
- The
cmd.get_errorlevel
Clink setting is now enabled by default. - Clink now expands
$
codes in%CLINK_RPROMPT%
before running prompt filters. - Fixed parsing
2>&1
style redirection symbols, so the&
doesn't get treated as a command separator. - Fixed argmatchers to generate file matches for redirection arguments;
app.exe >
should generate file matches for the>
symbol, not matches for theapp
argmatcher's first argument.
.v1.2.26 up top
- Fixed input line coloring for doskey aliases that don't have an argmatcher (regression introduced in v1.2.16).
- Fixed Space during
clink-select-complete
when there were already opening and closing quotes present. - Fixed redrawing multiple lines of input after certain commands such as
clink-show-help
Alt+H (regression introduced in v1.1.20). - Fixed the
completion-auto-query-items
config variable to account for multiple lines of input, if present. - Fixed potential race condition if multiple Clink instances try to get the last errorlevel at the same time.
.v1.2.25 up top
- Added
cua-select-all
command to select the entire input line. - Added
edit-and-execute-command
command to invoke an editor on the current input line and then execute the results (Ctrl+X,Ctrl+E). This attempts to invoke%VISUAL%
,%EDITOR%
, ornotepad.exe
as the editor, in that order. - Added some new expansion commands:
clink-expand-history
performs history expansion on the current input line (Alt+^).clink-expand-history-and-alias
performs history and doskey alias expansion on the current input line.clink-expand-line
performs history, doskey alias, and environment variable expansion on the current input line (Ctrl+Alt+E).
- Added some new completion commands:
glob-complete-word
performs wildcard completion on the text before the cursor point, with a*
implicitly appended (Alt+G).glob-expand-word
inserts all the wildcard completions thatglob-list-expansions
would list (Ctrl+X,*).glob-list-expansions
lists the possible wildcard completions of the text before the cursor point (Ctrl+X,g).
- Added some command name synonyms for increased .inputrc file portability with bash:
alias-expand-line
is a synonym forclink-expand-doskey-alias
.history-expand-line
is a synonym forclink-expand-history
.history-and-alias-expand-line
is a synonym forclink-expand-history-and-alias
.insert-last-argument
is a synonym foryank-last-arg
.shell-expand-line
is a synonym forclink-expand-line
.
- Added a
match.expand_envvars
Clink setting to expand environment variables in a word before performing completion (for mridgers #476). - Changed the
match.wild
Clink setting to apply to all completion commands. - Changed default key binding Ctrl+Alt+E to the
clink-expand-line
command (not the key binding expands everything, instead of only the env var at the cursor). - Removed default key binding Alt+Shift+H for the
clink-show-help-raw
command (it has only niche usefulness). - Removed unintended VI mode key binding Alt+Ctrl+H.
- Fixed Ctrl+Shift+2 and Ctrl+Shift+6 (regression introduced in v1.1.39).
- Fixed
More?
continuation prompt when pasting multiple lines. - Fixed
/flag:
and/flag=
handling quirks, especially when trying to complete an environment variable in/flag:%env
. - Fixed quirks about environment variable expansion in the
clink-expand-env-var
command and theos.expandenv()
function.
.v1.2.24 up top
- Added support for
%CLINK_RPROMPT%
to show a right side prompt, and for prompt filters to define a:rightfilter()
function to filter the right side prompt. - Fixed
clink-select-complete
to not append a space after a flag that ends with:
or=
(e.g./x:
).
.v1.2.23 up top
- Fixed PgUp and PgDn in the
clink-select-complete
command, under certain conditions where they don't navigate in the intended manner. - Cosmetic change: better key names for Enter vs Ctrl+M, and Alt+Bkspc vs Alt+Ctrl+H, depending on the
terminal.differentiate_keys
setting.
.v1.2.22 up top
- Added
clink-what-is
command bound by default to Alt+?, which shows the key binding for the next key sequence that is input. - Added
rl.getargument()
function to get the accumulated Readline numeric argument, if any. For use in "luafunc:" macros. - The
clink-show-help
command now categorizes key bindings and shows a description for the commands. Using a numeric argument can control whether categorization and descriptions are used. - Fixed invoking
clink-select-complete
while it is already active, so that it doesn't lose quotes around the current match if it has quotes. - Fixed
clink-show-help
to list "Enter" instead of "C-m" for the Enter key. Otherwise there's no way to differentiate between Enter and Ctrl+M when theterminal.differentiate_keys
setting is enabled. - Fixed the
insert-comment
command, which accidentally fell back to inserting#
after the first prompt (that's what bash inserts, and shouldn't be used in Clink). - Fixed the
dump-functions
command, which accidentally didn't list UTF8 key sequences correctly.
.v1.2.21 up top
- Fixed backwards exit codes from
clink autorun
commands. - Fixed alert message text on startup when
debug.log_terminal
is set to true. - Fixed #143; crash on start when
terminal.raw_esc
is true (regression introduced in v1.2.19).
.v1.2.20 up top
- Added
os.debugprint()
function to print debug text via the OSOutputDebugString()
API. - Enabled match completion coloring even when using match display filtering.
- Fixed input of slash and backslash in non-directory completions when using the
clink-select-complete
command. - Fixed match display filtering in the
clink-select-complete
command. - Fixed match display filtering in the
clink-popup-complete
command. - Fixed quirk from Readline where it sometimes displays one fewer columns of matches than actually fit on the screen.
.v1.2.19 up top
- Added
clink-select-complete
command which shows an interactive list of possible completions. - Added terminal emulation for CGI G, CSI s, and CSI u sequences.
- Fixed column alignment for match display filtering when some characters take more than one cell to display.
.v1.2.18 up top
- Added completions for
clink installscripts
andclink uninstallscripts
. - Added support for Readline's coloring and marking of symlinks.
- Fixed
clink installscripts --help
. - Fixed
clink-popup-directories
for directories with spaces.
.v1.2.17 up top
- Added
clink-popup-show-help
command to show popup list with searchable list of key bindings and invoke the selected key binding. - Added
clink.popuplist()
function to show a popup list. Only usable from inside a "luafunc:" key binding. - Incremental search in the popup list window now centers the found item so items above and below it are visible.
- Fixed potential internal error when a doskey alias starts with
$
(regression introduced in v1.2.16). - Fixed potential infinite loop when the
cmd.auto_answer
setting is enabled but an error occurs while retrieving a language string (might be related to #137).
.v1.2.16 up top
- Breaking Change: The
clink.onendedit()
Lua event has been split into two separate events:clink.onendedit()
registers a function to be called when the edit prompt ends.clink.onfilterinput()
registers a function to be called after the edit prompt ends (and after the onendedit event is sent), and the function can replace the input text.
- Added
rl.getkeybindings()
function to get a table containing key bindings. The bindings can be invoked viarl.invokecommand()
. For example, a "luafunc:" macro could use this to get key bindings, show an interactive list, and then invoke the selected key binding. - Fixed #134;
print()
can stop working. Issue #93 can potentially happen any time redirection is used, so the fix must be applied repeatedly (not just after Clink injection). - Fixed #119; reuse registered parsers for doskey macros.
.v1.2.15 up top
- Fixed #132; multiline prompt gets overwritten when resizing the terminal width (regression introduced in v1.2.14).
.v1.2.14 up top
- Automatically runs
clink_start.cmd
from the binaries directory and/or the profile directory when Clink is injected. - Clink is able to retrieve the last exit code for use by Lua scripts.
- The new
cmd.get_errorlevel
setting is off by default, but when enabled it retrieves the last exit code from CMD before running Lua scripts. - The new
os.geterrorlevel()
function gets the last exit code (or 0 if the setting is off). - It works by running a hidden command line between each interactive prompt (as if you typed
echo %errorlevel%
yourself every second command you type). If you experience problems with this, turn it off.
- The new
- Improved refreshing the input line when resizing the terminal window. It's better than before, but there's no way to make it work perfectly because Windows can resize the terminal further while a program is already trying to respond to the terminal having been resized previously.
- Fixed #130; doskey alias completions stop working when there are many aliases.
.v1.2.13 up top
- Added support for linking a parser to flags ending with
:
or=
; now completion works for the flag's argument.
.v1.2.12 up top
- Improved diagnostic output for coroutines (Ctrl-X,Ctrl+Z), plus more diagnostic info when the
lua.debug
setting is enabled. - Fixed potential for a script error when a coroutine gets skipped due to a new prompt starting.
.v1.2.11 up top
- Added
clink.print()
function which behaves likeprint()
but with support for ANSI escape codes (and terminal emulation), and also aNONL
special argument that suppresses the usual newline at the end of the output. - Expanded the sample code for async prompt filtering to clarify some things.
- Fixed #126; allow Esc to input literal escape character.
- The new
terminal.raw_esc
setting controls how Esc input works. - Added migration for the old
esc_clears_line
setting.
- The new
.v1.2.10 up top
- Added asynchronous prompt filtering -- scripts can use this to do work in the background (e.g.
git status
) and refresh the prompt when finished.- Added
clink.promptcoroutine()
function to allow a prompt filter to do some work in the background. - Added
io.popenyield()
function to allow a coroutine to yield until the command's complete output is ready. - Added
prompt.async
setting that can disable asynchronous prompt filtering if preferred.
- Added
- Log error codes for failures during
clink inject
. - Clarified help text for
clink autorun
(per #122). - Documentation clarifications and reorganization.
- Fixed
clink
andhistory
aliases getting lost after exiting a nested Clink instance. - Fixed some input keys accidentally handled by the OS after certain Lua code is run.
- Fixed #124;
onfiltermatches()
receives one fewer matches than it should. - Fixed #123; Failed to inject (Host validation failed).
- Fixed #117; Setup causes "System Error".
.v1.2.9 up top
- Added detection for possible antivirus interference when injecting Clink.
- Ignore duplicate scripts paths when loading scripts.
- Fixed #118; inputrc is not read from state directory (regression introduced in v1.0.0).
.v1.2.8 up top
- Fixed
...\
or.../
to change directories (path separator after several dots). - Fixed
/dirname/
to change directories (forward slashes when a directory is the only thing in the input line). - Fixed #114; "Clink already loaded in process" error when autorun is installed for both Current User and All Users.
- Fixed #113; forward slash translation didn't work with the
cd
command.
.v1.2.7 up top
- Fixed #113;
clink.slash_translation()
had been removed (regression introduced in v1.0.0).- The new
match.translate_slashes
setting controls the default behavior for slash translation for completion matches. - The new
clink.translateslashes()
API can override slash translation for completion matches (andclink.slash_translation()
is supported for backward compatibility).
- The new
.v1.2.6 up top
- Fixed tilde expansion for directory by itself; now
~\
can change the working directory to the~
directory. - Fixed pagination when displaying completions that take more than 1 line to display.
- Fixed inserting directory match completions when a Lua script didn't include a trailing path separator in the directory match.
- Fixed #111;
..
completion is different from bash (regression introduced in v1.0.0).
.v1.2.5 up top
- Added
os.expandenv()
function to expand environment variables in a string. - Added
console.cellcount()
function to count the cells a string will use when displayed. - Added
console.plaintext()
function to remove ANSI escape codes from a string. - Clink now sets
%=clink.bin%
that points to the Clink binaries directory. This can be particularly useful for a portable installation of Clink so that scripts can find the Clink binaries directory and construct relative paths to other nearby files. - Clean up column alignment in
--help
texts. - Fixed
history.sticky_search
with anchored history search. - Fixed
clink inject --profile
to use correct log file name while initially injecting. - Fixed Clink autorun to be more compatible with Cmder (Cmder #2536).
.v1.2.4 up top
- Added support for Shift+Arrows to select text and typing to replace selected text.
- Added optional argument to
word_classifications:classifyword()
andword_classifications:applycolor()
to allow only applying color where another color hasn't yet been applied. - Fixed first Up after reusing a history line so that it gets the reused history line, rather than getting the previous history line.
- Fixed
add-history
command to not add blank lines to history. - Fixed
rl.setmatches()
(regression introduced in v1.1.26). - Fixed input coloring for
clink set
and any color setting name (regression introduced in v1.2). - Fixed potential crash with
clink history --session
. - Fixed Ctrl+D when
cmd.ctrld_exits
is disabled; it didn't exit, but it did still discard the input line and start a new prompt. - Fixed #107; autorun reports inject failures (regression introduced in v1.2.3).
- Fixed #106; history missing
--bare
option (regression introduced in v1.2.3).
.v1.2.3 up top
- Added
history.sticky_search
setting: when enabled, reusing a history line does not add the reused line to the end of the history, and it leaves the history search position on the reused line so next/prev history can continue from there (e.g. replaying commands via Up several times then Enter, Down, Enter, etc). - Added failure reporting and logging when
clink inject
fails. - Added
--unique
flag for use withclink history compact --unique
to remove duplicate entries from the history list. - The
clink-popup-complete
command now matches wildcards. - Restored the Ctrl+Alt+U key binding from v0.4.9 (moves the current working directory up one level).
- Fixed searching for inputrc files to also search in the profile directory (regression introduced in v1.0.0).
- Fixed incremental search in the History popup list to search in reverse order (bottom to top).
- Fixed
clink-popup-history
to set the history search position like other history search commands do, so that it plays well with thehistory.sticky_search
setting.
.v1.2.2 up top
- Added
%CLINK_HISTORY_LABEL%
environment variable to use a different master history file (fixes #99).
.v1.2.1 up top
- Added Troubleshooting Tips section in the documentation.
- Added backward compatibility for
clink set
with v0.4.9. Old setting names and values are not documented, but are automatically mapped to the appropriate new setting(s). This was done so that suggestions in old web sites and posts can usually continue to work, to reduce confusion and support burden. - Fixed #97; VS2017 error C2039: 'min': is not a member of 'std'.
- Fixed #96; wrong setting string (the name of a setting was accidentally truncated).
- Fixed some slightly inaccurate/incomplete migration from old settings to new settings.
.v1.2 up top
- First official release from chrisant996/clink fork.
.v1.1.49 up top
- Added
clink.classifier()
to enable coloring the input line independently from argmatchers. - Added
word_classifications:applycolor()
to apply SGR escape codes anywhere in the input line. - Removed
word_classifications:iswordclassified()
. - Fixed the Product Version string in the binary file version resources.
.v1.1.48 up top
- Added
clink.getansihost()
function to get Clink's best guess who will process ANSI escape codes (can be useful for avoiding 256 bit and 24 bit color codes, for example). - Added detection for being hosted in ConsoleZ.
- Fixed #20;
set /p VAR=""
shows the normal command prompt text instead of empty prompt text.
.v1.1.47 up top
- Added default key binding for Ctrl+Space to invoke
old-menu-complete
, which is the most similar to CMD's standard Tab behavior. - Fixed
search-ignore-case
config variable to be on by default.
.v1.1.46 up top
- Added
rl.setvariable()
to temporarily override the value of a Readline config variable. - The completion commands now also expand tilde by itself (
~
), in addition to tilde followed by a path separator (~\etc
). - Fixed #94; setting
history.save
to False also disables interactive history in subsequent sessions.
.v1.1.45 up top
- Fixed #93; stdout is sometimes broken by Cmder init.bat.
.v1.1.44 up top
- Added
clink.getsession()
. - Added
%CLINK_NOAUTORUN%
which overrides automatic inject when Clink is installed for autorun. - Fixed #92;
clink-popup-history
and similar commands not working with ConEmu and Cmder (regression introduced in v1.1.25).
.v1.1.43 up top
- Added
clink history --diag
flag that prints diagnostic information while performing history operations. - Minor optimization in
clink history
when printing the full list of history items. - Fixed
clink history compact
so it actually performs compaction.
.v1.1.42 up top
- Added
clink history --bare
flag to omit history item numbers. - Added several Lua functions:
io.popenrw()
is likeio.popen()
, but returns both a read file handle and a write file handle (see documentation for important usage warning).os.createtmpfile()
creates a unique named temporary file, with control over the prefix and suffix and path.os.getfullpathname()
to get the full path name for a file.os.getlongpathname()
to get the long path name for a file.os.getshortpathname()
to get the 8.3 short path name (if available) for a file.
- Improved argument validation for Clink's Lua APIs. This could expose bugs in existing scripts, so there is also a
lua.strict
setting that can be disabled to revert back to loose argument validation. - Updated documentation.
- Fixed
clink history compact
so that it forces compaction as intended. - Fixed completion for
clink set
so that filename completion works in string settings. - Fixed backwards return value from
rl.invokecommand()
. - Fixed console input/output modes across "luafunc:" key bindings, in case the Lua functions spawn a process that alters the console mode without restoring it.
.v1.1.41 up top
- Added
terminal.adjust_cursor_style
setting as a workaround to avoid interfering with the Windows 10 Cursor Shape console setting. There are several trade-offs, though. - Added
rl_buffer:refreshline()
function to redraw the input line, e.g. in case something has written over it. - Added
os.getpid()
function to get the process ID, intended mainly to help salt unique resource names. - Added
clink.onfiltermatches()
so scripts can register a callback function to run after Clink generates matches and before it displays them.
.v1.1.40 up top
- Added a group of
clink-complete-numbers
commands that do completion for numbers from the console screen, bound to Ctrl+Alt+N by default. - Added
rl.getlastcommand()
function that returns the name of the last command invoked by key bindings. - Fixed sort order in Alt+H for the newly supported key bindings (that were added in v1.1.39).
- Fixed Ctrl+Space (regression introduced in v1.1.39).
- Fixed various Ctrl+Shift+whatever combinations (regression introduced in v1.1.39).
- Fixed
rl.setmatches()
when the input line is not empty andclink.colorize_input
is enabled.
.v1.1.39 up top
- Added support for many more key bindings, such as Ctrl+Shift+Letter keys.
- Added
terminal.differentiate_keys
setting that when enabled allows binding Ctrl + H or I or M or [ separately from Backspace, Tab, Return, or Escape. - Removed
terminal.modify_other_keys
setting and made it always enabled. - Changed
terminal.use_altgr_substitute
to be disabled by default so that Ctrl+Alt key bindings can work by default on keyboards with AltGr. - Changed output from
clink echo
so it's directly usable in the inputrc files. - Fixed
terminal.use_altgr_substitute
to only affect AltGr substitute key combinations (it had always broken the RightAlt key in general on other keyboard layouts). - Fixed a benign issue with the console input mode in
clink echo
.
.v1.1.38 up top
- Fixed #84; added
terminal.use_altgr_substitute
setting. - Fixed #80; clink.log is not deleted when Cmder injects Clink.
.v1.1.37 up top
- Fixed copy to clipboard (it never cleared the clipboard!).
- Fixed #82; added two new
clink.paste_crlf
modes:ampersand
replaces newlines with ampersands, andcrlf
pastes newlines as-is and executes any commands ending in a newline. - Fixed #69; space in the prompt disappears after enter echo: added support for CJK codepages.
.v1.1.36 up top
- Fixed #79; Issue with United States - international keyboard layout (regression introduced in v1.1.0).
- Fixed #78; crash when history file contains a line longer than 8192 characters (regression introduced in v1.1.2-alpha).
.v1.1.35 up top
- Fixed when the
mark-directories
inputrc variable isoff
(regression introduced in v1.1.1-alpha). - Fixed Lua reading from stdin, especially in the Lua debugger (regression introduced in v1.1.25).
- Fixed exponential cost performance bug in Readline when removing duplicate matches.
.v1.1.34 up top
- Fixed copying to clipboard (CF_UNICODETEXT was put on the clipboard correctly, but CF_TEXT was empty and should have been omitted to let Windows automatically convert it from the Unicode text).
.v1.1.33 up top
- Make the "replacing arglink" warning message a little more informative, and write a lua traceback to the Clink log file.
- Fixed #77; with ConsoleZ scrolling does not always work.
- Fixed #76; cannot
cd
up multiple directories normally.
.v1.1.32 up top
- Added support for non-standard escape codes to set the window title or print environment variables. Depending on the
terminal.emulation
setting, the behavior is slightly different. Whenemulate
Clink processes the escape codes. Whennative
with ConEmu (and Clink) the escape codes are passed to ConEmu, except that Clink processes the environment variable codes in prompt strings. Whennative
with other terminals, Clink preprocesses the title and environment variable escape codes in prompt strings, but passes the escape codes to the terminal outside of prompt strings. - Fixed #67; AutoRun interferes with Cmder.
.v1.1.31 up top
- Fixed #74; clink gets confused by non-standard ConEmu escape codes.
- Fixed #73;
exec.space_prefix
and other settings defined in Lua scripts don't take effect until second input line (regression introduced in v1.1.4).
.v1.1.30 up top
- Fixed history compacting on x86 (regression introduced in v1.1.2-alpha).
.v1.1.29 up top
- Added
clink installscripts
andclink uninstallscripts
to make it easy for package managers like Scoop to install/uninstall script packages for use with Clink. The installed script paths are stored in the registry for the current user. - Fixed
bold
vsbright
colors to more accurately follow generally accepted ANSI escape code conventions:- Renamed
dim
tonobold
for clarity (thoughdim
is still recognized for backward compatibility). bold
adds intensity to a non-intense color (e.g.cyan
which is 36).nobold
removes intensity added bybold
(e.g.1;36
becomes36
), but does not remove intensity from an explicit intense color (such asbright cyan
which is96
).
- Renamed
- Fixed support for
--file=
flags in argmatchers. - Fixed match display filtering on the first try for a word (regression introduced in v1.1.19).
- Fixed the
clink --profile
flag (regression introduced in v1.1.10). - Fixed
clink info
to accurately report the script dirs (it didn't account for theclink.path
setting correctly).
.v1.1.28 up top
- Renamed the
log.rl_terminal
setting todebug.log_terminal
; it has already been repeatedly very useful in multiple was since it was added, so it stays. - Fixed #70; ctrl+c not working (regression introduced in v1.1.25).
.v1.1.27 up top
- Added
color.argmatcher
setting which, when set, is used to color a command name if it has an associated argmatcher (this supersedescolor.cmd
,color.doskey
, andcolor.input
). By default it's not set. - Added
log.rl_terminal
setting which logs all terminal input and output for Readline (this setting may be renamed or removed in the future).
.v1.1.26 up top
- Added
rl.invokecommand()
which can invoke a Readline command from inside a "luafunc:" key binding. - Added
rl.setmatches()
which can override match completions from inside a "luafunc:" key binding. - Worked around UTF8 key binding problem with Readline which had been causing some meta key bindings (M-x, M-C-x, etc) to sometimes produce garbled key bindings and garbled entries in
clink-show-help
(Alt+H). - Fixed crash if "luafunc:" key binding macro refers to a symbol that doesn't exist.
.v1.1.25 up top
- Added
clink-find-conhost
command that, when in a default (conhost) console window, is equivalent to picking "Find..." from the system menu. - Added
clink-mark-conhost
command that, when in a default (conhost) console window, is equivalent to picking "Mark" from the system menu. clink-copy-word
now copies the current word by default, but copies the nth word if a numeric argument is entered (see "Readline Arguments" in the Readline manual).- Fixed match display filtering to not exceed the screen width (regression introduced in v1.1.12).
- Fixed multi-key sequences; in some cases it could get confused about whether an input key is part of a multi-key binding sequence (regression introduced in v1.1.1-alpha).
- Fixed stray input processing by conhost (holding Ctrl+A or Ctrl+F or etc could accidentally trigger conhost's shortcut keys).
- Fixed popup window location and size when using Windows Terminal.
- Fixed input coloring after
operate-and-get-next
; also fixes brief flicker of incorrect coloring whenever the input line is modified.
.v1.1.24 up top
auto
forterminal.emulation
now uses native VT support on Windows 10 build 15063 and higher, unless the HKCU\Console\ForceV2 regkey is 0.- Special quote handling now enables
"dir\"fi
to complete to"dir\file"
. CMD simply strips quotes during completion, and now Clink behaves similarly. - Breaking Change:
line:getword()
andline:getendword()
now strip quotes from the word. This should generally automagically make existing match generators work even with embedded quotes, but there's a chance that some match generator might need to be updated. This seems like a reasonable compromise, given the general benefit purchased by this breaking change. os:globdirs()
andos:globfile()
strip quotes from the globpattern in order to behave more like CMD. Embedded quotes are nonsensical and the intended interpretation is clear, so the APIs now help out with that.- Fixed #66; crash when injecting into 32 bit cmd (regression introduced in v1.1.21).
- Fixed #64; wrong cursor position when PROMPT contains BEL character.
- Fixed #62; argmatchers should color
-x:"foo"
as a flag if-x:
is a flag. - Fixed #61; argmatchers should not handle completion for text immediately following
-flag:
. Instead it always uses file completion. A custom generator can be used to override that behavior. - Fixed #60; completion fails with multiple slashes.
- Fixed completion in some circumstances. Readline and Clink didn't always agree on where the word breaks were; now Clink always tells Readline where the word breaks are (so that completion, input colorization, and lua scripts can all work properly and consistently).
- Fixed 256 color ANSI codes.
.v1.1.23 up top
- Fixed #57; slashes not normalized in some cases.
- Fixed #45; interaction between
history.dupe_mode
=erase_prev
andhistory.shared
=false
. - Fixed
menu-complete-wraparound
when off and there's only 1 match.
.v1.1.22 up top
- Added
menu-complete-wraparound
(on by default) that controls whether completion commands wrap around when cycling past an end (affects popup windows as well). - Fixed match completion getting stuck (regression introduced in v1.1.19).
- Fixed active mark region so it gets deactivated appropriately (it wasn't hooked up fully for Readline's callback mode, which is the mode Clink uses).
- Fixed
clink-show-help
(Alt+H) so it's able to listC-@
bindings. - Fixed inconsistent mark color.
.v1.1.21 up top
- Added
clink.oninject()
so scripts can register a callback function to run when Clink is injected into CMD. - Added
console.linehascolor()
function that returns whether the specified line contains any of the specified colors. - Added
console.findprevline()
andconsole.findnextline()
functions that can search backwards or forwards for text and/or colors in the screen buffer. Regular expressions may be used. - Fixed doskey alias parsing for match generators and input line coloring (Clink had been using slightly different parsing rules than CMD does).
- Fixed the "-- More --" prompt while listing key bindings; Esc didn't quit, and unexpected keys weren't ignored.
.v1.1.20 up top
- Now you can bind Lua functions to keys via "luafunc:" macros! Added new
rl_buffer
type that gets passed to the Lua function. - Added a group of
console
Lua APIs intended mainly for use by Lua function key bindings (e.g.console.scroll()
). - Added
string.equalsi()
function that performs a case insensitive UTF8 comparison of two strings. - Added
string.matchlen()
function that compares two UTF8 strings and returns how many characters match at the beginning, or -1 if the entire strings match. It respects thematch.ignore_case
andmatch.ignore_accent
settings. - Added
path.toparent()
function that adjust the input string by moving up one directory level. - Added
clink.onendedit()
so scripts can register a callback function to run when editing finishes (e.g. Enter is pressed). If desired, the function can even change the input text. This is very powerful, and should be used carefully. - Changed
os.getbatterystatus()
to return a table with the battery status details, rather than four separate return values. - Fixed the
doskey.enhanced
setting to not expand doskey aliases when preceded by a space. However, a doskey alias after a&
or|
command separator needs to be preceded by two spaces to avoid expanding it. That's soalias & alias
expands both, andalias & alias
expands neither; while the rules are more complicated to explain, they make more sense visually. - Fixed environment variable completion (regression introduced in v1.1.19).
- Fixed Cmder startup (regression introduced in v1.1.17). Cmder expects to be able to replace Clink v0.4.9's clink.lua file, but there is no such thing anymore in newer versions of Clink. To be properly backwardly compatible with Clink v0.4.9 requires loading clink.lua (if it exists) from the first script directory listed by
clink info
, and ignoring clink.lua files in all other script directories.
.v1.1.19 up top
- Improved responsiveness while typing: matches are collected only on demand, instead of always while typing. This makes it possible to always support match completion for UNC paths.
- Fixed #50; Alt+H could warn about likely mistakes in key bindings.
.v1.1.18 up top
- The input text now has context sensitive coloring based on the argmatchers. It's on by default and can be turned off with
clink set clink.colorize_input false
. - Updated the Readline library to 8.1.
- Terminal emulation now supports the audible bell character.
- Fixed #48;
menu-complete
gets stuck. - Fixed #47; Alt+D erases history instead of word.
- Fixed #46; typing
..
in subdirectory of root doesn't work. - Fixed restoring color after pager when showing help.
- Fixed
clink set
match completions for color settings.
.v1.1.17 up top
- Added
os.getbatterystatus()
function that gets battery status information much faster than launchingwmic
. - Fixed #44; Path completion doesn't work with
cd /d
. - Fixed loading scripts to ignore loading clink.lua, so that loading scripts behaves like Clink v0.4.9.
.v1.1.16 up top
- Added
match.ignore_accent
setting (enabled by default) that ignores Latin alphabet diacriticals when completing matches (e.g.ä
matchesa
,ı
matchesi
,ł
matchesl
, etc). - Fixed #42; history lines are split on special characters.
- Fixed #41; Enable custom doskey handling of
..
and-
. - Fixed Readline bug inserting dir matches;
\win_ foo
(cursor at_
) would become\Windows\\_ foo
. - Fixed the
quoted-insert
command to insert just\x1b
when ESC is pressed.
.v1.1.15 up top
- Migrating settings now immediately writes a new settings file, instead of waiting until a setting is changed.
- Added support to detect when running in Windows Terminal and use native terminal support (which enables things like Xterm 256 and 24-bit color support).
- Added terminal emulation support for Xterm 256 and 24-bit color escape codes. Clink maps the specified color to the most similar color in the active 16 color palette (using the CIELAB color space). To get full support for 24-bit color, it's necessary to use ConEmu or Windows Terminal or a similar console host, or to set
terminal.emulation
tonative
(which isn't supported on some older Windows OS versions). - Allow doskey macros named
..
or-
, and also now doskey macros that resolve to..
or-
or a directory name will work (just like if the macro text had been typed at the Clink prompt). - Fixed compatibility problem with various scripts getting the %HOME% environment variable. Now if it isn't set, then Clink synthesizes %HOME% from %HOMEDRIVE% and %HOMEPATH% or from %USERPROFILE%.
- Fixed saving color settings to behave like other settings: only write a setting's value to the setting file if it differs from the default value.
- Fixed the
clink.print()
Lua function so it also works during loading scripts and during prompt filtering. - Fixed the Readline input text display getting garbled if the filtered prompt includes Xterm's OSC window title code (
\x1b]0;text\x07
). Clink doesn't support that escape code, but at no longer garbles the input text if that escape code is present.
.v1.1.14 up top
- Migrate settings and history from an old version of Clink, if present. This only happens if the new-version Clink settings or history files don't exist. (Deleting an existing new-version Clink settings or history file will cause migration to happen again.)
- Added
color.prompt
setting for backward compatibility with Clink v0.4.x.
.v1.1.13 up top
- Fixed
clink.arg.register_parser
backward compatibility.
.v1.1.12 up top
- Added
clink.ondisplaymatches()
as a replacement for the deprecatedclink.match_display_filter
. The new API is able to support popup list windows as well. - Speculative possible fix for #35 Crash when clink on clink.bat.
- Fixed #33; Tab autocomplete, auto-quoting paths doesn't seem to work as in Clink 0.4.9.
.v1.1.11 up top
- Changed to load Lua scripts only once per session, unless forced to reload them. This enables backward compatibility for things like z.lua which has certain features that rely on Clink only loading scripts once per session.
- Added
clink.onbeginedit()
so scripts can register a callback function to run each time the edit prompt is activated. - Added
lua.reload_scripts
setting to optionally force reloading Lua scripts each time the edit prompt is activated. - Added
color.message
setting for the Readline message area color (e.g. the search prompt message or digit argument prompt message, etc). - Fixed stray sticky
=
appended to completions after typingset
and then typing a different command.
.v1.1.10 up top
- Fixed #32; hooking
ReadConsoleW
on Windows 7.
.v1.1.9 up top
- Added backward compatibility for
clink.match_display_filter
. The clink-completions/git.lua script uses it a lot, and that should all be working now. settings.add
adds a color setting when the type is string and the name starts with "color.".settings.get
now has an extra parameter to request the user friendly color name when getting a color setting.- Added
clink.version_encoded
variable with the Clink version number as MMmmmpppp (e.g. v1.1.9 is10010009
) to make it easy for scripts to check for feature availability. - The
clink info
command now shows Lua script paths as well. - Fixed backward compatibility for loading scripts from the profile directory (if
clink.path
isn't set, then load scripts from the DLL directory and the profile directory). - Fixed some
color.input
bleed through to other things (introduced in v1.1.5). - Fixed scroll commands (regression introduced by input line color in v1.1.5).
- Fixed horizontally sorted match display and re-enabled the performance fix from v1.1.4.
- Fixed wildcard evaluation with non-file and non-directory matches (e.g. a branch name
origin/master
accidentally didn't matchor
or*ma
because of the/
). - Fixed sort order of
foo\
vsfoo.bar\
when displaying matches or using themenu-complete
family of commands. - Fixed potentially-missing trailing path separator when
menu-complete
completes a directory match (regression introduced by wildcard matching in v1.1.5). - Other obscure minor fixes.
.v1.1.8 up top
- Fixed file match completions when an argmatcher only generates flag matches.
- Fixed automatic inferring whether Readline should use filename completion and/or display rules (regression introduced by backward compatibility in v1.1.3-alpha).
- Fixed backward compatibility for
clink.find_files()
andclink.find_dirs()
(regression introduced by performance improvement in v1.1.7).- Ignore extra arguments after the first one (the performance improvement in v1.1.7 revealed that some scripts call
clink.find_files()
with extra invalid arguments; e.g. clink-completions/modules/matchers.lua). - Don't append a trailing path separator on directory names returned by these functions (the new
os.globfiles()
andos.globdirs()
functions do, but the oldclink.find_files()
andclink.find_dirs()
functions should not).
- Ignore extra arguments after the first one (the performance improvement in v1.1.7 revealed that some scripts call
- Fixed backward compatibility for coloring matches (regression introduced by backward compatibility changes in v1.1.4).
.v1.1.7 up top
- Performance improvement when displaying matches: When enumerating files and dirs, the
os.globfiles
andos.globdirs
functions have all the info about each file. Now they can return that info in a table. This frees the match display function from needing to do any further file system IO. The performance boost is noticeable. - Rewrote the color settings: the .fg and .bg sub-settings are gone, and the main setting now uses a more natural syntax (e.g.
clink set color.input bright yellow
orclink set color.modmark bright cyan on blue
). - Added "cmd" match type for shell (CMD.EXE) command completions.
- Added VT emulation for the reverse video SGR parameters.
- Fixed tab completion for
clink set setting
, and also handle the new color setting syntax. - Fixed confusing behavior if multiple scripts try to add settings with the same name (now the first one succeeds and the rest report errors).
.v1.1.6 up top
- Hooked up tilde completion in the
cd
,md
, andrd
command argmatchers. - Hooked up tilde completion with the
exec.enable
setting ("~\pro" matches "C:\Users\myusername\program.exe"). - When
terminal.emulation
isauto
, now it also detects ANSI{32|64}.DLL just like Clink 0.4.8 did.
.v1.1.5 up top
- The
menu-complete
family of commands now support matching?
and*
wildcards when thematch.wild
setting is enabled. - Added
colour.input
andcolour.modmark
settings for coloring Readline's input line. - Added
clink.upper()
Lua function, and bothclink.lower()
andclink.upper()
are properly UTF8 aware now. - Added
clink-copy-word
command that copies the word at the cursor to the clipboard. - Added
clink.promptfilter
setting to control whether to filter the prompt with Lua scripts. - Renamed
terminal.emulate
setting toterminal.emulation
. - Improved executable file extension logic to consistently use %PATHEXT% (and efficiently).
- Improved file extension logic (e.g. "file.foo bar" has no extension because of the space).
- Updated arg matcher for
clink
itself (was missing some flags). - Changed
colour.hidden
setting to not be set by default. - Fixed #28; Tab completion for "~" does not work.
- Fixed #25; Unicode surrogate pairs (and emoji) input isn't working -- Microsoft Terminal renders the text correctly, but ConEmu and the default conhost still don't (and that isn't a Clink issue).
- Fixed screen size bug in Readline on Windows.
- Fixed the backwards values in the
terminal.emulation
setting. - Fixed
....
so it works properly again. - Fixed case sensitive sorting of matches.
- Fixed script error when %PATHEXT% is empty.
- Fixed the
exec.cwd
Clink setting to default to true, so that the default behavior is consistent with how v0.4.x behaved. - Fixed the
cd
,md
,rd
, etc argmatchers to only match one argument to be consistent with the actual command syntax.
.v1.1.4 up top
- Automatically detect when running inside ConEmu and disable Clink's Virtual Terminal emulation.
- Added
search-ignore-case
inputrc variable that makes the history search commands case insensitive. - Suppress adding a space after completing a flag match that ends with
:
or=
(e.g.msbuild -maxCpuCount:
). - Report any errors while loading Lua scripts.
- Report an error if a Lua script tries to add a flag string that begins with a letter.
- Fixed slow printing of possible matches. Readline is inefficient about emitting output, so Clink supplies a custom implementation.
- Fixed some bugs in auto detection of flag prefix characters.
- Fixed backward compatibility for flags, and for args when merging two parsers by calling
clink.arg.register_parser('foo')
multiple times for the same command string. - Fixed truncated message when the last line of a prompt exceeds 128 characters.
- Fixed abort (Ctrl+G or Esc) in non-incremental history search mode.
- Fixed saved values for settings added by Lua scripts; now the saved value is available to the script immediately on adding the setting, and saved values are retained even if the setting isn't always added by the script.
- Fixed (and documented) shorthand form for defining an argmatcher.
- Fixed length of colored match prefix after a path separator.
- Fixed normalizing a slash by itself (
command /
mustn't becomecommand \
since that can interfere with completing flags). - Fixed the
completion-auto-query-items
inputrc variable. - Fixed the key binding list to correctly respect
completion-display-width
. - No visible effect yet: internal change that parses the input line to identify colors to use for each word (command, argument, flag, etc), but the colors aren't yet applied to the input line.
.v1.1.3-alpha up top
- Fixed argmatcher lookup to be more strict, like in Clink 0.4.9 (match exact names, or name plus an extension from %PATHEXT%).
- Backward compatibility:
- Most things should work now.
- Dropping the new Clink on top of the vendor\clink directory in Cmder seems to work -- but make a backup before you try this at home!
- API changes:
- Added
log.info()
function. - Added Clink version numbers in
clink.version_major
, etc. - Added
_argmatcher:getwordbreakinfo()
callback; removed_argmatcher:setprefixincluded()
(it was a mess, and it was new to v1.x, so there's no compatibility concern with removing it). - Deprecated
_argmatcher:setflagprefix()
; now it happens automagically when using_argmatcher:addflags()
. - Introduced several deprecated functions to support backward compatibility.
- Added
- Improvements to Lua debugger:
- Added
lua.traceback_on_error
,lua.break_on_error
, andlua.break_on_traceback
settings to make debugging script errors easier. - Made
pause()
consistent about pausing in the caller (rather than sometimes inside the pause command itself). - The debugger automatically shows the stack trace when entering debug mode, and on every pause.
- Show 3 lines of source context by default.
- The help list is sorted now.
- Fixed the
set
command in the debugger to behave as documented.
- Added
.v1.1.2-alpha up top
- Documentation is mostly updated; just the argmatcher Lua API and Clink command line options are left to be documented.
- Added
history.max_lines
setting that controls how many lines of command history to save (1 to 50000, default is 2500). - Added
readline.hide_stderr
setting that can suppress stderr output from the Readline library. - For backward compatibility with 0.4.8,
clink_inputrc
files are loaded as well. - Lua script API changes:
addmatch()
in Lua scripts takes an optional match type argument.- Removed
displayable
,aux
, andsuffix
fields in matches. - Revert the change to disallow mixing file/directory/symlink with other match types (it broke the tests and certain completion scenarios).
- Fixed issues:
- Other fixes:
- There should be no more problems running on Windows Insider builds because Clink now uses Detours for hooking APIs.
- Fixed crash in
insert-completions
due to heap failure (introduced by the performance changes for displaying matches). - Fixed
clink
andhistory
built-in aliases (solve glitchy path problem). - Fixed scrolling to top of screen buffer.
- Fixed env var and
set
completions. - Fixed
tilde-expand
for quoted text. - Fixed Esc in Readline's digit argument input mode (it doesn't try to cancel the mode, because that's not how Readline is documented to work).
- Fixed exit code from some
clink
command line options.
- Set locale to UTF8 much earlier to avoid quirky behavior early in script processing.
.v1.1.1-alpha up top
- Exclusively use Readline's completion implementation. This (with fixes and enhancements in Readline itself) makes the completion experience much nicer and more sophisticated, and removes a lot of code that was added in v1.0.0a0.
- Exclusively use Readline's key binding implementation. This makes it possible to have a single consistent way to set key bindings (inputrc) and for
clink-show-help
to list all key bindings, and removes a lot of code that was added in v1.0.0a0. - Converted all of Clink's internal key behaviors to be implemented as commands that can be bound in the inputrc file.
- Rewrote and refactored the pagination routine to be used in multiple places.
- Fixed prompt filtering to correctly use the specified priority order.
- Readline library:
- Updated the Readline library from v6.2 to v8.0. This picked up lots of bug fixes and new capabilities (for example colored completions).
- Changed Readline to support backslash as a path separator.
- The pager prompt in Readline is optionally colored, controlled by the
colour.interact
Clink setting. - Added
completion-auto-query-items
config variable (on by default) which asks whether to list possible matches when the number of lines listed will fill one screen page. - Added
history-point-at-end-of-anchored-search
config variable in inputrc to make the cursor point behave like 4Dos/4NT/TakeCommand when searching forward and backward through command history. - Fixed prev history at top of history.
- Fixed to get the current values of environment variables when needed, rather than always getting the value from whenever Clink was started.
- Fixed coloring directory completions.
- Fixed
menu-complete
for\dir
and.
and..
. - Fixed slow performance when displaying matches. Readline was calling stat() at least once per match (!!). A new match type field enables faster performance, coloring readonly and hidden file matches, applying filename completion rules only to filenames (vs branch names or other text strings), correct match de-duplication, and more. The Lua match APIs can supply the new match type.
- Fixed inserting a completion to happen as a single undo group.
- Fixed tilde to map to
%USERPROFILE%
instead of%APPDATA%
on Windows.
- Typing a directory by itself uses
cd /d
to change to the directory:- Typing a directory with a trailing path separator changes to the directory.
- Typing
..\
changes to the parent directory. - Typing
...
or....
etc moves up an extra parent directory level for each extra dot (2 dots move up one parent, 3 dots moves up two parents, etc). A trailing path separator is optional when there are more than 2 dots. - Typing
-
orcd -
orchdir -
changes to the previous directory.
- Commands that are new, enhanced, or fixed:
- Added
add-history
andremove-history
commands (similar to 4Dos/4NT/TakeCommand). - Got the
menu-complete
,menu-complete-backward
, andold-menu-complete
commands working (they never worked properly before in Clink).- Also added a corresponding
old-menu-complete-backward
command for reverse order. - All of the
*-menu-complete-*
commands support wildcards (*
and?
).
- Also added a corresponding
- Added
clink-show-help
command (Alt+H). The help now lists all key bindings, and it shows user-friendly key names (likeA-Up
orC-x,C-r
orC-S-PgUp
orA-C-S-F3
). - Added
clink-popup-completions
command that shows a popup window listing possible completions. Enter inserts the highlighted completion. - Added
clink-popup-directories
command that shows a popup window listing recent directories. Enter changes to the highlighted directory, or Shift+Enter inserts the highlighted directory in the editing line (or Ctrl+Enter). - Added
clink-popup-history
command that shows a popup window listing command history. Enter executes the highlighted command, or Shift+Enter jumps to the highlighted command in the history (or Ctrl+Enter). - Added
clink-scroll-lineup
,clink-scroll-linedown
,clink-scroll-page-up
,clink-scroll-page-down
,clink-scroll-top
, andclink-scroll-bottom
commands that do what it looks like they'd do and are bound to the keys it looks like they'd be. - Added
clink-expand-doskey
command (Ctrl+Alt+f) that expands the current line according to the current doskey aliases. - Added
clink-expand-env-var
command (Ctrl+Alt+e) that expands the environment variable at the cursor point. - Added
clink-exit
command (Alt+F4) that exits CMD.
- Added
- Fixed keyboard input issues:
- Esc is a bindable key now (
\e[27;27~
). - Added more bindable key combinations (run
clink echo
then press keys to see the key sequence to use in the inputrc file). - Ctrl+@ (NUL) didn't work.
- Ins toggles insert/overwrite mode.
- Unbound keys are ignored now, instead of inserting gibberish characters (part of the terminal internal key sequence).
- Fixed input handling so the
quoted-insert
command can work properly. - Fixed Esc while searching.
- Fixed vi mode (was working in v0.4.9, but not in v1.0.x).
- Esc is a bindable key now (
- Fixed command history issues:
- The
dont_add_to_history_cmds
Clink setting is a space-delimited list of commands to not add to history. - Fixed bleeding between history banks.
- Fixed uninitialized variable that made history updates intermittently do nothing or corrupt the other history bank.
- Fixed output from
clink history
to convert to UTF16 when writing to the console (but write UTF8 when output is redirected).
- The
- Fixed terminal output issues:
- Added
terminal.emulate
Clink setting that controls whether Clink does VT emulation or passes all ANSI escape codes directly to the console host. For example, this lets the prompt and completion coloring take advantage of more sophisticated ANSI escape codes such as XTerm 256 color and 16 bit color support. - Added back support for the
prefer-visible-bell
config variable. - Fixed underline support.
- Fixed handling for UTF8 output from Readline.
- Fixed invisible cursor point in Lua debugger.
- Added
- Completions:
- Added
match.sort_dirs
Clink setting that specifies where to sort directories in the list of possible completions: before files, mixed in with files, or after files. - Don't attempt completing incomplete UNC paths: at least the
\\server\share\
path components are required (for anything shorter the OS APIs are guaranteed to fail, but will fail slowly). - Fixed sorting to use Unicode aware locale based sorting (like Windows does) instead of dumb UTF8 byte comparisons.
- Fixed arbitrary limit on completions (had been limited to 64KB worth of completions).
- Fixed quoting spaces in completions.
- Fixed to use the same list as CMD for characters that require quoting.
- Fixed normalizing UNC paths.
- Fixed volume relative completions (e.g.
x:foo
). - Disallow mixing file/directory/symlink with other match types. This was to avoid a confusing/malfunctioning case in match display and prefix highlighting.
- Added
- Fixed UTF8 encoding in various Lua functions.
- Fixed printing stderr output from Readline, Lua, and Clink.
- Fixed crashes and other failures when starting Clink in 32 bit CMD.
- Fixed some memory leaks that accumulated with each new line of input.
- Fixed prompt filtering API to be backward compatible with v0.4.9 scripts.
- Fixed Lua errors from
clink set
(it neglected to fully initialize Clink's Lua integration before loading Lua scripts). - Fixed UTF8 conversion bug that could truncate a string without fully converting it.
- Fixed serious rampant memory corruption bug in v1.0.x (not present in v0.4.9), which had been causing intermittent malfunctions and data corruption and crashes.
- Fixed multi-line doskey macros to show the prompt in between lines, like CMD does.
- Removed the 4096 byte limit on input.
- Renamed the Clink DLL back to what it was in v0.4.x, to fix compile time problems.
- Other fixed issues:
- mridgers #544 Clink v1.0.0.a1 doesn't support cyrillic characters keyboard input on Windows 10 with console V2.
- mridgers #543 Not compatible with Windows Insider Build 20150.
- mridgers #537 Clink breaks the CMDS tool.
- mridgers #520 Clink 1.0.0.a1 -
clink set history_io 1
Error. - mridgers #519 Clink v1.0.0.a1 -
-s|--scripts [path]
command line arg removed? - mridgers #516 Doskey $T not handled properly.
- mridgers #512 Command history missing in .history.
- mridgers #503 Keyboard shortcut for scrolling.
- mridgers #501 Ctrl+Backspace works now.
- mridgers #487 Clink breaks ConEmu-specific Escape codes.
- mridgers #480 History never saved.
- mridgers #465 Using LuaJIT (FFI).
- mridgers #456 Clear-screen not working properly when PROMPT is two lines long.
- mridgers #453 Wrong cursor position when a line contains non-printable characters.
- mridgers #442 Unable to paste more than 1024 characters using Ctrl+V.
- mridgers #422 Problem with filename modifiers.
- mridgers #420 Use NtSuspendProcess instead of CreateToolhelp32Snapshot to freeze the threads.
- mridgers #372 Provide a way to select a previous directory.
- mridgers #365 history-search behavior.
- mridgers #342 Clink_inputrc not being processed if it the clink_inputrc is a link (created via mklink).
- Fixed many other bugs.
.Releases from mridgers/clink original repo up top
.v1.0.0a1 (alpha test release) up top
- Improve terminal integration with the Readline library.
- Internal improvements to the built-in ecma48 terminal emulator.
- Fixed use after free in Doskey emulation.
- Fixed dash-dash flag completion.
- Search ancestors for a compatible target process (for when cmd.exe starts another process that subsequently starts clink; especially useful during development).
- Use clink/terminal's wcwidth() implementation.
- screen_buffer::set_cursor() should be relative to the visible area.
- Try to adjust the cursor position better when resizing the terminal.
- Some internal Lua functions needed the unquoted clink exe path.
- The origin path now affects the hash in the dll cache, to guard against directory moves.
- More code reorganization.
.v1.0.0a0 (alpha test release) up top
- Extensive code reorganization, refactoring, and rewriting -- multiple times -- almost everything was touched.
- OS integration:
- Fixed Doskey macros on Win8, and on Win10.
- Fixed
clink_x??.exe
startup stall on Windows 10. - Removed XP support. It doesn't load DLLs like Clink uses them.
- Removed Powershell support.
- Readline integration:
- Search for multiple places for [.|_]inputrc (fixes mridgers #258).
- Disabled Readline's completion code, and only use the clink alternative code.
- Removed redundant slash translation and shims to make it happen.
- Removed control of Readline's suffix appending and disabled it.
clink
commands and flags:- Changed
--cfgdir
to--profile
, it's no longer required, and added help about it. - Added a
--version
option to print Clink's version. - Added
clink info
to print information about Clink. - Added
clink echo
command to echo input key sequences to stdout. - Added
clink history
command (fixes mridgers #172). - Added
history
as an alias forclink history
. - Added internal
--list
flag toclink set
for match generation. - Removed
--scripts
argument (fixes mridgers #206). - Updated
clink autorun
command's help text.
- Changed
- Lua scripts:
- Prefer
userprofile
over other standard environment variables for where to look for lua scripts. - New API for argument style completion scripts.
- Refactored prompt filtering, and introduced new prompt filtering API.
- Refactored generating matches, and introduced new match generator API.
- Removed built in completions scripts for git, go, hg, and p4. There's better ones.
- Renamed many of clink's Lua functions.
- Moved functions from
clink
toos
in Lua. - Removed
clink.is_match()
in Lua; don't presume anything on anyone's behalf about matches. - Added some current dir functions in Lua.
- Added some env/dir functions in Lua.
- Exposed path manipulation functions to Lua.
- Embed the core Lua scripts instead of loading them from files.
- Prefer
- Terminal IO:
- Added a module for scrolling the screen.
- Rewrote the terminal emulation module, and all Readline IO goes through it.
- Use VT220-style control codes for special keys.
- If Alt is pressed send ESC in the input stream rather than setting meta bit.
- Replaced wcwidth() with a more complete and correct version.
- Settings:
- Added
clink_path
setting for where to look for lua scripts. - Added
match.ignore_case
setting. - Added
files.unc_paths
setting for optional matching from UNC paths. - Added a setting to skip adding lines that start with
history
. - Removed
esc_clears_line
setting. - Pasting CRLFs doesn't really make sense.
- Don't write out settings that are set to default.
- Added
- Make sure Ctrl-C doesn't modify history.
- Make a cached copy of Clink's DLL when injecting so as to not lock the master.
- Guard against Readline's writes to stderr.
- Remove
clink_inputrc_base
file and embed its content (fixes mridgers #257). - Include more metadata in the Clink's executables.
.v0.4.9 up top
- Fixed broken Doskey on Win10 (#438, #451)
.v0.4.8 up top
- Environment variable
clink_profile
overrides Clink's profile path (#390). - Load a clink_inputrc file from Clink's profile directory (fixes #406).
- Bug fixes;
- Redraw issues when prompts end in OSC ANSI codes (#387, #384).
- Fixed
clink autorun --help
crash.
.v0.4.7 up top
- Bug fixes;
- Sometimes autorun tries to run clink.exe (#374).
- Autorun would cause cmd.exe to return an error if it wasn't interactive (#373).
.v0.4.6 up top
- HOME is only set if it is currently unset.
- Readline can be initialised with .inputrc and _inputrc files too (#258).
- Bug fixes;
- Executable completion;
- Paths from PATH were checked twice.
- Incorrect results were returned for words ending in
.
or-
. - Directories . and .. were incorrectly displayed.
- Fixed a crash if .bat script's stdout is redirected (#366).
- Occasional crash when injecting Clink (#351).
- Display errors;
- When editing near the window's right-hand edge (#347).
- Double display of multi-line prompts when resizing the terminal (#352).
- Very rare wrap artefacts when making the terminal window larger.
- Doskey emulation (#344).
- Improved
clink autorun
help (#348). - Fixed launching Clink when clink.bat is renamed (#357).
- Executable completion;
.v0.4.5 up top
- Improved
clink autorun
. It now defaults to the Current User registry hive. clink set
gives more details for enumeration-type settings.- Tab completion for p4vc.
- New settings
history_expand_mode
to control history expansion in quotes (#317). - Bug fixes;
- Use full width of the terminal (#337).
- Fixed MinGW compile error (#335).
- Autorun now defaults to the current user's hive (#332).
- Creating clink.html no longer needs Pandoc, plus it looks a bit better (#331).
- Added settings to control history expansion (#326).
- Correct fallback when
use_altgr_substitute
is off (#325). - Load history prior to saving it on shutdown (#318).
- Added Shift-Tab documentation and menu completion example (#190).
- Added shim for backwards menu completion (#190).
- Input handling now outputs
\e`Z
for Shift-Tab (#190). - Updated Readme with current Premake info (#310).
- Guard against there being no buffer to read from (#304).
- Fixed artefacts when resizing conhost's buffer (#139).
- Clear remaining characters if scroll window was too small (#301)
- Escape % characters when expanding aliases (#280).
- Fixed leaking exception filters.
- Clearing the screen doesn't leave artefacts behind.
.v0.4.4 up top
- Completing .. behaves more like Bash (#277).
- Escape from yes/no question when Ctrl+C is pressed.
- Valid XP executables (#278, #289).
- Fixed n-th argument yank not working as expected (#254).
- Fixed prompt colours sometimes not working (#279, #286).
- Fixed
!0
causing Clink to crash. - Save/restore cursor position in case Readline moves it.
.v0.4.3 up top
- Localised Y/N when auto-answering "terminate?" prompt.
$*
would early out if there was no arguments.- Disable ANSI code support if third party provides it.
- Installer can now set %CLINK_DIR% to install location.
- Improved output from
clink set
. - Support for Windows 10 Technical Preview.
- Ctrl-L now scrolls last line to the top of the window rather than clearing.
- New option to control how newline characters are pasted to the line.
- New options to control history;
history_file_lines
- maximum lines saved to disk.history_ignore_space
- ignore lines prefixed with whitespace.history_dupe_mode
- how duplicate entries are handled.history_io
- load/save history from disk every line.
- Fixed nonfunctional numpad keys.
- Fixed missing WINCH signals if other processes resize the buffer.
- Support Alt codes sent from Conhost.
.v0.4.2 up top
- Prompt colouring no longer requires third party ANSI code utility.
- Override settings with environment variables prefixed with 'clink'.
- Ctrl-PgUp goes up a directory.
- Updated Go completions (by matrixik).
- Arguments to clink.arg.new_parser() now initialise parser's flags/args (from vladimir-kotikov).
- New clink.arg.add_flags() and clink.arg.add_arguments() functions.
- Removed footer and Alt-H tip for more succinct stdout output.
- Bug fixes;
- Windows XP works again.
- Fixed race condition in lua_execute().
.v0.4.1 up top
- Bug fixes;
- Various Unicode fixes causing corrupt environment variables.
- Fixed thread resume/suspend causing rare system-wide deadlock.
- Fixed incorrect translation of suffixed slash when completing flags.
- Add
--nolog
argument to disable file logging. Fix #187 Fix #154 - Added missing escape sequences from doskey emulation.
- Reinstated unix-kill-line key binding.
- Mapped PgUp/Down to search history using line typed so far.
- Added documentation covering escape codes for special keys.
- Added support for Windows' AltGr substitute Ctrl-Alt.
- Support for Readline's 'menu' style completion (see docs).
.v0.4 up top
- New features;
- Better
clink.arg
API. Easier, more intuitive, and more powerful. - Whitespace prefix skips exec matching.
- Added a
set
verb to easily change settings from the command line. - Basic support for a shells other than cmd.exe.
- Completion for Go (contributed by Dobroslaw Zybort).
- Setting
exec_match_style
to -1 disables it entirely. - Make history persistence optional.
- Alias/doskey completion.
- Very basic support for Powershell.
- View cmd.exe's autorun entry without needing admin rights.
- Better
- New key bindings;
- Ctrl-Alt-C : Copy command line to the clipboard.
- Ctrl-Alt-E : Expand environment variable under cursor.
- Ctrl-Alt-U : "up directory" (formerly Shift-Up).
- Ctrl-U : Adds
..\
to the command line. - Alt-H : Shows active keymap's key bindings.
- New Lua functions;
- clink.execute().
- clink.get_host_process().
- clink.match_files().
- clink.match_words().
- clink.get_console_aliases().
- Lots of bug fixes, including;
- Better command extraction.
- Fixed cmd.exe command paging and Ctrl-C/Ctrl-Break handling.
- Multiple locale fixes.
- Use localised text for "Terminate batch job?" prompt.
.v0.3 up top
- Automatic answering of cmd.exe's "Terminate batch script?" prompt.
- Coloured prompts (requires ANSICON or ConEmu).
- Added Shift-Up keyboard shortcut to automatically execute
cd ..
- Mapped Ctrl-Z to undo, Microsoft style.
- Improved integration of Readline;
- New input handling code (Ctrl-Alt combos now work).
- An implementation of the Termcap library.
- Fully functional Vi-mode support.
- Support for resizable consoles.
- Line wrapping now works correctly (issue 50).
- Adjustable executable match style (issue 65).
- Improved environment variable completion.
- Added settings file to customise Clink.
- New Lua features and functions;
- Matches can now be filtered in Lua before they are display.
- clink.quote_split().
- clink.arg.node_merge().
- clink.get_screen_info() (issue 71).
- clink.split() (for splitting strings).
- clink.chdir().
- clink.get_cwd().
- Functions to query Clink's settings.
- New command line options;
--profile dir
to override default profile directory.--nohostcheck
disables verification that host is cmd.exe.--pid
specifies the process to inject into.
- Update Mercurial completion (issue 73).
- Start menu shortcut starts in USERPROFILE, like cmd.exe
- Zip distribution is now portable.
.v0.2.1 up top
- The .history file now merges multiple sessions together.
- Fixed missing y/n, pause, and other prompts.
- Fixed segfault in loader executable.
- Better ConEmu compatibility.
.v0.2 up top
- Basic argument completion for
git
,hg
,svn
, andp4
. - Traditional Bash clear screen (Ctrl-L) and exit shortcuts (Ctrl-D).
- Scrollable command window using PgUp/PgDown keys.
- Doskey support.
- Automatic quoting of file names with spaces.
- Scriptable custom prompts.
- New argument framework to ease writing context-sensitive match generators.
- History and log file is now saved per-user rather than globally.
- Improved Clink's command line interface (
clink --help
). - More reliable handling of cmd.exe's autorun entry.
- General improvements to executable and directory-command completion.
- Symbolic link support.
- Documentation.
- Windows 8 support.
- Improved hooking so Clink can be shared with other thirdparty utilities that also hook cmd.exe (ConEmu, ANSICon, etc.).
.v0.1.1 up top
- Fixed AltGr+<key> on international keyboards.
- Fixed broken completion when directories have a
-
in their name (Mark Hammond) - The check for single match scenarios now correctly handles case-insensitivity.
.v0.1 up top
- Initial release.
.License top
Clink is distributed under the terms of the GNU General Public License, version 3.
.Credits top
.Clink up top
Clink was originally built by Martin Ridgers (https://github.com/mridgers/clink).
Copyright (c) 2012-2018 by Martin Ridgers.
Clink has been forked and renovated by Christopher Antos (https://github.com/chrisant996/clink).
Portions Copyright (c) 2020-2024 by Christopher Antos.
.Libraries up top
GNU Readline library version 8.1 (https://tiswww.case.edu/php/chet/readline/rltop.html).
GNU Readline is distributed under the terms of the GNU General Public License, version 3.
Lua 5.2 (https://www.lua.org).
getopt library.
Copyright (c) 1997 Gregory Pietsch, placed in the public domain.
WildMatch library (https://github.com/davvid/wildmatch).
Licensed under the BSD License.
Includes test cases copied from git's wildmatch implementation, licensed under the terms of the GNU General Public License, version 2.
Detours library version 4.0.1 (https://github.com/microsoft/detours).
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.
Match completion display uses column width calculations from GNU coreutils ls.c.
Licensed under the terms of the GNU General Public License, version 3.
The Dracula color theme (https://draculatheme.com).
Copyright (c) 2018 Dracula Theme.
Licensed under the MIT License.
The Solarized color theme (https://ethanschoonover.com/solarized).
Copyright (c) 2011 Ethan Schoonover.
Licensed under the MIT License.
The Tomorrow color theme (https://github.com/chriskempson/tomorrow-theme).
Copyright (C) 2011 Chris Kempson.
Licensed under the MIT License.
Custom prompts included with Clink are based on some custom prompt themes for the zsh shell.
For details about the original prompt implementation for each one, refer to information at the top of each .clinkprompt file.
Clink documentation embeds the highlight.js library (https://highlightjs.org).
Highlight.js is released under the BSD License.
Clink documentation embeds SVG artwork for a link icon from Bootstrap.
Licensed under the MIT License.
Special thanks to Alexandra Barros and Matthew Wild for (https://code.matthewwild.co.uk/luatraverse).
Originally from (http://lua-users.org/lists/lua-l/2006-07/msg00110.html).
The script was very useful in tracking down dangling references.