Python + readline + auto -completion (tab): почему тире и вопросительные знаки рассматриваются как разделители слов?

Здравствуйте, программисты и отважные пользователи GNU-readline,
Несколько месяцев назад я начал использовать модуль readline Python (2.7.1) для оболочки -подобное приложение, которое я написал. Приложение не имеет ничего общего с файлами и файловыми системами - это специализированное решение для проприетарного программного обеспечения для управления.

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

Предоставляются следующие значения для автозаполнения:

aaa0   aaa1   aaa2   bbb_0  bbb_1  bbb_2
ccc-0  ccc-1  ccc-2  ddd?0  ddd?1  ddd?2

...тогда неожиданное поведение выглядит следующим образом (за каждым действием следует результат, а вертикальная черта | представляет курсор):

  1. Введите 'b'.
    Input> b |
  2. Нажмите TAB (который в моей конфигурации привязан к действию автозаполнения).
    Input> bbb_ |
  3. Нажмите TAB еще раз. Ваш текст останется прежним, но вы получите следующую подсказку:
    bbb_0 bbb_1 bbb_2
    Ввод> bbb_ |
  4. Введите «0» и нажмите TAB.
    bbb_0 bbb_1 bbb_2
    Ввод> bbb_0 |

    Обратите внимание на пробел между символом «0» и курсором (это объясняется в фрагменте кода ниже).
    Пока все хорошо, и попытка сделать то же самое с 'a' приведет к аналогичному результату, только без подчеркивания (aaa0, aaa1, aaa2).
  5. Начните заново и введите «c».
    Input> c
  6. Нажмите TAB.
    Input> ccc-
  7. Снова нажмите TAB.
    aaa0 aaa1 aaa2 bbb_0 bbb_1 bbb_2 ccc-0 ccc-1 ccc-2 ddd? 0 ddd? 1 ddd? 2
    Input> ccc- |

    Это первая половина моя проблема. Отображаются все значения, а не только значения, начинающиеся с «ccc-».
  8. Введите «0» и нажмите TAB.
    aaa0 aaa1 aaa2 bbb_0 bbb_1 bbb_2 ccc-0 ccc-1 ccc-2 ddd? 0 ddd? 1 ddd? 2
    Input> ccc-0 |

    Это вторая половина Видите ли, в моей проблеме нет пробела между символом «0» и курсором (опять же, приведенный ниже фрагмент объясняет, почему должен быть пробел). Фактически, нажатие TAB не меняет текст и не отображает подсказку, и дальнейшие нажатия TAB ведут себя так же.

На практике то, что происходит на шаге 7, является недоразумением .Строка чтения "ошибочно" принимает символ тире '-' как разделитель слов (и то же самое касается символа вопросительного знака '?', Если вы попробуете автозаполнение 'ddd?'; Другими распространенными разделителями слов являются, например: пробел, табуляция, '='). Итак, поскольку текущий строчный буфер заканчивается разделителем слов, пришло время для нового слова, верно? Следовательно, на шаге 7 (где мы находимся) все значения отображаются при нажатии TAB.

На шаге 8, когда строка выглядит как « Input> ccc-0 | », нажатие TAB не имеет никакого эффекта, потому что тире, будучи разделителем слов, разделяет строку на два слова: ccc и 0. Итак, слово, которое нужно дополнить, - это «0», но, увы, ни одно из возможных значений не начинается с «0», так что никакого эффекта.

К сожалению, здесь нет правильного или неправильного. Например, в моем приложении знак равенства «=» на самом деле является разделителем слов, а тире «-» - нет. Я полагаю, это должно быть вопросом конфигурации, но я не нашел способа настроить, какие символы разделяют слова. Вот с чем мне нужна помощь.

Я человек слова, вот фрагмент кода, который я обещал:

import readline
values = ['aaa0',  'aaa1',  'aaa2',  'bbb_0', 'bbb_1', 'bbb_2',
          'ccc-0', 'ccc-1', 'ccc-2', 'ddd?0', 'ddd?1', 'ddd?2']
def complete(text, state):
    matches = [v for v in values if v.startswith(text)]
    if len(matches) == 1 and matches[0] == text:
        # Add space if the current text is the same as the only match
        return "{} ".format(matches[0]) if state == 0 else None
    if state >= len(matches):
        return None
    return matches[state]
readline.set_completer(complete)
for line in ("tab: complete", "set show-all-if-unmodified on"):
    readline.parse_and_bind(line)
raw_input("Input> ")

Мальчики и девочки, пожалуйста, помогите! Я обещаю быть очень благодарным и даже вернуть услугу. : )

Заранее большое спасибо, Амнон Дж.

5
задан Amnon Grossman 24 September 2011 в 21:58
поделиться