custom readline functions in bash commandline? - c

Code from GNU readline and key bindings :
#include <stdio.h>
#include <readline/readline.h>
int my_cool_readline_func (int count, int key) {
printf ("key pressed: %d\n", key);
rl_on_new_line ();
return 0;
}
int main(void) {
rl_command_func_t my_cool_readline_func;
rl_bind_key ('\t', my_cool_readline_func);
rl_bind_key (27, my_cool_readline_func); /* ascii code for ESC */
rl_bind_keyseq ("\\C-a", my_cool_readline_func);
while (1) {
char *line = readline ("rl> ");
}
}
Is it possible to use this kind of custom readline functions in bash commandline?
For example, I have tried these (a custom function can be much more complex, of course):
bind '"\C-t" beginning-of-line shell-kill-word'
bind '"\C-t" beginning-of-line, shell-kill-word'
bind '"\C-t" beginning-of-line; shell-kill-word'
None of them worked.

I think this binding is the key to understanding how this is done:
"\C-x\"": "\"\"\C-b"
Read "When I press Ctrl+X and then ", insert two quotes (\"\") and move the cursor once to the left (\C-b) so it ends up between the two double quotes.
On the right hand side of the :, you can only have a single readline function or a "macro" or a single shell function. A macro is a sequence of keystrokes.
So what you need to do is assign the functions you want to keys and then use the keys in the macro:
bind '"\C-t":"\C-a\ed"'
See also: Complex keybinding in bash

Related

ncurses "get_wch" function behavior

I try to understand how the get_wch function from ncurses works.
Here is a piece of code that I use to test it under TTY, terminator, and konsole:
#include <stdlib.h>
#include <curses.h>
#include <locale.h>
int main(void)
{
// initialize curses
initscr();
setlocale(LC_ALL, ""); // Just a check to see if something change with it
wint_t char_code;
int key_code = get_wch(&char_code);
char truc [20];
sprintf(truc, "%d / %d", key_code, char_code);
refresh();
getch();
endwin();
printf("%d\n", KEY_CODE_YES);
printf(truc);
printf("\n");
return 0;
}
When I hit a "classic" key like 'a' or '?', I get a char_code (UTF-8 code, I supposed). But when I hit a function key like F1 or F12, I get a char_code 27, and a key_code 0, except for F11 (key_code: KEY_CODE_YES, char_code: 410).
The documentation say that:
When get_wch, wget_wch, mvget_wch, and mvwget_wch functions successfully report the pressing of a function key, they return KEY_CODE_YES. When they successfully report a wide character, they return OK.
F1 to F12 are the so called "function keys" ? If I'm right, could you explain me why the function return 0 as a key_code when I hit a Fx key ?
You'll get KEY_CODE_YES only with keypad set to true, see keypad man page about that :
The keypad option enables the keypad of the user's terminal. If enabled (bf is TRUE),
the user can press a function key (such as an arrow key) and wgetch returns a single value
representing the function key, as in KEY_LEFT. If disabled (bf is FALSE), curses does not
treat function keys specially and the program has to interpret the escape sequences
itself. If the keypad in the terminal can be turned on (made to transmit) and off (made to
work locally), turning on this option causes the terminal keypad to be turned on when
wgetch is called. The default value for keypad is false.
And you're not getting keycode 0 but the success status OK from get_wch, see related manpage.
Without it, you'll have to get multiple char_code to get the key code like :
wint_t char_code;
wint_t char_code2 = 0, char_code3 = 0;
int key_code = get_wch(&char_code);
if (key_code == OK) key_code = get_wch(&char_code2);
if (key_code == OK) key_code = get_wch(&char_code3);
For function keys, you'll the escape code in char_code (0x27), the function code in char_code2 (0x4b) and the specific function key_code in char_code3.
EDIT As noticed by #dratenik, with xterm/VT220+ terminals, the F5-F12 function keys output four char_code, so you'll need to query another char_code when you get [ (0x5b) in char_code2 and 1 (0x31) in char_code3 to get the specific function keys key_code for theses function keys. You'll find the possible key codes in this useful link provided by #dratenik.

readline with a default value

I am able to limit the user input to 5 characters using GNU readline:
#include <readline/readline.h>
#include <stdio.h>
#include <stdlib.h>
static int limit_rl(FILE *f)
{
if (rl_end > 5) {
return '\b';
}
return rl_getc(f);
}
int main(void)
{
char *str;
rl_getc_function = limit_rl;
str = readline("> ");
printf("%s\n", str);
free(str);
return 0;
}
But, how to read an input with a default value (not a prompt), e.g.:
> ummy
^ cursor here
if user types d and Enter return "dummy"
if user types DEL and Enter return "mmy"
On the homepage of readline a possible use is mentioned:
rl.c is an example program that uses Readline to read a line of input from a user and echo it to the standard output, suitable for use by shell scripts.
and since editing an existing entry could well be part of this, I decided to take a look at its source (direct download link). This indeed shows how to insert a string into the buffer used by readline before it appears on the screen, through the use of a hook function:
Variable: rl_hook_func_t * rl_startup_hook
If non-zero, this is the address of a function to call just before readline prints the first prompt.
(https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#IDX223)
Inside the hook function you can directly manipulate the internal buffer, for example to insert text:
Function: int rl_insert_text (const char *text)
Insert text into the line at the current cursor position. Returns the number of characters inserted.
(https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#IDX295)
The hook function only needs to do this once (it is called only once per readline call inside readline_internal_setup), but apparently rl's author went for the belt-and-suspenders approach and specifically disables it after it has been used.
Relevant snippets from rl.c, comments are mine:
/* a global char * to hold a default initial text */
static char *deftext;
/* the callback function. The argument is supposed to be 'void' per
its declaration:
typedef int rl_hook_func_t (void);
so you cannot provide the default text here */
static int set_deftext ()
{
if (deftext)
{
/* Apparently the "current cursor position" in which text is inserted
is 0, when initially called */
rl_insert_text (deftext);
deftext = (char *)NULL;
/* disable the global 'rl_startup_hook' function by setting it to NULL */
rl_startup_hook = (rl_hook_func_t *)NULL;
}
return 0;
}
// ...
if (deftext && *deftext)
rl_startup_hook = set_deftext;
temp = readline (prompt);

What does the "in" keyword in Lua do?

I know it's usually combined with a for i,v in pairs() do loop (or ipairs, or even next) but what exactly is in?
Just to clarify, I know how to use it, I just don't know the logic behind it, how does it work/what does it return?
Lua's in is not a function or a variable. It's a part of the syntax for flow control. You can't replace it, you can't copy it, you can't even refer to it. It's rather like parentheses: a syntactic construct which has meaning for how a program is parsed, but which cannot be referred to within the program.
It doesn't "return" anything. It doesn't have "logic." It's more like a placeholder, or punctuation.
It doesn't do anything. It is syntax. It isn't a function. It isn't an opcode. It isn't a language feature. It is purely syntactical.
See the forlist function in lparser.c:
static void forlist (LexState *ls, TString *indexname) {
/* forlist -> NAME {,NAME} IN explist1 forbody */
FuncState *fs = ls->fs;
expdesc e;
int nvars = 0;
int line;
int base = fs->freereg;
/* create control variables */
new_localvarliteral(ls, "(for generator)", nvars++);
new_localvarliteral(ls, "(for state)", nvars++);
new_localvarliteral(ls, "(for control)", nvars++);
/* create declared variables */
new_localvar(ls, indexname, nvars++);
while (testnext(ls, ','))
new_localvar(ls, str_checkname(ls), nvars++);
checknext(ls, TK_IN);
line = ls->linenumber;
adjust_assign(ls, 3, explist1(ls, &e), &e);
luaK_checkstack(fs, 3); /* extra space to call generator */
forbody(ls, base, line, nvars - 3, 0);
}
Create the control variables.
Handle the local variables in the comma list.
Check that the next token is TK_IN which maps to luaX_tokens.

How to prevent function from printing?

Is it possible to silence a function?
For example:
#include <stdio.h>
int function(){
printf("BLAH!");
return 10;
}
int main(){
printf("%d", silence( function()) );
return 0;
}
And instead of:
BLAH!
10
I would get:
10
Is it possible? If positive how to do it?
An awfully complicated way to do almost what you want is to use the dup2() system call. This requires executing fflush(stdout); dup2(silentfd, stdout); before function() is called, and copying back afterwards: fflush(stdout); dup2(savedstdoutfd, stdout);. So it is not possible to do as just silence(function()), since this construct only allows to execute code after function() has already been executed.
The file descriptors silentfd and savedstdoutfd have to be prepared in advance (untested code):
int silentfd = open("/dev/null",O_WRONLY);
int savedstdoutfd = dup(stdout);
This is almost certainly not what you really want, but inasmuch as your question is phrased as “is it possible?”, the answer is “almost”.
use macro function and null device.
E.g. for windows
#include <stdio.h>
#define silence(x) (_stream = freopen("NUL:", "w", stdout), _ret_value = x,_stream = freopen("CON:", "w", stdout),_ret_value)
int _ret_value;
FILE *_stream;
int function(){
printf("BLAH!");
return 10;
}
int main(void){
printf("%d", silence( function()) );
return 0;
}
No its not possible. You could however try to temporarily redirect the stdout to something else. That may come close to what you want.
You can use this macro instead of printf to be able to prevent printing:
int flag=0;
#define PRINT(...) if(flag){printf(...)}
then use PRINT macro by considering the variable flag. If flag==1, the function will print and if flag==0, the function will not print.
With GCC extensions, you might consider having macros like
bool silent;
#define silence(X) ({int _x; quiet(); _x = (X); verbose(); _x; })
#define printf(Fmt,...) \
do{if (!silent) printf(Fmt,##__VA_ARGS__);}while(0)
that silence macro would work only if its argument X is a int expression (or use typeof) I also assume that the result of printf is never used. Recall that "recursive" macros are specially pre-processed, the inside occurrence of printf (in that printf macro) is left verbatim without macro-expansion.
Notice that silence cannot be a function (otherwise, its argument would have been evaluated before calling it). And you need GCC statement expressions extension to "remember" the result of the argument in some variable _x (you could generate that name using __COUNTER__ and preprocessor concatenation), to give it back as the value of silence macro invocation.
Then you need to define your functions quiet() and verbose(), perhaps something like
void quiet()
{
silent = true;
}
void verbose()
{
silent = false,
}
if you don't want to define printf as your macro, you could use freopen(3) on stdout (perhaps with "/dev/null" etc...) or do dup2(2) tricks (like suggested by Pascal Cuoq).
If your code base is huge, and you want something more serious and are willing to spend days or weeks of work, consider customizing your GCC compiler with a plugin or a MELT extension (or ask someone to do it). Notice that printf is known to GCC.
In reality, you should define your own macro like
#define myprintf(Fmt, ...) do{if (!silent) \
printf(Fmt,__VA_ARGS__);}while(0)
and just use myprintf instead of printf everywhere, this is a portable trick. Of course, I assume you are not passing printf as a function pointer.
For debugging, I actually recommend
#define dbgprintf(Fmt,...) do{if (wantdebug) \
printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \
##__VA_ARGS__);}while(0)
and then I use dbgprintf("i=%d",i) or simply dbgprintf("foo here") in my code.
I'm using ##__VA_ARGS__ which is a GCC extension to accept no variable arguments to a variadic macro. If you want strict C99, you will just say __VA_ARGS__ and every dbgprintf would need one argument after the format.
You could also re-implement your own printf function, but I don't advise doing that.
(Notice that things could be more complex, you can print using fputs not printf ....)
If you're designing the function do the following:
int function(void (*printer)(char *)){
if (!printer)
printer = printf;
printer("BLAH!");
return 10;
}
void silence(char *s){
return;
}
int main(int argc, char **argv){
printf("%d\n", function(silence));
return 0;
}
That should do what you're looking for. Unfortunately, I didn't test it and my C is probably a little bit rusty.
Of course if function isn't something you have control over, the answers already posted are all correct solutions.
Actually, if you're designing the function yourself, just do:
int function(int print){
if (print)
printf("BLAH!");
return 10;
}
function(0); /* Won't print anything */
function(!0); /* Will print "BLAH!" */
because 0 is false and any non-zero (or !0) value is true. My above suggestion is error prone since you'll have to be able to mimic the printf signature for silence or for any other function you wish to use.
Unfortunately if you have the function explicitly printing and call it like this then it will always print. if you want to silence the function completely you could simply comment out that line.You could even use a control statement so that it only prints IF and when a condition is met otherwise it stays blank and only returns the number.

Is it possible to exchange a C function implementation at run time?

I have implemented a facade pattern that uses C functions underneath and I would like to test it properly.
I do not really have control over these C functions. They are implemented in a header. Right now I #ifdef to use the real headers in production and my mock headers in tests. Is there a way in C to exchange the C functions at runtime by overwriting the C function address or something? I would like to get rid of the #ifdef in my code.
To expand on Bart's answer, consider the following trivial example.
#include <stdio.h>
#include <stdlib.h>
int (*functionPtr)(const char *format, ...);
int myPrintf(const char *fmt, ...)
{
char *tmpFmt = strdup(fmt);
int i;
for (i=0; i<strlen(tmpFmt); i++)
tmpFmt[i] = toupper(tmpFmt[i]);
// notice - we only print an upper case version of the format
// we totally disregard all but the first parameter to the function
printf(tmpFmt);
free(tmpFmt);
}
int main()
{
functionPtr = printf;
functionPtr("Hello world! - %d\n", 2013);
functionPtr = myPrintf;
functionPtr("Hello world! - %d\n", 2013);
return 0;
}
Output
Hello World! - 2013
HELLO WORLD! - %D
It is strange that you even need an ifdef-selected header. The code-to-test and your mocks should have the exact same function signatures in order to be a correct mock of the module-to-test. The only thing that then changes between a production-compilation and a test-compilation would be which .o files you give to the linker.
It is possible With Typemock Isolator++ without creating unnecessary new levels of indirection. It can be done inside the test without altering your production code. Consider the following example:
You have the Sum function in your code:
int Sum(int a, int b)
{
return a+b;
}
And you want to replace it with Sigma for your test:
int Sigma(int a, int b)
{
int sum = 0;
for( ; 0<a ; a--)
{
sum += b;
}
return sum;
}
In your test, mock Sum before using it:
WHEN_CALLED: call the method you want to fake.
ANY_VAL: specify the args values for which the mock will apply. in this case any 2 integers.
*DoStaticOrGlobalInstead: The alternative behavior you want for Sum.
In this example we call Sigma instead.
TEST_CLASS(C_Function_Tests)
{
public:
TEST_METHOD(Exchange_a_C_function_implementation_at_run_time_is_Possible)
{
void* context = NULL; //since Sum global it has no context
WHEN_CALLED(Sum (ANY_VAL(int), ANY_VAL(int))).DoStaticOrGlobalInstead(Sigma, context);
Assert::AreEqual(2, Sum(1,2));
}
};
*DoStaticOrGlobalInstead
It is possible to set other types of behaviors instead of calling an alternative method. You can throw an exception, return a value, ignore the method etc...
For instance:
TEST_METHOD(Alter_C_Function_Return_Value)
{
WHEN_CALLED(Sum (ANY_VAL(int), ANY_VAL(int))).Return(10);
Assert::AreEqual(10, Sum(1,2));
}
I don't think it's a good idea to overwrite functions at runtime. For one thing, the executable segment may be set as read-only and even if it wasn't you could end up stepping on another function's code if your assembly is too large.
I think you should create something like a function pointer collection for the one and the other set of implementations you want to use. Every time you want to call a function, you'll be calling from the selected function pointer collection. Having done that, you may also have proxy functions (that simply call from the selected set) to hide the function pointer syntax.

Resources