public void SetSymbolShortcut(KalkShortcut shortcut) { if (shortcut == null) { throw new ArgumentNullException(nameof(shortcut)); } RemoveShortcut(shortcut.Name); Add(shortcut.Name, shortcut); foreach (KalkShortcutKeySequence shortcutKey in shortcut.Keys) { var map = ShortcutKeyMap; KalkConsoleKey consoleKey = default; for (int i = 0; i < shortcutKey.Keys.Count; i++) { if (i > 0) { if (!map.TryGetShortcut(consoleKey, out var newMap) || !(newMap is KalkShortcutKeyMap)) { newMap = new KalkShortcutKeyMap(); map[consoleKey] = newMap; } map = (KalkShortcutKeyMap)newMap; } consoleKey = shortcutKey.Keys[i]; } map[consoleKey] = shortcutKey.Expression; } }
public void RemoveShortcut(string name) { if (!TryGetValue(name, out var shortcut)) { return; } Remove(name); foreach (KalkShortcutKeySequence shortcutKey in shortcut.Keys) { var map = ShortcutKeyMap; KalkConsoleKey consoleKey = default; for (int i = 0; i < shortcutKey.Keys.Count; i++) { if (i > 0) { if (!map.TryGetShortcut(consoleKey, out var newMap) || !(newMap is KalkShortcutKeyMap)) { continue; } map = (KalkShortcutKeyMap)newMap; } consoleKey = shortcutKey.Keys[i]; } map.Remove(consoleKey); } // Cleanup all maps to remove empty ones CleanupMap(ShortcutKeyMap); }
public static List <KalkShortcutKeySequence> Parse(ScriptExpression keys, ScriptExpression expression) { if (keys == null) { throw new ArgumentNullException(nameof(keys)); } var keyAsString = keys is ScriptLiteral literal && literal.Value is string strValue? strValue : keys.ToString(); var keySequencesAsText = keyAsString.Split(',', StringSplitOptions.RemoveEmptyEntries); var keySequences = new List <KalkShortcutKeySequence>(); foreach (var keySequence in keySequencesAsText) { var keyList = keySequence.Split(' ', StringSplitOptions.RemoveEmptyEntries); var resultKeys = new List <KalkConsoleKey>(); foreach (var keyText in keyList) { try { var key = KalkConsoleKey.Parse(keyText); resultKeys.Add(key); } catch (Exception ex) { throw new ScriptRuntimeException(keys.Span, $"Unable to parse key. Reason: {ex.Message}"); } } keySequences.Add(new KalkShortcutKeySequence(resultKeys, expression)); } return(keySequences); }
internal bool OnKey(ConsoleKeyInfo arg, ConsoleText line, ref int cursorIndex) { bool resetMap = true; bool resetCompletion = true; try { bool hasShift = (arg.Modifiers & ConsoleModifiers.Shift) != 0; // For now, we discard SHIFT entirely, as it is handled separately for range selection // TODO: we should handle them not differently from ctrl/alt, but it's complicated arg = new ConsoleKeyInfo(arg.KeyChar, arg.Key, false, (arg.Modifiers & ConsoleModifiers.Alt) != 0, (arg.Modifiers & ConsoleModifiers.Control) != 0); KalkConsoleKey kalkKey = arg; if (cursorIndex >= 0 && cursorIndex <= line.Count) { if (_currentShortcutKeyMap.TryGetValue(kalkKey, out var value)) { if (value is KalkShortcutKeyMap map) { _currentShortcutKeyMap = map; resetMap = false; // we don't reset if } else { var expression = (ScriptExpression)value; var result = EvaluateExpression(expression); if (result is KalkActionObject command) { // Particular case the completion action, we handle it here if (command.Action == "completion") { // In case of shift we go backward if (OnCompletionRequested(hasShift, line, ref cursorIndex)) { resetCompletion = false; return(true); } } else if (OnAction != null) { command.Call(OnAction); } } else if (result != null) { var resultStr = ObjectToString(result); line.Insert(cursorIndex, resultStr); cursorIndex += resultStr.Length; } } return(true); } } } finally { if (resetMap) { // Restore the root key map in case of an error. _currentShortcutKeyMap = Shortcuts.ShortcutKeyMap; } if (resetCompletion) { ResetCompletion(); } } return(false); }