rakitzis / rc

rc shell -- independent re-implementation for Unix of the Plan 9 shell (from circa 1992)
Other
257 stars 23 forks source link

How to edit command line in vim / copy command line to clipboard / bind fzf-file-widget? #96

Open MaxGyver83 opened 5 months ago

MaxGyver83 commented 5 months ago

Thank you for implementing rc for Linux! I'm new to it and I have some questions:

Can I achieve any of the following in rc (with readline support):

Edit command line in vim

I have this in my .inputrc:

# edit command line in vim
"\ev": edit-and-execute-command

This does not work in rc because it's a bash function. I think it belongs into my .bashrc then. Could I replace edit-and-execute-command with an equivalent rc function? Would this have to be done in rc's source code?

Copy the current command line to the clipboard

I have this in my .bashrc:

copy_line_to_x_clipboard () {
  # using OSC 52
  printf "\e]52;c;%s\a" "$(printf %s "$READLINE_LINE" | openssl base64 -A)"
}
# bind to Ctrl-Shift-x
bind -x '"\C-X": copy_line_to_x_clipboard'

I have adapted this function for rc (in my .rcrc):

fn copy_line_to_x_clipboard {
    # using OSC 52
    printf '\e]52;c;%s\a' `{printf %s $READLINE_LINE | openssl base64 -A}
}

and moved the binding to C-X into my .inputrc:

"\C-X": copy_line_to_x_clipboard

But it still does not work. Is it possible at all to bind readline keystrokes to rc functions? (Maybe I just got the quotes wrong.)

Use fzf for file selection

More or less the same question: How can I migrate this bash snippet to rc?

  # CTRL-T - Paste the selected file path into the command line
  if [[ "${FZF_CTRL_T_COMMAND-x}" != "" ]]; then
    bind -m emacs-standard -x '"\C-t": fzf-file-widget'
    bind -m vi-command -x '"\C-t": fzf-file-widget'
    bind -m vi-insert -x '"\C-t": fzf-file-widget'
  fi

fzf/shell/key-bindings.bash at 07880ca4415009d7a151d262bc5ac62f8b6dc719 · junegunn/fzf

rakitzis commented 2 months ago

Hi, I'm looking at these questions and I don't know the answers. Readline support is ad hoc. If you send me a pull request to run shell functions from readline keystrokes, I'll review it.

MaxGyver83 commented 2 months ago

Hi Byron,

I tried adding this for bestline. But so far it does not work. These are my current local changes for rc:

diff --git a/Makefile b/Makefile
index 39966e6..a22e4f6 100644
--- a/Makefile
+++ b/Makefile
@@ -9,9 +9,9 @@ VERSION = 1.7.4
 PREFIX = /usr/local
 MANPREFIX = $(PREFIX)/share/man

-_CFLAGS = -Wall $(CFLAGS)
-_CPPFLAGS = -I. -I$(srcdir) -I$(PREFIX)/include $(CPPFLAGS)
-_LDFLAGS = -L$(PREFIX)/lib $(LDFLAGS)
+_CFLAGS = -Wall $(CFLAGS) -g
+_CPPFLAGS = -I/home/max/repos/bestline-dev -I. -I$(srcdir) -I$(PREFIX)/include $(CPPFLAGS)
+_LDFLAGS = -L/home/max/repos/bestline-dev -L$(PREFIX)/lib $(LDFLAGS) -g

 BINS = history mksignal mkstatval tripping
 HEADERS = edit.h getgroups.h input.h jbwrap.h proto.h rc.h rlimit.h stat.h \
diff --git a/builtins.c b/builtins.c
index f73cd2d..269f921 100644
--- a/builtins.c
+++ b/builtins.c
@@ -23,7 +23,7 @@
 #include "addon.c"
 #endif

-static void b_break(char **), b_cd(char **), b_continue(char **), b_eval(char **), b_flag(char **),
+static void b_bind(char **), b_break(char **), b_cd(char **), b_continue(char **), b_eval(char **), b_flag(char **),
    b_exit(char **), b_newpgrp(char **), b_return(char **), b_shift(char **), b_umask(char **),
    b_wait(char **), b_whatis(char **);

@@ -35,10 +35,17 @@ static void b_limit(char **);
 static void b_echo(char **);
 #endif

+#if EDIT == bestline
+extern void bestlineAddBinding(char **);
+#endif
+
 static struct {
    builtin_t *p;
    char *name;
 } builtins[] = {
+#if EDIT == bestline
+   { b_bind,   "bind" },
+#endif
    { b_break,  "break" },
    { b_builtin,    "builtin" },
    { b_cd,     "cd" },
@@ -81,6 +88,8 @@ extern void funcall(char **av) {
    Edata jreturn, star;
    if (sigsetjmp(j.j, 1))
        return;
+   /* char *bv = getenv("BESTLINE_LINE"); */
+   /* fprint(2, "\nBESTLINE_LINE: %s\n", bv ? bv : "UNSET"); */
    starassign(*av, av+1, TRUE);
    jreturn.jb = &j;
    star.name = "*";
@@ -102,6 +111,18 @@ static void badnum(char *num) {
     set(FALSE);
 }

+#if EDIT == bestline
+static void b_bind(char **av) {
+   av++; // skip "bind"
+   if (*av == NULL || !streq(*av, "-x") || *(av+1) == NULL || *(av+2) == NULL) {
+       fprint(2, RC "%s\n", "usage: bind -x C-x my_func arg1 arg2");
+       set(FALSE);
+       return;
+   }
+   bestlineAddBinding(++av); // skip "-x"
+}
+#endif
+
 /* a dummy command. (exec() performs "exec" simply by not forking) */

 extern void b_exec(char **ignore) {
diff --git a/edit-bestline.c b/edit-bestline.c
index 74c36a9..ddf7567 100644
--- a/edit-bestline.c
+++ b/edit-bestline.c
@@ -280,6 +280,7 @@ void *edit_begin(int fd) {
    struct cookie *c;

    bestlineSetCompletionCallback(completion);
+   bestlineSetShellFunctionCallback((void (*)(const char **))funcall);

    hist = varlookup("history");
    if (hist != NULL)

Of course, bestline needs to be extended as well. Maybe I'll try to get it running with readline, first.

MaxGyver83 commented 2 months ago

Btw, I have written an article about rc: rc shell instead of bash or fish