LINUX.ORG.RU

Научить консольный софт автокомплитить

 


0

2

Привет. Ребята, интересует вот что - можно ли при помощи readline, предварительно прилинковав к своей софтине, сделать следующее:

  1. в командрой строке некоторый код режима, например ‘p’, ‘Space’
  2. нажимаем ‘Tab’, в итоге имеем «p ‘Tab’»
  3. и вот тут нам вываливается список файлов относительно какой-то заданной начальной директории (например /usr/share/my_app/).

Хочу понять - умеет ли readline, или надо велосипедить? Если не умеет, то не хочется впустую читать доки.

★★

Умеет, наверняка, судя по докам (правда написано всё недоходчиво).

Пока читал, встретил

The function readline() prints a prompt prompt and then reads and returns a single line of text from the user. If prompt is NULL or the empty string, no prompt is displayed. The line readline returns is allocated with malloc(); the caller should free() the line when it has finished with it.

Разве это правильно (вызов malloc и free из возможно разных модулей)? Я ведь могу слинковать std статически, -lreadline динамически. Readline должен давать свою rl_free(). Вроде серьёзная либа с историей, а какие-то детские ошибки. Или какой-то секрет есть?

pavlick ★★
() автор топика
Последнее исправление: pavlick (всего исправлений: 1)

Ты описал свои фантазии на тему решения некой задачи, но не описал саму задачу?

zolden ★★★★★
()
Ответ на: комментарий от zolden

да вроде все описал: вводим в консоли - p, пробел, таб; получаем список файлов из /usr/share/app/mode_p. Вводим в консоли - r, пробел, таб; получаем список файлов из /usr/share/app/mode_r.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

readline умеет и автодополнение, и историю, и редактирование.

returns is allocated with malloc(); the caller should free()

ничего страшного в этом нет.

sergej ★★★★★
()
Ответ на: комментарий от sergej

readline умеет и автодополнение

бесспорно, но надо учесть код команды (p или r) для выбора префикса, по которому лежат файлы (без нажатия Enter).

ничего страшного в этом нет.

Похоже что так и есть, попытался слинковать:

# mv /usr/lib/libreadline.a /usr/lib/libreadline.a~
# g++ m.cc -lreadline -static
/usr/bin/ld: cannot find -lreadline
collect2: error: ld returned 1 exit status
# mv /usr/lib/libreadline.a~ /usr/lib/libreadline.a
# g++ m.cc -lreadline -static

в общем-то не знал, что нельзя сделать статико-динамический винегрет.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

Сделать можно, но не так. -static делает статический бинарь. Убери его и укажи явно путь к libreadline.a вместо -lreadline.

sergej ★★★★★
()
Ответ на: комментарий от sergej

Убери его и укажи явно путь к libreadline.a вместо -lreadline

При таком раскладе, libreadline.a будет линковаться с malloc() из libc.so, а не libc.a

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

просто разработчики софта обычно сопровождают и устанавливают со своей программой файл для bash-completion, наверняка это способ менее трудозатратный

ls /usr/share/bash-completion/completions|wc -l
894
Perspective
()
Ответ на: комментарий от Perspective

Это прикольно, но я ввожу команды в цикле софтины (когда она запущена), там баш комплишен бесполезен ведь.

pavlick ★★
() автор топика
Ответ на: комментарий от Perspective

Я тут подумал, наверное действительно так и сделаю - уберу внутренний цикл с ридлайн и вынесу всё наружу с баш комплишн. Спасибо, направили.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

ну и славненько, ато я уже возмущаться хотел, нахрена тебе интерактивное поведение как, например, у питон-консоли или мускуль-сессии прямо во время работы, но ты и сам догадался.

deep-purple ★★★★★
()
Ответ на: комментарий от pavlick

При таком раскладе, libreadline.a будет линковаться с malloc() из libc.so, а не libc.a

Нет. С чего бы? Но даже если гипотетически это каким-то чудесным образом произойдёт, что в этом плохого?

sergej ★★★★★
()

На случай, если кто-то придёт сюда за ответом на ОП: можно задать rl_attempted_completion_function, в которой смотреть на значение rl_line_buffer, а дальше rl_filename_completion_function после chdir(), наверное, сработает.

xaizek ★★★★★
()
Ответ на: комментарий от sergej

Нет. С чего бы?

Не пойму, что в этом удивительного?

#include <iostream>
#include <readline/readline.h>
int main()
{
    readline("enter val: "); // не заходим в первый, пропустим стадию переразмещений
    readline("enter val: ");
    readline("enter val: ");
}

$ g++ -g m.cc /usr/lib/libreadline.a /usr/lib/libncursesw.a

(gdb) b main
# пропускаем первый вызов readline
(gdb) b malloc
(gdb) c
(gdb) disassemble
Dump of assembler code for function __GI___libc_malloc:
=> 0x00007ffff7ab2770 <+0>:     mov    0x132769(%rip),%rax        # 0x7ffff7be4ee0
...
(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
...
0x00007ffff7a4e340  0x00007ffff7b95fab  Yes         /usr/lib/libc.so.6

Не сложно заметить, что попали в динамическую libc.so

Но даже если гипотетически это каким-то чудесным образом произойдёт, что в этом плохого?

Нет в этом ничего плохого, это наоборот - хорошо. Не должно быть в одной программе несколько версий libc, нельзя в одной делать malloc, а в другой free. Когда я в посте выше попытался заставить сделать это, gcc отказался стрелять мне в ноги, что стало для меня открытием.

pavlick ★★
() автор топика
Ответ на: комментарий от xaizek

спасибо, для общего развития тоже гляну.

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick

а, это я неправильно прочитал сообщение и судя по коменту «Щито?» не я один :)

sergej ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.