Побег косые черты в Баш завершена - PullRequest
5 голосов
/ 02 апреля 2019

Я пытаюсь использовать встроенную команду bash complete, чтобы показать различные опции для команды.

У меня проблемы, когда опция содержит путь, как в -F/dev/null.

В настоящее время я использую

#!/bin/bash

_xyz-completion ()
{
  local cur

  COMPREPLY=()   # Array variable storing the possible completions.
  cur=${COMP_WORDS[COMP_CWORD]}

  case "$cur" in
    -*)
    COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
    ;;
  esac

  return 0
}

complete -F _xyz-completion -o filenames xyz

Если -F уже набрано, то Tab завершит его успешно.

Но если набрать только -, то на вкладке 1016 * отобразится

null -oOption1

Но я ожидаю увидеть

-F / dev / null -oOption1

Я уже пробовал -F\/dev\/null, -F//dev//null, "-F/dev/null" и -F\\\/dev\\\/null

Кажется, это только проблема с отображением, поскольку само завершение работает, как и ожидалось.

Я не вижу, как правильно экранировать косую черту в `-F / dev / null`.


Для комментирования комментариев:

1)

Не берите в голову, это также проблема, если -F заменен не опцией, такой как -Q. - Бенджамин В.

Это не проблема, что -F выглядит как опция для complete, так как он даже не работает, если я изменил его на xOPTION1 xF/dev/null

2)

Мне интересно, что compgen -W "-oOption1 -F / dev / null" - - отображает для вас.

Отображает (как и ожидалось)

-oOption1
-F / DEV / нуль

Как уже упоминалось, -F успешно завершается до -F/dev/null

1 Ответ

3 голосов
/ 06 апреля 2019

Если вы удалите опцию -o filenames из complete, ваш пример будет работать как положено. Что имеет некоторый смысл, поскольку дополнения не являются именами файлов. Это с версией bash 5.0.2 (1).

Итак:

#!/bin/bash

_xyz-completion ()
{
  local cur

  COMPREPLY=()   # Array variable storing the possible completions.
  cur=${COMP_WORDS[COMP_CWORD]}

  case "$cur" in
    -*)
    COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
    ;;
  esac

  return 0
}

complete -F _xyz-completion xyz

Это определенно похоже на ошибку, что это урезало бы часть завершения, когда есть слэши. И только при отображении вариантов, фактическое завершение работает правильно.

РЕДАКТИРОВАТЬ:

После более подробного изучения опция filenames используется для экранирования строк, которые могут содержать пробелы или другие символы пробела. В основном очистка имен файлов для оболочки. Из Программируемой страницы завершения встроенного руководства

-o filenames

Скажите Readline, что compspec генерирует имена файлов, поэтому он может выполнять любую специфичную для имени файла обработку (например, добавлять косую черту в имена каталогов, заключать в кавычки специальные символы или подавлять конечные пробелы). Эта опция предназначена для использования с функциями оболочки, указанными с -F.

Очевидно, это включает в себя удаление всего до и включая последнюю косую черту.

EDIT2:

Вот комментарий из источника readline, который bash использует для завершения имени файла. Я получил это из репозитория bash на https://git.savannah.gnu.org/git/bash.git). Мастер, так что 5.0 патч 3 на момент написания.

. / Lib / readline / complete.c строка 697

/* Return the portion of PATHNAME that should be output when listing
   possible completions.  If we are hacking filename completion, we
   are only interested in the basename, the portion following the
   final slash.  Otherwise, we return what we were passed.  Since
   printing empty strings is not very informative, if we're doing
   filename completion, and the basename is the empty string, we look
   for the previous slash and return the portion following that.  If
   there's no previous slash, we just return what we were passed. */
static char *
printable_part (char *pathname)

Для завершения имени файла он хочет напечатать только базовое имя, все после последней косой черты.

...