The OpenD Programming Language

LineGetter

A user-interactive line editor class, used by Terminal.getline. It is similar to GNU readline, offering comparable features like tab completion, history, and graceful degradation to adapt to the user's terminal.

More...
class LineGetter {
string[] history;
Terminal* terminal;
string historyFilename;
bool insertMode;
protected
bool lineChanged;
}

Constructors

this
this(Terminal* tty, string historyFilename)

Make sure that the parent terminal struct remains in scope for the duration of LineGetter's lifetime, as it does hold on to and use the passed pointer throughout.

Members

Enums

HistoryCommitMode
enum HistoryCommitMode

History is normally only committed to the file when the program is terminating, but if you are losing data due to crashes, you might want to change this to historyCommitMode = HistoryCommitMode.afterEachLine;.

HistoryRecallFilterMethod
enum HistoryRecallFilterMethod

Set in historyRecallFilterMethod.

Functions

addChar
void addChar(dchar ch)

Adds a character at the current position in the line. You can call this too if you hook events for hotkeys or something. You'll probably want to call redraw() after adding chars.

addString
void addString(string s)

.

appendHistoryToFile
void appendHistoryToFile(string item)

If historyCommitMode is HistoryCommitMode.afterEachLine, this line is called after each line to append to the file instead of saveSettingsAndHistoryToFile.

cancelHistorySearch
void cancelHistorySearch()

Cancels an in-progress history search immediately, discarding the result, returning to the normal prompt.

deleteChar
void deleteChar()

Deletes the character at the current position in the line. You'll probably want to call redraw() after deleting chars.

deleteToEndOfLine
void deleteToEndOfLine()
dispose
void dispose()

Call this before letting LineGetter die so it can do any necessary cleanup and save the updated history to a file.

editLineInEditor
dchar[] editLineInEditor(dchar[] line, size_t cursorPosition)
line may have private data packed into the dchar bits if you enabled enableAutoCloseBrackets. Use ch & ~PRIVATE_BITS_MASK to get standard dchars.
enableAutoCloseBrackets
string enableAutoCloseBrackets()

Enables automatic closing of brackets like (, {, and [ when the user types. Specifically, you subclass and return a string of the completions you want to do, so for that set, return "()[]{}"

finishGettingLine
string finishGettingLine()
getline
string getline(RealTimeConsoleInput* input)

One-call shop for the main workhorse If you already have a RealTimeConsoleInput ready to go, you should pass a pointer to yours here. Otherwise, LineGetter will make its own.

hadInput
bool hadInput()

Returns true if there was any input in the buffer. Can be checked in the case of a UserInterruptionException.

helpMessage
string helpMessage()
historyFileDirectory
string historyFileDirectory()

Override this to change the directory where history files are stored

historyFileExtension
string historyFileExtension()
historyFilter
string historyFilter(string candidate)

Override this if you don't want all lines added to the history. You can return null to not add it at all, or you can transform it.

historyPath
string historyPath()

semi-private, do not rely upon yet

isWordSeparatorCharacter
bool isWordSeparatorCharacter(dchar d)

Used by the word movement keys (e.g. alt+backspace) to find a word break.

lastLineWasRetained
bool lastLineWasRetained()

Returns true if the last line was retained by the user via the F9 or ctrl+enter key which runs it but keeps it in the edit buffer.

lineAsString
string lineAsString()

Gets the current line buffer as a duplicated string.

loadSettingsAndHistoryFromFile
void loadSettingsAndHistoryFromFile()

You may override this to do nothing

replaceLine
void replaceLine(dchar[] line)
void replaceLine(char[] line)

Replaces the line currently being edited with the given line and positions the cursor inside it.

saveSettingsAndHistoryToFile
void saveSettingsAndHistoryToFile()

You may override this to do nothing. If so, you should also override appendHistoryToFile if you ever change historyCommitMode.

showHelp
void showHelp()

Called by the default event loop when the user presses F1. Override showHelp to change the UI, override helpMessage if you just want to change the message.

showTabCompleteList
void showTabCompleteList(string[] list)

Override this to provide a custom display of the tab completion list.

startGettingLine
void startGettingLine()

Starts getting a new line. Call workOnLine and finishGettingLine afterward.

syntaxHighlightMatch
SyntaxHighlightMatch syntaxHighlightMatch(dchar[] line, size_t currentDrawPosition, size_t currentCursorPosition)

Subclasses that implement this function can enable syntax highlighting in the line as you edit it.

tabComplete
string[] tabComplete(dchar[] candidate, dchar[] afterCursor)

Override this to provide tab completion. You may use the candidate argument to filter the list, but you don't have to (LineGetter will do it for you on the values you return). This means you can ignore the arguments if you like.

tabCompleteHelp
string tabCompleteHelp(string candidate)

This gives extra information for an item when displaying tab competition details.

tabCompleteStartPoint
size_t tabCompleteStartPoint(dchar[] candidate, dchar[] afterCursor)

Override this to provide a different tab competition starting point. The default is 0, always completing the complete line, but you may return the index of another character of candidate to provide a new split.

workOnLine
bool workOnLine(InputEvent e, RealTimeConsoleInput* rtti)

for integrating into another event loop you can pass individual events to this and the line getter will work on it

Manifest constants

PRIVATE_BITS_MASK
enum PRIVATE_BITS_MASK;

If enableAutoCloseBrackets does not return null, you should ignore these bits in the line.

Properties

maximumDrawHeight
int maximumDrawHeight [@property getter]

Returns the maximum vertical space available to draw.

maximumDrawWidth
int maximumDrawWidth [@property getter]

If you are implementing a subclass, use this instead of terminal.width to see how far you can draw. Use care to remember this is a width, not a right coordinate.

maximumDrawWidth
int maximumDrawWidth [@property setter]

Sets the maximum width the line getter will use. Set to 0 to disable, in which case it will use the entire width of the terminal.

prompt
string prompt [@property setter]
string prompt [@property getter]

Set this if you want a prompt to be drawn with the line. It does NOT support color in string.

Structs

SyntaxHighlightMatch
struct SyntaxHighlightMatch

Subclasses that implement this function can enable syntax highlighting in the line as you edit it.

Variables

autoSuggest
bool autoSuggest;

Turn on auto suggest if you want a greyed thing of what tab would be able to fill in as you type.

background
Color background;

You can customize the colors here. You should set these after construction, but before calling startGettingLine or getline.

echoChar
dchar echoChar;

Controls the input echo setting.

handleLinkEvent
void delegate(LinkEvent ev, LineGetter lg) handleLinkEvent;

Gives a convenience hook for subclasses to handle my terminal's hyperlink extension.

historyCommitMode
HistoryCommitMode historyCommitMode;

History is normally only committed to the file when the program is terminating, but if you are losing data due to crashes, you might want to change this to historyCommitMode = HistoryCommitMode.afterEachLine;.

historyRecallFilterMethod
HistoryRecallFilterMethod historyRecallFilterMethod;

Controls what happens when the user presses the up key, etc., to recall history entries. See HistoryRecallMethod for the options.

pastePreprocessor
string delegate(string s) pastePreprocessor;
promptColor
Color promptColor;
regularForeground
Color regularForeground;
specialCharBackground
Color specialCharBackground;

You can customize the colors here. You should set these after construction, but before calling startGettingLine or getline.

suggestionForeground
Color suggestionForeground;

You can customize the colors here. You should set these after construction, but before calling startGettingLine or getline.

Detailed Description

A note on history:

To save history, you must call LineGetter.dispose() when you're done with it. History will not be automatically saved without that call!

The history saving and loading as a trivially encountered race condition: if you open two programs that use the same one at the same time, the one that closes second will overwrite any history changes the first closer saved.

GNU Getline does this too... and it actually kinda drives me nuts. But I don't know what a good fix is except for doing a transactional commit straight to the file every time and that seems like hitting the disk way too often.

We could also do like a history server like a database daemon that keeps the order correct but I don't actually like that either because I kinda like different bashes to have different history, I just don't like it all to get lost.

Regardless though, this isn't even used in bash anyway, so I don't think I care enough to put that much effort into it. Just using separate files for separate tasks is good enough I think.

Meta