hanslub42 / rlwrap

A readline wrapper
GNU General Public License v2.0
2.59k stars 151 forks source link

Option to allow inserting literal \t characters via <Tab>? #146

Closed nmeum closed 2 years ago

nmeum commented 2 years ago

Hello,

I am using rlwrap 0.4.5 with a program where I don't need tab completion and primarily use rlwrap to have readline-like keybindings like Ctrl+A and Ctrl+E. However, even though I don't use tab completion it does not seem to be possible to insert a literal \t character when the program is started through rlwrap, i.e. pressing <Tab> does nothing. I would like have <Tab> insert a literal \t instead.

Would it be possible to add an option which allows having <Tab> insert a literal tab character? Maybe something along the following?

--- b/src/main.c    2021-06-15 10:44:01.000000000 +0200
+++ a/src/main.c    2022-01-03 12:41:30.020930830 +0100
@@ -112,11 +112,11 @@ static void main_loop(void);

 /* options */
 #ifdef GETOPT_GROKS_OPTIONAL_ARGS
-static char optstring[] = "+:a::A::b:cC:d::D:e:Ef:F:g:hH:iIl:nNM:m::oO:p::P:q:rRs:S:t:TUvw:Wz:";
+static char optstring[] = "+:a::A::b:cC:d::D:e:Ef:F:g:hH:iIl:nNM:m::oO:p::P:q:rRs:S:t:TUvw:Wz:x";
 /* +: is not really documented. configure checks wheteher it works as expected
    if not, GETOPT_GROKS_OPTIONAL_ARGS is undefined. @@@ */
 #else
-static char optstring[] = "+:a:A:b:cC:d:D:e:Ef:F:g:hH:iIl:nNM:m:oO:p:P:q:rRs:S:t:TUvw:Wz:";    
+static char optstring[] = "+:a:A:b:cC:d:D:e:Ef:F:g:hH:iIl:nNM:m:oO:p:P:q:rRs:S:t:TUvw:Wz:x";   
 #endif

 #ifdef HAVE_GETOPT_LONG
@@ -158,6 +158,7 @@ static struct option longopts[] = {
   {"wait-before-prompt",        required_argument,      NULL, 'w'},
   {"polling",                   no_argument,            NULL, 'W'},
   {"filter",                    required_argument,      NULL, 'z'},
+  {"disable-completion",        no_argument,            NULL, 'x'},
   {0, 0, 0, 0}
 };
 #endif
@@ -928,6 +929,10 @@ read_options_and_command_name(int argc,
     case 'W':
       polling = TRUE; break;
     case 'z': filter_command = mysavestring(optarg);   break;
+    case 'x':
+      /* disable completions */
+      rl_bind_key('\t', rl_insert);
+      break;
     case '?':
       assert(optind > 0);
       WONTRETURN(myerror(FATAL|NOERRNO, "unrecognised option %s\ntry '%s --help' for more information", argv[optind-1], full_program_name));

Is there a better way to achieve this? I don't want to do this through .inputrc since I want other readline-based programs to support tab completions.

hanslub42 commented 2 years ago

The easiest way to achieve this is by adding the following lines to your .inputrc:

$if pass_through_TAB
  TAB:rlwrap-direct-keypress # This is *wrong*! Use self-insert (see below)
$endif

... and then calling rlwrap -C pass_through_TAB <your_program>

I don't want to do this through .inputrc since I want other readline-based programs to support tab completions.

Other readline-based programs (unless they are called pass_through_TAB) will then still support TAB completion.

That said, both when using your solution, or mine, any output produced by the underlying command in response to your will be invisible until either:

both of which will probably result in a garbled mess.

nmeum commented 2 years ago

That said, both when using your solution, or mine, any output produced by the underlying command in response to your will be invisible until either […]

That is fine in my case (I am using rlwrap with ed(1) and want to be able to insert \t in edited files). I will use your solution. I wasn't aware that the -C option can be used in this way. Thanks for pointing this out to me.

The only problem with your solution seems to be that it is not possible to delete inserted \t characters with backspace on my system (while this is possible with my patch). Any idea why this might be the case?

hanslub42 commented 2 years ago

Yes, my bad. You should use self-insert instead of rlwrap-direct-keypress.

The difference:

nmeum commented 2 years ago

Ah! Works as intended now, thanks again!