per Skript readline-Kommandos an Bash absetzen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
hupfdule
Beiträge: 1868
Registriert: 09.12.2002 15:04:37
Wohnort: Berlin
Kontaktdaten:

per Skript readline-Kommandos an Bash absetzen

Beitrag von hupfdule » 26.03.2025 17:20:49

Hallo,

ich suche einen Weg readline-Kommandos per Shellskript and die aktuelle Bash abzusetzen.
Im Grunde das selbe, was in Fish per commandline builtin möglich ist.

Beispielsweise kann ich in Fish per

Code: Alles auswählen

commandline -f backward-word
den Cursor um ein Wort zurück bewegen (was per

Code: Alles auswählen

Alt-b
interaktiv ausgelöst würde).

Hintergrund ist, dass iich das Tool re-search, das ich für die Search-History in Fish benutze, auch für Bash einsetzen. Das Tool stellt eine eigene Suche in der Shell-History bereit und befüllt anschließend die aktuelle Kommandozeile mit der gefundenen Befehlszeile. Im Anschluss sollen aber dann automatisiert (eben per Shell-Skript) readline-Befehle abgesetzt und die Kommandozeile ausgeführt werden.

TLDR: Gibt es ein Äquivalent zu Fishs "commandline" in Bash?

TuxPeter
Beiträge: 2029
Registriert: 19.11.2008 20:39:02
Lizenz eigener Beiträge: MIT Lizenz

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von TuxPeter » 26.03.2025 18:58:07

Meinst du so etwas?

Code: Alles auswählen

echo -n "Suchwort: "
read such
echo Suchwort:$such:

Benutzeravatar
hupfdule
Beiträge: 1868
Registriert: 09.12.2002 15:04:37
Wohnort: Berlin
Kontaktdaten:

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von hupfdule » 26.03.2025 20:43:53

Nein.

Angenommen ich möchte die Kommandozeile

Code: Alles auswählen

ls /bin
erzeugen und den Cursor hinter den Slash setzen.

Das kann ich durch das manuelle Eintippen der folgenden Tasten(-kombinationen) erreichen:

Code: Alles auswählen

l
s
<space>
/
b
i
n
<alt-b>
Ich möchte das aber nicht eintippen, sondern aus einem Shellskript heraus auf der aktuellen Kommandozeile erzeugen.


Zum Vergleich: In fish erreiche ist das hierdurch:

Code: Alles auswählen

commandline -r "ls /bin" ; commandline -f backward-word

Benutzeravatar
Huo
Beiträge: 825
Registriert: 26.11.2017 14:03:31
Wohnort: Freiburg

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von Huo » 27.03.2025 08:02:20

hupfdule hat geschrieben: ↑ zum Beitrag ↑
26.03.2025 20:43:53
Zum Vergleich: In fish erreiche ist das hierdurch:

Code: Alles auswählen

commandline -r "ls /bin" ; commandline -f backward-word
Ich denke nicht, dass etwas Äquivalentes mit bash builtins möglich ist. Mit dem Werkzeug Debianxdotool lässt es sich aber nachstellen:

Code: Alles auswählen

xdotool type "ls /bin"; xdotool key Alt+b

Benutzeravatar
hupfdule
Beiträge: 1868
Registriert: 09.12.2002 15:04:37
Wohnort: Berlin
Kontaktdaten:

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von hupfdule » 27.03.2025 08:15:05

Ja, xdotool ist die einzige Möglichkeit, die ich bis jetzt gefunden habe, aber leider von X abhängig. Ohne X würde das nicht mehr klappen.

Benutzeravatar
hikaru
Moderator
Beiträge: 14038
Registriert: 09.04.2008 12:48:59

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von hikaru » 27.03.2025 09:19:52

hupfdule hat geschrieben: ↑ zum Beitrag ↑
27.03.2025 08:15:05
Ja, xdotool ist die einzige Möglichkeit, die ich bis jetzt gefunden habe, aber leider von X abhängig. Ohne X würde das nicht mehr klappen.
Falls es dir hier um X vs Wayland geht, das Äquivalent zu Debianxdotool wäre Debianwlrctl.

Ich bin allerdings skeptisch ob der Ansatz zielführend ist, denn xdotool/wlrctl kann ja nicht kontextsensitiv arbeiten.
Du möchtest in deinem Beispiel zwar hinter den "/" springen, kannst dem Tool aber nur sagen: "Drücke dreimal CursorLinks!" Das funktioniert hier, weil du vorher abgezählt hast, dass "bin" drei Zeichen hat, aber wenn du stattdessen "ls /proc" eingegeben hättest, dann passt die 3 nicht mehr, und du müsstest deiner Lösung das Zählen beibringen.

Benutzeravatar
hupfdule
Beiträge: 1868
Registriert: 09.12.2002 15:04:37
Wohnort: Berlin
Kontaktdaten:

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von hupfdule » 27.03.2025 10:06:15

hikaru hat geschrieben: ↑ zum Beitrag ↑
27.03.2025 09:19:52
hupfdule hat geschrieben: ↑ zum Beitrag ↑
27.03.2025 08:15:05
Ja, xdotool ist die einzige Möglichkeit, die ich bis jetzt gefunden habe, aber leider von X abhängig. Ohne X würde das nicht mehr klappen.
Falls es dir hier um X vs Wayland geht, das Äquivalent zu Debianxdotool wäre Debianwlrctl.
Nein, ich will gänzlich unabhängig davon sein. Das soll auch ganz ohne grafische Oberfläche funktionieren. Also bspw. eine Bash per SSH session.
Ich bin allerdings skeptisch ob der Ansatz zielführend ist, denn xdotool/wlrctl kann ja nicht kontextsensitiv arbeiten.
Ja, ich bin da auch noch skeptisch. Aber aus anderen Gründen.
Du möchtest in deinem Beispiel zwar hinter den "/" springen, kannst dem Tool aber nur sagen: "Drücke dreimal CursorLinks!" Das funktioniert hier, weil du vorher abgezählt hast, dass "bin" drei Zeichen hat, aber wenn du stattdessen "ls /proc" eingegeben hättest, dann passt die 3 nicht mehr, und du müsstest deiner Lösung das Zählen beibringen.
Das sollte nicht das Problem sein. Denn ich muss nicht dreimal CursorLinks drücken, sondern nur einmal Alt-b. Das löst ja die Readline-Funktion backward-word in Bash aus. Ist aber trotzdem keine schöne Lösung, falls diese Tastaturkürzel angepasst wurden. Dann läuft das ins Leere.

Und weiter: Was ich da momentan bei Fish tue, ist noch etwas mehr, als ich oben beschrieben habe (um das Thema nicht zu sehr zu verkomplizieren). Im Grunde könnte es so aussehen:

Code: Alles auswählen

# 1. Fülle die Kommandozeile mit dem Befehl "ls /bin /tmp"
commandline -r "ls /bin /tmp"
# 2. Setze den Cursor auf das Leerzeichen hinter dem /bin (Cursor 7 Positionen nach rechts verschieben)"
commandline -C 7
# 3. Springe ein Wort zurück (Readline Funktion "backward-word")
commandline -f "backward-word"
# 4. Füge ein "s" an der Cursorposition ein
commandline -i "s"
# 5. Führe die Kommandozeile aus
commandline -f execute
Punkt 1 ist auch mit Bash machbar, indem die Variablen READLINE_LINE und READLINE_POINT gesetzt werden.
Die anderen Punkte sind theoretisch mit xdotool lösbar, aber recht unschön. Bei Punkt 2 müsste dann tatsächlich 7 mal die Taste CursorRechts betätigt werden, bei Punkt 3 Alt-b (was nur klappt, wenn das Tastaturkürzel nicht ungepasst wurde), Punkt 4 müsste die Taste "s" gedrückt werden und bei Punkt 5 "Enter".

Schöner wäre es, wenn es ein Tool gäbe, das ähnlich Fishs commandline funktioniert. Scheint aber nicht der Fall zu sein. Die Abhängigkeit von X bei der Verwendung von xdotool ist jedoch ein No-go.

Benutzeravatar
Huo
Beiträge: 825
Registriert: 26.11.2017 14:03:31
Wohnort: Freiburg

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von Huo » 27.03.2025 13:55:10

hupfdule hat geschrieben: ↑ zum Beitrag ↑
27.03.2025 10:06:15
Die Abhängigkeit von X bei der Verwendung von xdotool ist jedoch ein No-go.
Es gibt die Alternative Debianydotool, die völlig ohne graphische Oberfläche auskommt. Aus verschiedenen Gründen scheue ich mich allerdings das Tool zu empfehlen:
  • Es benötigt den Daemon Debianydotoold, den zumindest ich unter Debian nie korrekt zum Laufen bekam (unter Manjaro allerdings schon).
  • Die zu simulierenden Tastenkürzel müssen kryptisch kodiert an ydotool übergeben werden (56:1 bedeutet z.B. Alt-Taste drücken, 56:0 Alt-Taste loslassen).
  • Ich konnte ydotool nicht dazu bringen, das Keyboard-Layout zu erkennen, weshalb teilweise mit type falsche Zeichen ausgegeben werden.

rodney
Beiträge: 404
Registriert: 09.12.2016 04:15:59

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von rodney » 27.03.2025 18:54:42

Eine Debiantmux-Session nutzen und mittels tmux send-keys... die gewuenschten Tasten "senden" waere eine Moeglichkeit die ohne X oder Wayland funktionieren wuerde.

Benutzeravatar
heisenberg
Beiträge: 4236
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: per Skript readline-Kommandos an Bash absetzen

Beitrag von heisenberg » 27.03.2025 19:19:35

Code: Alles auswählen

# 1. Fülle die Kommandozeile mit dem Befehl "ls /bin /tmp"
commandline -r "ls /bin /tmp"
# 2. Setze den Cursor auf das Leerzeichen hinter dem /bin (Cursor 7 Positionen nach rechts verschieben)"
commandline -C 7
Das in die .bashrc + ausführen (source) und dann wird bei [Ctrl]+[o] das Kommando in die Zeile gesetzt und der Cursor am Ende des ersten Verzeichnisses positioniert.

Ich habe die Pos jetzt in Abhängigkeit von dem ersten Verzeichnis berechnet. Man kann die Variable natürlich auch einfach fest auf 7 setzen. Ich möchte mit der aufwändigeren Berechnung eine dynamische Bearbeitung der Kommandozeile demonstrieren.

Code: Alles auswählen

enter_command_and_place_cursor() {

  CMD="ls /irgendwas /tmp"

  # regex: /-Zeichen, gefolgt von nicht-/-Zeichen, gefolgt von einem Leerzeichen, also das Muster des ersten Pfad-Elementes
  regex="/[^/]+ "
  
  # finde den regexp, lese die Position und den gefundenen Text in zwei Variablen ein
  read startpos finding < <( \
  	grep --only-matching --byte-offset --perl-regexp "$regex"  <<<"$CMD" \
        | awk -F: '{print $1,$2}')

  # berechne die Position nach dem ersten Verzeichnis
  ((pos=$startpos+${#finding}))

  # Fülle Ausgabezeile
  READLINE_LINE="$CMD"
  
  # Setze Cursor
  READLINE_POINT=$pos
}

# Tastenkombination definieren
bind -x '"\C-o":enter_command_and_place_cursor'

Das sollte als Vorlage für die restlichen Punkte helfen.

Antworten