Использование реактивного расширения для определенных последовательностей нажатия клавиш?

Я новичок ... или, точнее ... никогда не использовал RX, поэтому мне было интересно, могу ли я использовать его в этой ситуации: я хочу добавить в свое приложение своего рода функцию живых шаблонов Resharper, которая позволяет пользователям вводить короткие последовательности символов, за которыми следуют с помощью [Tab], и мое приложение заменит ранее введенные символы полным текстом, указанным в другом месте.

Теперь у меня есть список массивов символов, каждый из которых представляет одну возможную последовательность. Мне нужны какие-то стоп-слова/клавиши, которые разрывают цепочку (например, пробел). У меня есть событие, которое возникает при каждом нажатии клавиши в моем приложении, теперь (как) я могу использовать RX для наблюдения за этим событием и проверки по этому вышеупомянутому списку, была ли выполнена одна из последовательностей и, наконец, была нажата [Tab]?


person Jörg Battermann    schedule 17.08.2010    source источник


Ответы (1)


Не знаю, поздно ли, но у меня есть для тебя ответ.

Метод расширения Rx, который вам нужно использовать, — BufferWithCount.

Я предполагаю, что вы знаете, как превратить события нажатия клавиш в IObservable<char>.

Итак, если у вас есть список последовательностей символов, которые вы хотите обнаружить, а затем выполнить действие, я предлагаю использовать Dictionary<string, Action> для хранения этих данных, например:

var matches = new Dictionary<string, Action>()
{
    { "ba", () => Console.WriteLine("ba") },
    { "aba", () => Console.WriteLine("aba") },
    { "baa", () => Console.WriteLine("baa") },
    { "abc\t", () => Console.WriteLine("abc\\t") },
};

Итак, вот необходимые запросы Rx (и IEnumerable):

int max =
    matches
    .Select(m => m.Key.Length)
    .Max();

IObservable<string> chords =
    Enumerable
    .Range(2, max - 1)
    .Select(n => keys
        .BufferWithCount(n, 1)
        .Select(cs => new string(cs.ToArray())))
    .Merge();

IObservable<Action> actions =
    chords
    .Where(s => matches.ContainsKey(s))
    .Select(s => matches[s]);

Итак, наконец, у вас есть IObservable<Action>, на который вы можете подписаться, и вы просто вызываете Action.

Если вы хотите проверить, работает ли это, используйте следующий код:

IConnectableObservable<char> keys = "ababc\tdabaababc\tebad"
    .ToObservable()
    .Publish();
//`.Publish()` makes a cold observable become hot,
// but you must call `Connect()` to start producing values.

//insert above `matches` definition here.
//insert above queries here.

actions.Subscribe(a => a());

keys.Connect();

Результат должен быть:

ba
aba
abc\t
ba
aba
baa
ba
aba
abc\t
ba

Наслаждаться!

person Enigmativity    schedule 08.12.2010