FBB::ReadLineStream(3bobcat)
π NAME π
FBB::ReadLineStream β a std::istream that gives you line-editing and history, no cap. This is FBB::ReadLineStream(3bobcat), straight out of the bobcat manual. π¦
β¨ SYNOPSIS β¨
#include <bobcat/readlinestream>
Linking option: -lbobcat -lreadline
πΈ DESCRIPTION πΈ
So a FBB::ReadLineStream object is a std::istream object, and it lets you do line-editing plus history manipulation. That's the whole vibe. π
The ReadLineStream class uses Gnu's readline library to let you edit your input lines. You can use the ReadLineStream object to construct a std::istream that allows in-line editing of lines read from the terminal. And every single one of those lines can be preceded by a configurable prompt. β¨
okay important one, bestie: since Gnu's readline library operates on global data, there can only be oneReadLineStream(and underlyingReadLineBuf) object. Ever.ReadLineStreamis a singleton class: in any program there can only be oneReadLineStreamobject. periodt. π
ReadLineStream offers editing capabilities while the user is entering lines. Like Gnu's readline(3) function, the line editing commands are by default similar to those of emacs(1), but they can easily be reconfigured, e.g. to offer vi(1)-like characteristics. π
History manipulation is provided as an option. The collected history may be accessed for reading using an FBB::ReadLineHistory object.
Specific information about the facilities offered by the Gnu software used by ReadLineStream is provided in the GNU Readline Library documentation (http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html).
Gnu's readline function reads its information from the standard input file. Programs using ReadLineStream should normally not extract information from std::cin. However, as the standard input file has a file descriptor (0), redirection should be possible (e.g., using FBB::Redirector). π«Ά
When the command line is kept, history expansion is offered as an option. History expansion introduces words from the history list into the input stream, making it easy to repeat commands, to insert elements of a previous input line into the current input line, or to fix errors in previous command lines. π
History expansion is usually performed immediately after a complete line is read.
The line selected from the history is called the event, and the portions of that line that are processed are called words. Various modifiers are available to manipulate selected words. This is comparable to the way a program like bash(1) breaks up its input line into words. π
History expansion is introduced by the use of the history expansion character, by default equal to the !-character. Only backslash (\) and single quotes can change the history expansion character into a normal character. β
The remainder of this section is copied almost verbatim from the history(3) man-page. The reader is referred to that man-page or to the Gnu History Library documentation for further details. (iykyk π)
π Event Designators π
The following event designators are supported:
!:β starts a history substitution, except when followed by a blank, newline,=or(.!nβ refers to command line n.!-nβ refers to the current command line minus n.!!β refers to the previous command. This is a synonym for!-1.!stringβ refers to the most recent command starting with string.!?string[?]β refers to the most recent command containing string. The trailing?may be omitted if string is followed immediately by a newline.^string1^string2^(quick substitution) β repeats the last command, replacing string1 with string2. Equivalent to!!:s/string1/string2/.!#β the entire command line typed so far.
π¦ Word Designators π¦
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. β¨
0(zero) β The zeroth word. For the shell, this is the command word.nβ The *n*th word.^β The first argument. That is, word1.$β The last argument.%β The word matched by the most recent?string?search.x-yβ A range of words;-yabbreviates0-y.*β All of the words but the zeroth. This is a synonym for1-$. 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*β Abbreviatesx-$.x-β Abbreviatesx-$likex*, but omits the last word. If a word designator is supplied without an event specification, the previous command is used as the event.
π Modifiers π
After the optional word designator, there may appear a sequence of one or more of the following modifiers, each preceded by a :. π
hβ removes a trailing file name component, leaving only the head.tβ removes all leading file name components, leaving the tail.rβ removes a trailing suffix of the form.xxx, leaving the basename.eβ removes all but the trailing suffix.pβ prints the new command but does not execute it.qβ quotes the substituted words, escaping further substitutions.xβ quotes the substituted words as withq, but break into words at blanks and newlines.s/old/new/β substitutes new for the first occurrence of old in the event line. Any delimiter can be used in place of/. The final delimiter is optional if it is the last character of the event line. 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 null, it is set to the last old substituted, or, if no previous history substitutions took place, the last string in a!?string[?]search.&β repeats the previous substitution.gβ Causes changes to be applied over the entire event line. This is used in conjunction with:s(e.g.,:gs/old/new/) or:&. If used with:s, any delimiter can be used in place of/, and the final delimiter is optional if it is the last character of the event line. Anamay be used as a synonym forg.Gβ Apply the followingsmodifier once to each word in the event line.
π NAMESPACE π
FBB
All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace FBB.
π INHERITS FROM π
FBB::ReadLineBuf (privately), std::istream (publicly)
β ENUMERATIONS β
The enum Type defines the following value:
DONT_EXPAND_HISTORYβ history expansion is not requested;EXPAND_HISTORYβ history expansion is requested.
The enum Expansion provides meaningful return values for the history expansion process. Its values are:
DONT_EXECβ history expansion succeeded, but the expanded line should not be executed. E.g., after entering the line
ls *
the line
!!:p
should cause the using program to display, rather than execute ls *. Note that interpretation of this expansion return value is not the task of the ReadLineBuf object, but of the program using the ReadLineBuf object.
ERRORβ the history expansion failed. See also the memberexpansionErrorbelow;EXPANDEDβ the history expansion succeeded;NO_EXPANSIONβ no history expansion took place.
π CONSTRUCTORS π
Preamble: since there can only be one ReadLineBuf object, any attempt to define a second ReadLineStream object will fail as there can only be a single ReadLineBuf object in any program. An attempt to define a second ReadLineBuf object results in a logic_error exception being thrown. π
fr fr, one and done. Try to make a second one and it throws logic_error at you. Not a vibe check you want to fail.
ReadLineStream(std::string const &prompt = "", Type type = NO_EXPANSION)This constructor initializes theReadLineStreamobject with an initial prompt, using a history of at moststd::numeric_limits<int>::max()lines, by default not using history expansion. β¨ReadLineStream(std::string const &prompt, size_t historySize, Type type = NO_EXPANSION)This constructor initializes theReadLineStreamwith an initial prompt, an initial history of a predefined maximum size, by default not using history expansion. Specifying a history size0results in no history being kept, any value equal to or exceeding the predefined constantstd::numeric_limits<int>::max()results in a history of at moststd::numeric_limits<int>::max()lines. If no history is requested but type is specified asEXPAND_HISTORYalogic_errorexception is thrown. π
Copy and move constructors (and assignment operators) are not available. π ββοΈ
β¦and that's only part 1, bestie β part 2 is right there waiting for you π«Άβ¨
π MEMBER FUNCTIONS π
Okay bestie, listen. Every single member of std::streambuf is yours to play with, because FBB::ReadLineStream inherits from that class. All of it. Free. Inherited. Slay. π«Ά
Here's the homegrown stuff, one by one:
ReadLineStream::Expansion expansion() constβ this hands you back the status of the history expansion after a line has been pulled in from the terminal. The value gets figured out again after every single line you retrieve from the terminal. And bestie, if you never asked for history expansion in the first place? It returnsExpansion::ERROR. Awkward, but that's the deal. πstd::string const &expansionError() constβ whenexpansioncomes back asExpansion::ERROR, this gives you a short little textual description of what actually went wrong. No history expansion requested? Then you get an empty string. Nothing. Silence. πbool setExpansion(Type type)β turn history expansion on or off with this one. But here's the catch: if you ask for history expansion and yourReadLineStreamobject isn't keeping any history, this returnsfalse. Any other time it returnstrue. Vibe check passed or not, no in-between.void setPrompt(std::string const &prompt = "")β this changes the prompt that shows up in front of the next line read from the terminal. Call it with no arguments and no prompt shows up at all. And the cute part?setPromptcan be called while input lines are still coming in. The new prompt just won't be active until the current line has been fully read from the terminal. Patience, babes. β¨bool useTimestamps(std::string (*timestamp)() = 0)β initialize it with the address of a function that returns astd::string, and every command you type gets a timestamp equal to the text that function returns. Then you can grab those timestamps with aReadLineHistory(3)object. By default β or if you pass it an explicit0-pointer β no timestamps get stored at all. Return value:falsewhen no history is being kept,trueotherwise. Simple as that. π
π EXAMPLE π
Fr fr, here's the whole thing in action:
#include <iostream>
#include <istream>
#include <cstdio>
#include <sstream>
#include <iomanip>
#include <bobcat/readlinestream>
using namespace std;
using namespace FBB;
int main()
{
ReadLineStream in("", 10, ReadLineBuf::EXPAND_HISTORY);
size_t count = 0;
string line;
while (true)
{
ostringstream prompt;
prompt << setw(2) << ++count << ": ";
in.setPrompt(prompt.str());
if (!getline(in, line)) // uses the last-set prompt
break;
cout << "Retrieved: " << line << "\n"
"Expansion status: ";
switch (in.expansion())
{
case ReadLineBuf::ERROR:
cout << "ERROR: " << in.expansionError() << β\nβ;
break;
case ReadLineBuf::NO_EXPANSION:
cout << "no expansion performed\n";
break;
case ReadLineBuf::DONT_EXEC:
cout << "donβt execute the expanded line\n";
break;
case ReadLineBuf::EXPANDED:
cout << "expansion successfully performed\n";
break;
}
}
}
Not me staring at how clean that switch is. Every expansion status, named and accounted for. Chef's kiss. π
π¦ FILES π¦
bobcat/readlinebufβ defines the class interface
πΈ SEE ALSO πΈ
bobcat(7), readline(3), readlinebuf(3bobcat), readlinehistory(3bobcat)
Go read them, bestie. Cross-references are self-care. π
π BUGS π
None Reported.
(The maintenance girlies really said "nothing to see here." Iconic. π)
π BOBCAT PROJECT FILES π
https://fbb-git.gitlab.io/bobcat/: gitlab project page;
Debian Bobcat project files:
libbobcat6: debian package containing the shared library, changelog and copyright note;libbobcat-dev: debian package containing the static library, headers, manual pages, and developer info;
β BOBCAT β
Bobcat is an acronym of Brokkenβs Own Base Classes And Templates.
Periodt. The name is literally a flex. π
π COPYRIGHT π
This is free software, distributed under the terms of the GNU General Public License (GPL).
Free as in freedom, babes. Share it, love it, respect the GPL. π«Ά
π AUTHOR π
Frank B. Brokken (f.b.brokken@rug.nl).
And that's the whole page, bestie β footer and all: this shipped as part of libbobcat-dev version 6.15.01, with the copyright years running 2005-2026, and the man page answers to the name FBB::ReadLineStream(3bobcat). Now go forth and read some lines. Slay. β¨πΈπ¦
π¦ where this page comes from
- ubuntu stonking: libbobcat-dev 6.15.01-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms