aboutsummaryrefslogtreecommitdiff
path: root/src/content/usecases/KeymapUseCase.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/usecases/KeymapUseCase.ts')
-rw-r--r--src/content/usecases/KeymapUseCase.ts87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/content/usecases/KeymapUseCase.ts b/src/content/usecases/KeymapUseCase.ts
new file mode 100644
index 0000000..af0ad77
--- /dev/null
+++ b/src/content/usecases/KeymapUseCase.ts
@@ -0,0 +1,87 @@
+import KeymapRepository, { KeymapRepositoryImpl }
+ from '../repositories/KeymapRepository';
+import SettingRepository, { SettingRepositoryImpl }
+ from '../repositories/SettingRepository';
+import AddonEnabledRepository, { AddonEnabledRepositoryImpl }
+ from '../repositories/AddonEnabledRepository';
+
+import * as operations from '../../shared/operations';
+import { Keymaps } from '../../shared/Settings';
+import Key from '../domains/Key';
+import KeySequence, * as keySequenceUtils from '../domains/KeySequence';
+
+type KeymapEntityMap = Map<KeySequence, operations.Operation>;
+
+const reservedKeymaps: Keymaps = {
+ '<Esc>': { type: operations.CANCEL },
+ '<C-[>': { type: operations.CANCEL },
+};
+
+
+export default class KeymapUseCase {
+ private repository: KeymapRepository;
+
+ private settingRepository: SettingRepository;
+
+ private addonEnabledRepository: AddonEnabledRepository;
+
+ constructor({
+ repository = new KeymapRepositoryImpl(),
+ settingRepository = new SettingRepositoryImpl(),
+ addonEnabledRepository = new AddonEnabledRepositoryImpl(),
+ } = {}) {
+ this.repository = repository;
+ this.settingRepository = settingRepository;
+ this.addonEnabledRepository = addonEnabledRepository;
+ }
+
+ nextOp(key: Key): operations.Operation | null {
+ let sequence = this.repository.enqueueKey(key);
+
+ let keymaps = this.keymapEntityMap();
+ let matched = Array.from(keymaps.keys()).filter(
+ (mapping: KeySequence) => {
+ return mapping.startsWith(sequence);
+ });
+ if (!this.addonEnabledRepository.get()) {
+ // available keymaps are only ADDON_ENABLE and ADDON_TOGGLE_ENABLED if
+ // the addon disabled
+ matched = matched.filter((keymap) => {
+ let type = (keymaps.get(keymap) as operations.Operation).type;
+ return type === operations.ADDON_ENABLE ||
+ type === operations.ADDON_TOGGLE_ENABLED;
+ });
+ }
+ if (matched.length === 0) {
+ // No operations to match with inputs
+ this.repository.clear();
+ return null;
+ } else if (matched.length > 1 ||
+ matched.length === 1 && sequence.length() < matched[0].length()) {
+ // More than one operations are matched
+ return null;
+ }
+ // Exactly one operation is matched
+ let operation = keymaps.get(matched[0]) as operations.Operation;
+ this.repository.clear();
+ return operation;
+ }
+
+ clear(): void {
+ this.repository.clear();
+ }
+
+ private keymapEntityMap(): KeymapEntityMap {
+ let keymaps = {
+ ...this.settingRepository.get().keymaps,
+ ...reservedKeymaps,
+ };
+ let entries = Object.entries(keymaps).map((entry) => {
+ return [
+ keySequenceUtils.fromMapKeys(entry[0]),
+ entry[1],
+ ];
+ }) as [KeySequence, operations.Operation][];
+ return new Map<KeySequence, operations.Operation>(entries);
+ }
+}