/* ----------------------------------------------------------------------------1Copyright (c) 2021, Daan Leijen2This is free software; you can redistribute it and/or modify it3under the terms of the MIT License. A copy of the license can be4found in the "LICENSE" file at the root of this distribution.5-----------------------------------------------------------------------------*/6#pragma once7#ifndef IC_ISOCLINE_H8#define IC_ISOCLINE_H910#ifdef __cplusplus11extern "C" {12#endif1314#include <stddef.h> // size_t15#include <stdbool.h> // bool16#include <stdint.h> // uint32_t17#include <stdarg.h> // term_vprintf181920/*! \mainpage21Isocline C API reference.2223Isocline is a pure C library that can be used as an alternative to the GNU readline library.2425See the [Github repository](https://github.com/daanx/isocline#readme)26for general information and building the library.2728Contents:29- \ref readline30- \ref bbcode31- \ref history32- \ref completion33- \ref highlight34- \ref options35- \ref helper36- \ref completex37- \ref term38- \ref async39- \ref alloc40*/4142/// \defgroup readline Readline43/// The basic readline interface.44/// \{4546/// Isocline version: 102 = 1.0.2.47#define IC_VERSION (104)484950/// Read input from the user using rich editing abilities.51/// @param prompt_text The prompt text, can be NULL for the default ("").52/// The displayed prompt becomes `prompt_text` followed by the `prompt_marker` ("> ").53/// @returns the heap allocated input on succes, which should be `free`d by the caller.54/// Returns NULL on error, or if the user typed ctrl+d or ctrl+c.55///56/// If the standard input (`stdin`) has no editing capability57/// (like a dumb terminal (e.g. `TERM`=`dumb`), running in a debuggen, a pipe or redirected file, etc.)58/// the input is read directly from the input stream up to the59/// next line without editing capability.60/// See also \a ic_set_prompt_marker(), \a ic_style_def()61///62/// @see ic_set_prompt_marker(), ic_style_def()63char* ic_readline(const char* prompt_text);6465/// \}666768//--------------------------------------------------------------69/// \defgroup bbcode Formatted Text70/// Formatted text using [bbcode markup](https://github.com/daanx/isocline#bbcode-format).71/// \{7273/// Print to the terminal while respection bbcode markup.74/// Any unclosed tags are closed automatically at the end of the print.75/// For example:76/// ```77/// ic_print("[b]bold, [i]bold and italic[/i], [red]red and bold[/][/b] default.");78/// ic_print("[b]bold[/], [i b]bold and italic[/], [yellow on blue]yellow on blue background");79/// ic_style_add("em","i color=#888800");80/// ic_print("[em]emphasis");81/// ```82/// Properties that can be assigned are:83/// * `color=` _clr_, `bgcolor=` _clr_: where _clr_ is either a hex value `#`RRGGBB or `#`RGB, a84/// standard HTML color name, or an ANSI palette name, like `ansi-maroon`, `ansi-default`, etc.85/// * `bold`,`italic`,`reverse`,`underline`: can be `on` or `off`.86/// * everything else is a style; all HTML and ANSI color names are also a style (so we can just use `red`87/// instead of `color=red`, or `on red` instead of `bgcolor=red`), and there are88/// the `b`, `i`, `u`, and `r` styles for bold, italic, underline, and reverse.89///90/// See [here](https://github.com/daanx/isocline#bbcode-format) for a description of the full bbcode format.91void ic_print( const char* s );9293/// Print with bbcode markup ending with a newline.94/// @see ic_print()95void ic_println( const char* s );9697/// Print formatted with bbcode markup.98/// @see ic_print()99void ic_printf(const char* fmt, ...);100101/// Print formatted with bbcode markup.102/// @see ic_print103void ic_vprintf(const char* fmt, va_list args);104105/// Define or redefine a style.106/// @param style_name The name of the style.107/// @param fmt The `fmt` string is the content of a tag and can contain108/// other styles. This is very useful to theme the output of a program109/// by assigning standard styles like `em` or `warning` etc.110void ic_style_def( const char* style_name, const char* fmt );111112/// Start a global style that is only reset when calling a matching ic_style_close().113void ic_style_open( const char* fmt );114115/// End a global style.116void ic_style_close(void);117118/// \}119120121//--------------------------------------------------------------122// History123//--------------------------------------------------------------124/// \defgroup history History125/// Readline input history.126/// \{127128/// Enable history.129/// Use a \a NULL filename to not persist the history. Use -1 for max_entries to get the default (200).130void ic_set_history(const char* fname, long max_entries );131132/// Remove the last entry in the history.133/// The last returned input from ic_readline() is automatically added to the history; this function removes it.134void ic_history_remove_last(void);135136/// Clear the history.137void ic_history_clear(void);138139/// Add an entry to the history140void ic_history_add( const char* entry );141142/// \}143144//--------------------------------------------------------------145// Basic Completion146//--------------------------------------------------------------147148/// \defgroup completion Completion149/// Basic word completion.150/// \{151152/// A completion environment153struct ic_completion_env_s;154155/// A completion environment156typedef struct ic_completion_env_s ic_completion_env_t;157158/// A completion callback that is called by isocline when tab is pressed.159/// It is passed a completion environment (containing the current input and the current cursor position),160/// the current input up-to the cursor (`prefix`)161/// and the user given argument when the callback was set.162/// When using completion transformers, like `ic_complete_quoted_word` the `prefix` contains the163/// the word to be completed without escape characters or quotes.164typedef void (ic_completer_fun_t)(ic_completion_env_t* cenv, const char* prefix );165166/// Set the default completion handler.167/// @param completer The completion function168/// @param arg Argument passed to the \a completer.169/// There can only be one default completion function, setting it again disables the previous one.170/// The initial completer use `ic_complete_filename`.171void ic_set_default_completer( ic_completer_fun_t* completer, void* arg);172173174/// In a completion callback (usually from ic_complete_word()), use this function to add a completion.175/// (the completion string is copied by isocline and do not need to be preserved or allocated).176///177/// Returns `true` if the callback should continue trying to find more possible completions.178/// If `false` is returned, the callback should try to return and not add more completions (for improved latency).179bool ic_add_completion(ic_completion_env_t* cenv, const char* completion);180181/// In a completion callback (usually from ic_complete_word()), use this function to add a completion.182/// The `display` is used to display the completion in the completion menu, and `help` is183/// displayed for hints for example. Both can be `NULL` for the default.184/// (all are copied by isocline and do not need to be preserved or allocated).185///186/// Returns `true` if the callback should continue trying to find more possible completions.187/// If `false` is returned, the callback should try to return and not add more completions (for improved latency).188bool ic_add_completion_ex( ic_completion_env_t* cenv, const char* completion, const char* display, const char* help );189190/// In a completion callback (usually from ic_complete_word()), use this function to add completions.191/// The `completions` array should be terminated with a NULL element, and all elements192/// are added as completions if they start with `prefix`.193///194/// Returns `true` if the callback should continue trying to find more possible completions.195/// If `false` is returned, the callback should try to return and not add more completions (for improved latency).196bool ic_add_completions(ic_completion_env_t* cenv, const char* prefix, const char** completions);197198/// Complete a filename.199/// Complete a filename given a semi-colon separated list of root directories `roots` and200/// semi-colon separated list of possible extensions (excluding directories).201/// If `roots` is NULL, the current directory is the root (".").202/// If `extensions` is NULL, any extension will match.203/// Each root directory should _not_ end with a directory separator.204/// If a directory is completed, the `dir_separator` is added at the end if it is not `0`.205/// Usually the `dir_separator` is `/` but it can be set to `\\` on Windows systems.206/// For example:207/// ```208/// /ho --> /home/209/// /home/.ba --> /home/.bashrc210/// ```211/// (This already uses ic_complete_quoted_word() so do not call it from inside a word handler).212void ic_complete_filename( ic_completion_env_t* cenv, const char* prefix, char dir_separator, const char* roots, const char* extensions );213214215216/// Function that returns whether a (utf8) character (of length `len`) is in a certain character class217/// @see ic_char_is_separator() etc.218typedef bool (ic_is_char_class_fun_t)(const char* s, long len);219220221/// Complete a _word_ (i.e. _token_).222/// Calls the user provided function `fun` to complete on the223/// current _word_. Almost all user provided completers should use this function.224/// If `is_word_char` is NULL, the default `&ic_char_is_nonseparator` is used.225/// The `prefix` passed to `fun` is modified to only contain the current word, and226/// any results from `ic_add_completion` are automatically adjusted to replace that part.227/// For example, on the input "hello w", a the user `fun` only gets `w` and can just complete228/// with "world" resulting in "hello world" without needing to consider `delete_before` etc.229/// @see ic_complete_qword() for completing quoted and escaped tokens.230void ic_complete_word(ic_completion_env_t* cenv, const char* prefix, ic_completer_fun_t* fun, ic_is_char_class_fun_t* is_word_char);231232233/// Complete a quoted _word_.234/// Calls the user provided function `fun` to complete while taking235/// care of quotes and escape characters. Almost all user provided completers should use236/// this function. The `prefix` passed to `fun` is modified to be unquoted and unescaped, and237/// any results from `ic_add_completion` are automatically quoted and escaped again.238/// For example, completing `hello world`, the `fun` always just completes `hel` or `hello w` to `hello world`,239/// but depending on user input, it will complete as:240/// ```241/// hel --> hello\ world242/// hello\ w --> hello\ world243/// hello w --> # no completion, the word is just 'w'>244/// "hel --> "hello world"245/// "hello w --> "hello world"246/// ```247/// with proper quotes and escapes.248/// If `is_word_char` is NULL, the default `&ic_char_is_nonseparator` is used.249/// @see ic_complete_quoted_word() to customize the word boundary, quotes etc.250void ic_complete_qword( ic_completion_env_t* cenv, const char* prefix, ic_completer_fun_t* fun, ic_is_char_class_fun_t* is_word_char );251252253254/// Complete a _word_.255/// Calls the user provided function `fun` to complete while taking256/// care of quotes and escape characters. Almost all user provided completers should use this function.257/// The `is_word_char` is a set of characters that are part of a "word". Use NULL for the default (`&ic_char_is_nonseparator`).258/// The `escape_char` is the escaping character, usually `\` but use 0 to not have escape characters.259/// The `quote_chars` define the quotes, use NULL for the default `"\'\""` quotes.260/// @see ic_complete_word() which uses the default values for `non_word_chars`, `quote_chars` and `\` for escape characters.261void ic_complete_qword_ex( ic_completion_env_t* cenv, const char* prefix, ic_completer_fun_t* fun,262ic_is_char_class_fun_t* is_word_char, char escape_char, const char* quote_chars );263264/// \}265266//--------------------------------------------------------------267/// \defgroup highlight Syntax Highlighting268/// Basic syntax highlighting.269/// \{270271/// A syntax highlight environment272struct ic_highlight_env_s;273typedef struct ic_highlight_env_s ic_highlight_env_t;274275/// A syntax highlighter callback that is called by readline to syntax highlight user input.276typedef void (ic_highlight_fun_t)(ic_highlight_env_t* henv, const char* input, void* arg);277278/// Set a syntax highlighter.279/// There can only be one highlight function, setting it again disables the previous one.280void ic_set_default_highlighter(ic_highlight_fun_t* highlighter, void* arg);281282/// Set the style of characters starting at position `pos`.283void ic_highlight(ic_highlight_env_t* henv, long pos, long count, const char* style );284285/// Experimental: Convenience callback for a function that highlights `s` using bbcode's.286/// The returned string should be allocated and is free'd by the caller.287typedef char* (ic_highlight_format_fun_t)(const char* s, void* arg);288289/// Experimental: Convenience function for highlighting with bbcodes.290/// Can be called in a `ic_highlight_fun_t` callback to colorize the `input` using the291/// the provided `formatted` input that is the styled `input` with bbcodes. The292/// content of `formatted` without bbcode tags should match `input` exactly.293void ic_highlight_formatted(ic_highlight_env_t* henv, const char* input, const char* formatted);294295/// \}296297//--------------------------------------------------------------298// Readline with a specific completer and highlighter299//--------------------------------------------------------------300301/// \defgroup readline302/// \{303304/// Read input from the user using rich editing abilities,305/// using a particular completion function and highlighter for this call only.306/// both can be NULL in which case the defaults are used.307/// @see ic_readline(), ic_set_prompt_marker(), ic_set_default_completer(), ic_set_default_highlighter().308char* ic_readline_ex(const char* prompt_text, ic_completer_fun_t* completer, void* completer_arg,309ic_highlight_fun_t* highlighter, void* highlighter_arg);310311/// \}312313314//--------------------------------------------------------------315// Options316//--------------------------------------------------------------317318/// \defgroup options Options319/// \{320321/// Set a prompt marker and a potential marker for extra lines with multiline input.322/// Pass \a NULL for the `prompt_marker` for the default marker (`"> "`).323/// Pass \a NULL for continuation prompt marker to make it equal to the `prompt_marker`.324void ic_set_prompt_marker( const char* prompt_marker, const char* continuation_prompt_marker );325326/// Get the current prompt marker.327const char* ic_get_prompt_marker(void);328329/// Get the current continuation prompt marker.330const char* ic_get_continuation_prompt_marker(void);331332/// Disable or enable multi-line input (enabled by default).333/// Returns the previous setting.334bool ic_enable_multiline( bool enable );335336/// Disable or enable sound (enabled by default).337/// A beep is used when tab cannot find any completion for example.338/// Returns the previous setting.339bool ic_enable_beep( bool enable );340341/// Disable or enable color output (enabled by default).342/// Returns the previous setting.343bool ic_enable_color( bool enable );344345/// Disable or enable duplicate entries in the history (disabled by default).346/// Returns the previous setting.347bool ic_enable_history_duplicates( bool enable );348349/// Disable or enable automatic tab completion after a completion350/// to expand as far as possible if the completions are unique. (disabled by default).351/// Returns the previous setting.352bool ic_enable_auto_tab( bool enable );353354/// Disable or enable preview of a completion selection (enabled by default)355/// Returns the previous setting.356bool ic_enable_completion_preview( bool enable );357358/// Disable or enable automatic identation of continuation lines in multiline359/// input so it aligns with the initial prompt.360/// Returns the previous setting.361bool ic_enable_multiline_indent(bool enable);362363/// Disable or enable display of short help messages for history search etc.364/// (full help is always dispayed when pressing F1 regardless of this setting)365/// @returns the previous setting.366bool ic_enable_inline_help(bool enable);367368/// Disable or enable hinting (enabled by default)369/// Shows a hint inline when there is a single possible completion.370/// @returns the previous setting.371bool ic_enable_hint(bool enable);372373/// Set millisecond delay before a hint is displayed. Can be zero. (500ms by default).374long ic_set_hint_delay(long delay_ms);375376/// Disable or enable syntax highlighting (enabled by default).377/// This applies regardless whether a syntax highlighter callback was set (`ic_set_highlighter`)378/// Returns the previous setting.379bool ic_enable_highlight(bool enable);380381382/// Set millisecond delay for reading escape sequences in order to distinguish383/// a lone ESC from the start of a escape sequence. The defaults are 100ms and 10ms,384/// but it may be increased if working with very slow terminals.385void ic_set_tty_esc_delay(long initial_delay_ms, long followup_delay_ms);386387/// Enable highlighting of matching braces (and error highlight unmatched braces).`388bool ic_enable_brace_matching(bool enable);389390/// Set matching brace pairs.391/// Pass \a NULL for the default `"()[]{}"`.392void ic_set_matching_braces(const char* brace_pairs);393394/// Enable automatic brace insertion (enabled by default).395bool ic_enable_brace_insertion(bool enable);396397/// Set matching brace pairs for automatic insertion.398/// Pass \a NULL for the default `()[]{}\"\"''`399void ic_set_insertion_braces(const char* brace_pairs);400401/// \}402403404//--------------------------------------------------------------405// Advanced Completion406//--------------------------------------------------------------407408/// \defgroup completex Advanced Completion409/// \{410411/// Get the raw current input (and cursor position if `cursor` != NULL) for the completion.412/// Usually completer functions should look at their `prefix` though as transformers413/// like `ic_complete_word` may modify the prefix (for example, unescape it).414const char* ic_completion_input( ic_completion_env_t* cenv, long* cursor );415416/// Get the completion argument passed to `ic_set_completer`.417void* ic_completion_arg( const ic_completion_env_t* cenv );418419/// Do we have already some completions?420bool ic_has_completions( const ic_completion_env_t* cenv );421422/// Do we already have enough completions and should we return if possible? (for improved latency)423bool ic_stop_completing( const ic_completion_env_t* cenv);424425426/// Primitive completion, cannot be used with most transformers (like `ic_complete_word` and `ic_complete_qword`).427/// When completed, `delete_before` _bytes_ are deleted before the cursor position,428/// `delete_after` _bytes_ are deleted after the cursor, and finally `completion` is inserted.429/// The `display` is used to display the completion in the completion menu, and `help` is displayed430/// with hinting. Both `display` and `help` can be NULL.431/// (all are copied by isocline and do not need to be preserved or allocated).432///433/// Returns `true` if the callback should continue trying to find more possible completions.434/// If `false` is returned, the callback should try to return and not add more completions (for improved latency).435bool ic_add_completion_prim( ic_completion_env_t* cenv, const char* completion,436const char* display, const char* help,437long delete_before, long delete_after);438439/// \}440441//--------------------------------------------------------------442/// \defgroup helper Character Classes.443/// Convenience functions for character classes, highlighting and completion.444/// \{445446/// Convenience: return the position of a previous code point in a UTF-8 string `s` from postion `pos`.447/// Returns `-1` if `pos <= 0` or `pos > strlen(s)` (or other errors).448long ic_prev_char( const char* s, long pos );449450/// Convenience: return the position of the next code point in a UTF-8 string `s` from postion `pos`.451/// Returns `-1` if `pos < 0` or `pos >= strlen(s)` (or other errors).452long ic_next_char( const char* s, long pos );453454/// Convenience: does a string `s` starts with a given `prefix` ?455bool ic_starts_with( const char* s, const char* prefix );456457/// Convenience: does a string `s` starts with a given `prefix` ignoring (ascii) case?458bool ic_istarts_with( const char* s, const char* prefix );459460461/// Convenience: character class for whitespace `[ \t\r\n]`.462bool ic_char_is_white(const char* s, long len);463464/// Convenience: character class for non-whitespace `[^ \t\r\n]`.465bool ic_char_is_nonwhite(const char* s, long len);466467/// Convenience: character class for separators.468/// (``[ \t\r\n,.;:/\\(){}\[\]]``.)469/// This is used for word boundaries in isocline.470bool ic_char_is_separator(const char* s, long len);471472/// Convenience: character class for non-separators.473bool ic_char_is_nonseparator(const char* s, long len);474475/// Convenience: character class for letters (`[A-Za-z]` and any unicode > 0x80).476bool ic_char_is_letter(const char* s, long len);477478/// Convenience: character class for digits (`[0-9]`).479bool ic_char_is_digit(const char* s, long len);480481/// Convenience: character class for hexadecimal digits (`[A-Fa-f0-9]`).482bool ic_char_is_hexdigit(const char* s, long len);483484/// Convenience: character class for identifier letters (`[A-Za-z0-9_-]` and any unicode > 0x80).485bool ic_char_is_idletter(const char* s, long len);486487/// Convenience: character class for filename letters (_not in_ " \t\r\n`@$><=;|&\{\}\(\)\[\]]").488bool ic_char_is_filename_letter(const char* s, long len);489490491/// Convenience: If this is a token start, return the length. Otherwise return 0.492long ic_is_token(const char* s, long pos, ic_is_char_class_fun_t* is_token_char);493494/// Convenience: Does this match the specified token?495/// Ensures not to match prefixes or suffixes, and returns the length of the match (in bytes).496/// E.g. `ic_match_token("function",0,&ic_char_is_letter,"fun")` returns 0.497/// while `ic_match_token("fun x",0,&ic_char_is_letter,"fun"})` returns 3.498long ic_match_token(const char* s, long pos, ic_is_char_class_fun_t* is_token_char, const char* token);499500501/// Convenience: Do any of the specified tokens match?502/// Ensures not to match prefixes or suffixes, and returns the length of the match (in bytes).503/// E.g. `ic_match_any_token("function",0,&ic_char_is_letter,{"fun","func",NULL})` returns 0.504/// while `ic_match_any_token("func x",0,&ic_char_is_letter,{"fun","func",NULL})` returns 4.505long ic_match_any_token(const char* s, long pos, ic_is_char_class_fun_t* is_token_char, const char** tokens);506507/// \}508509//--------------------------------------------------------------510/// \defgroup term Terminal511///512/// Experimental: Low level terminal output.513/// Ensures basic ANSI SGR escape sequences are processed514/// in a portable way (e.g. on Windows)515/// \{516517/// Initialize for terminal output.518/// Call this before using the terminal write functions (`ic_term_write`)519/// Does nothing on most platforms but on Windows it sets the console to UTF8 output and possible520/// enables virtual terminal processing.521void ic_term_init(void);522523/// Call this when done with the terminal functions.524void ic_term_done(void);525526/// Flush the terminal output.527/// (happens automatically on newline characters ('\n') as well).528void ic_term_flush(void);529530/// Write a string to the console (and process CSI escape sequences).531void ic_term_write(const char* s);532533/// Write a string to the console and end with a newline534/// (and process CSI escape sequences).535void ic_term_writeln(const char* s);536537/// Write a formatted string to the console.538/// (and process CSI escape sequences)539void ic_term_writef(const char* fmt, ...);540541/// Write a formatted string to the console.542void ic_term_vwritef(const char* fmt, va_list args);543544/// Set text attributes from a style.545void ic_term_style( const char* style );546547/// Set text attribute to bold.548void ic_term_bold(bool enable);549550/// Set text attribute to underline.551void ic_term_underline(bool enable);552553/// Set text attribute to italic.554void ic_term_italic(bool enable);555556/// Set text attribute to reverse video.557void ic_term_reverse(bool enable);558559/// Set text attribute to ansi color palette index between 0 and 255 (or 256 for the ANSI "default" color).560/// (auto matched to smaller palette if not supported)561void ic_term_color_ansi(bool foreground, int color);562563/// Set text attribute to 24-bit RGB color (between `0x000000` and `0xFFFFFF`).564/// (auto matched to smaller palette if not supported)565void ic_term_color_rgb(bool foreground, uint32_t color );566567/// Reset the text attributes.568void ic_term_reset( void );569570/// Get the palette used by the terminal:571/// This is usually initialized from the COLORTERM environment variable. The572/// possible values of COLORTERM for each palette are given in parenthesis.573///574/// - 1: monochrome (`monochrome`)575/// - 3: old ANSI terminal with 8 colors, using bold for bright (`8color`/`3bit`)576/// - 4: regular ANSI terminal with 16 colors. (`16color`/`4bit`)577/// - 8: terminal with ANSI 256 color palette. (`256color`/`8bit`)578/// - 24: true-color terminal with full RGB colors. (`truecolor`/`24bit`/`direct`)579int ic_term_get_color_bits( void );580581/// \}582583//--------------------------------------------------------------584/// \defgroup async ASync585/// Async support586/// \{587588/// Thread-safe way to asynchronously unblock a readline.589/// Behaves as if the user pressed the `ctrl-C` character590/// (resulting in returning NULL from `ic_readline`).591/// Returns `true` if the event was successfully delivered.592/// (This may not be supported on all platforms, but it is593/// functional on Linux, macOS and Windows).594bool ic_async_stop(void);595596/// \}597598//--------------------------------------------------------------599/// \defgroup alloc Custom Allocation600/// Register allocation functions for custom allocators601/// \{602603typedef void* (ic_malloc_fun_t)( size_t size );604typedef void* (ic_realloc_fun_t)( void* p, size_t newsize );605typedef void (ic_free_fun_t)( void* p );606607/// Initialize with custom allocation functions.608/// This must be called as the first function in a program!609void ic_init_custom_alloc( ic_malloc_fun_t* _malloc, ic_realloc_fun_t* _realloc, ic_free_fun_t* _free );610611/// Free a potentially custom alloc'd pointer (in particular, the result returned from `ic_readline`)612void ic_free( void* p );613614/// Allocate using the current memory allocator.615void* ic_malloc(size_t sz);616617/// Duplicate a string using the current memory allocator.618const char* ic_strdup( const char* s );619620/// \}621622#ifdef __cplusplus623}624#endif625626#endif /// IC_ISOCLINE_H627628629