diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/content/InputDriver.ts | 6 | ||||
| -rw-r--r-- | src/content/actions/index.ts | 4 | ||||
| -rw-r--r-- | src/content/actions/input.ts | 4 | ||||
| -rw-r--r-- | src/content/client/FollowMasterClient.ts | 2 | ||||
| -rw-r--r-- | src/content/components/common/follow.ts | 2 | ||||
| -rw-r--r-- | src/content/components/common/index.ts | 12 | ||||
| -rw-r--r-- | src/content/components/common/keymapper.ts | 87 | ||||
| -rw-r--r-- | src/content/components/common/mark.ts | 6 | ||||
| -rw-r--r-- | src/content/controllers/KeymapController.ts | 2 | ||||
| -rw-r--r-- | src/content/controllers/MarkKeyController.ts | 4 | ||||
| -rw-r--r-- | src/content/domains/Key.ts (renamed from src/shared/utils/keys.ts) | 47 | ||||
| -rw-r--r-- | src/content/domains/KeySequence.ts | 64 | ||||
| -rw-r--r-- | src/content/reducers/input.ts | 4 | ||||
| -rw-r--r-- | src/content/repositories/KeymapRepository.ts | 11 | ||||
| -rw-r--r-- | src/content/usecases/KeymapUseCase.ts | 35 | 
15 files changed, 115 insertions, 175 deletions
diff --git a/src/content/InputDriver.ts b/src/content/InputDriver.ts index 09648c1..cddc825 100644 --- a/src/content/InputDriver.ts +++ b/src/content/InputDriver.ts @@ -1,5 +1,5 @@  import * as dom from '../shared/utils/dom'; -import * as keys from '../shared/utils/keys'; +import Key, * as keys from './domains/Key';  const cancelKey = (e: KeyboardEvent): boolean => {    return e.key === 'Escape' || e.key === '[' && e.ctrlKey; @@ -8,7 +8,7 @@ const cancelKey = (e: KeyboardEvent): boolean => {  export default class InputDriver {    private pressed: {[key: string]: string} = {}; -  private onKeyListeners: ((key: keys.Key) => boolean)[] = []; +  private onKeyListeners: ((key: Key) => boolean)[] = [];    constructor(target: HTMLElement) {      this.pressed = {}; @@ -19,7 +19,7 @@ export default class InputDriver {      target.addEventListener('keyup', this.onKeyUp.bind(this));    } -  onKey(cb: (key: keys.Key) => boolean) { +  onKey(cb: (key: Key) => boolean) {      this.onKeyListeners.push(cb);    } diff --git a/src/content/actions/index.ts b/src/content/actions/index.ts index eb826fc..49f6484 100644 --- a/src/content/actions/index.ts +++ b/src/content/actions/index.ts @@ -1,5 +1,5 @@  import Redux from 'redux'; -import * as keyUtils from '../../shared/utils/keys'; +import Key from '../domains/Key';  // User input  export const INPUT_KEY_PRESS = 'input.key.press'; @@ -25,7 +25,7 @@ export const NOOP = 'noop';  export interface InputKeyPressAction extends Redux.Action {    type: typeof INPUT_KEY_PRESS; -  key: keyUtils.Key; +  key: Key;  }  export interface InputClearKeysAction extends Redux.Action { diff --git a/src/content/actions/input.ts b/src/content/actions/input.ts index 1df6452..24dbb99 100644 --- a/src/content/actions/input.ts +++ b/src/content/actions/input.ts @@ -1,7 +1,7 @@  import * as actions from './index'; -import * as keyUtils from '../../shared/utils/keys'; +import Key from '../domains/Key'; -const keyPress = (key: keyUtils.Key): actions.InputAction => { +const keyPress = (key: Key): actions.InputAction => {    return {      type: actions.INPUT_KEY_PRESS,      key, diff --git a/src/content/client/FollowMasterClient.ts b/src/content/client/FollowMasterClient.ts index 464b52f..c841902 100644 --- a/src/content/client/FollowMasterClient.ts +++ b/src/content/client/FollowMasterClient.ts @@ -1,5 +1,5 @@  import * as messages from '../../shared/messages'; -import { Key } from '../../shared/utils/keys'; +import Key from '../domains/Key';  export default interface FollowMasterClient {    startFollow(newTab: boolean, background: boolean): void; diff --git a/src/content/components/common/follow.ts b/src/content/components/common/follow.ts index e0003e3..413244e 100644 --- a/src/content/components/common/follow.ts +++ b/src/content/components/common/follow.ts @@ -1,7 +1,7 @@  import MessageListener from '../../MessageListener';  import { LinkHint, InputHint } from '../../presenters/Hint';  import * as messages from '../../../shared/messages'; -import { Key } from '../../../shared/utils/keys'; +import Key from '../../domains/Key';  import TabsClient, { TabsClientImpl } from '../../client/TabsClient';  import FollowMasterClient, { FollowMasterClientImpl }    from '../../client/FollowMasterClient'; diff --git a/src/content/components/common/index.ts b/src/content/components/common/index.ts index c74020e..1aacf51 100644 --- a/src/content/components/common/index.ts +++ b/src/content/components/common/index.ts @@ -1,11 +1,11 @@  import InputDriver from './../../InputDriver';  import FollowComponent from './follow';  import MarkComponent from './mark'; -import KeymapperComponent from './keymapper'; +// import KeymapperComponent from './keymapper';  import * as messages from '../../../shared/messages';  import MessageListener from '../../MessageListener';  import * as blacklists from '../../../shared/blacklists'; -import * as keys from '../../../shared/utils/keys'; +import Key from '../../domains/Key';  import AddonEnabledUseCase from '../../usecases/AddonEnabledUseCase';  import SettingUseCase from '../../usecases/SettingUseCase'; @@ -18,11 +18,11 @@ export default class Common {      const input = new InputDriver(win.document.body);      const follow = new FollowComponent();      const mark = new MarkComponent(store); -    const keymapper = new KeymapperComponent(store); +    // const keymapper = new KeymapperComponent(store); -    input.onKey((key: keys.Key) => follow.key(key)); -    input.onKey((key: keys.Key) => mark.key(key)); -    input.onKey((key: keys.Key) => keymapper.key(key)); +    input.onKey((key: Key) => follow.key(key)); +    input.onKey((key: Key) => mark.key(key)); +    // input.onKey((key: Key) => keymapper.key(key));      this.reloadSettings(); diff --git a/src/content/components/common/keymapper.ts b/src/content/components/common/keymapper.ts deleted file mode 100644 index c901ffe..0000000 --- a/src/content/components/common/keymapper.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as inputActions from '../../actions/input'; -import * as operationActions from '../../actions/operation'; -import * as operations from '../../../shared/operations'; -import * as keyUtils from '../../../shared/utils/keys'; - -import AddonEnabledUseCase from '../../usecases/AddonEnabledUseCase'; -import { SettingRepositoryImpl } from '../../repositories/SettingRepository'; -import { Keymaps } from '../../../shared/Settings'; - -type KeymapEntityMap = Map<keyUtils.Key[], operations.Operation>; - -let addonEnabledUseCase = new AddonEnabledUseCase(); -let settingRepository = new SettingRepositoryImpl(); - -const reservedKeymaps: Keymaps = { -  '<Esc>': { type: operations.CANCEL }, -  '<C-[>': { type: operations.CANCEL }, -}; - -const mapStartsWith = ( -  mapping: keyUtils.Key[], -  keys: keyUtils.Key[], -): boolean => { -  if (mapping.length < keys.length) { -    return false; -  } -  for (let i = 0; i < keys.length; ++i) { -    if (!keyUtils.equals(mapping[i], keys[i])) { -      return false; -    } -  } -  return true; -}; - -export default class KeymapperComponent { -  private store: any; - -  constructor(store: any) { -    this.store = store; -  } - -  key(key: keyUtils.Key): boolean { -    this.store.dispatch(inputActions.keyPress(key)); - -    let input = this.store.getState().input; -    let keymaps = this.keymapEntityMap(); -    let matched = Array.from(keymaps.keys()).filter( -      (mapping: keyUtils.Key[]) => { -        return mapStartsWith(mapping, input.keys); -      }); -    if (!addonEnabledUseCase.getEnabled()) { -      // available keymaps are only ADDON_ENABLE and ADDON_TOGGLE_ENABLED if -      // the addon disabled -      matched = matched.filter((keys) => { -        let type = (keymaps.get(keys) as operations.Operation).type; -        return type === operations.ADDON_ENABLE || -          type === operations.ADDON_TOGGLE_ENABLED; -      }); -    } -    if (matched.length === 0) { -      this.store.dispatch(inputActions.clearKeys()); -      return false; -    } else if (matched.length > 1 || -      matched.length === 1 && input.keys.length < matched[0].length) { -      return true; -    } -    let operation = keymaps.get(matched[0]) as operations.Operation; -    let act = operationActions.exec(operation); -    this.store.dispatch(act); -    this.store.dispatch(inputActions.clearKeys()); -    return true; -  } - -  private keymapEntityMap(): KeymapEntityMap { -    let keymaps = { -      ...settingRepository.get().keymaps, -      ...reservedKeymaps, -    }; -    let entries = Object.entries(keymaps).map((entry) => { -      return [ -        keyUtils.fromMapKeys(entry[0]), -        entry[1], -      ]; -    }) as [keyUtils.Key[], operations.Operation][]; -    return new Map<keyUtils.Key[], operations.Operation>(entries); -  } -} diff --git a/src/content/components/common/mark.ts b/src/content/components/common/mark.ts index eec95d6..058b873 100644 --- a/src/content/components/common/mark.ts +++ b/src/content/components/common/mark.ts @@ -1,12 +1,12 @@  import * as markActions from '../../actions/mark';  import * as consoleFrames from '../..//console-frames'; -import * as keyUtils from '../../../shared/utils/keys'; +import Key from '../../domains/Key';  import MarkUseCase from '../../usecases/MarkUseCase';  let markUseCase = new MarkUseCase(); -const cancelKey = (key: keyUtils.Key): boolean => { +const cancelKey = (key: Key): boolean => {    return key.key === 'Esc' || key.key === '[' && Boolean(key.ctrlKey);  }; @@ -18,7 +18,7 @@ export default class MarkComponent {    }    // eslint-disable-next-line max-statements -  key(key: keyUtils.Key) { +  key(key: Key) {      let { mark: markState } = this.store.getState();      if (!markState.setMode && !markState.jumpMode) { diff --git a/src/content/controllers/KeymapController.ts b/src/content/controllers/KeymapController.ts index b7a7bc2..424292c 100644 --- a/src/content/controllers/KeymapController.ts +++ b/src/content/controllers/KeymapController.ts @@ -8,7 +8,7 @@ import FocusUseCase from '../usecases/FocusUseCase';  import ClipboardUseCase from '../usecases/ClipboardUseCase';  import BackgroundClient from '../client/BackgroundClient';  import MarkKeyyUseCase from '../usecases/MarkKeyUseCase'; -import { Key } from '../../shared/utils/keys'; +import Key from '../domains/Key';  export default class KeymapController {    private keymapUseCase: KeymapUseCase; diff --git a/src/content/controllers/MarkKeyController.ts b/src/content/controllers/MarkKeyController.ts index 9406fbf..395dee3 100644 --- a/src/content/controllers/MarkKeyController.ts +++ b/src/content/controllers/MarkKeyController.ts @@ -1,6 +1,6 @@  import MarkUseCase from '../usecases/MarkUseCase';  import MarkKeyyUseCase from '../usecases/MarkKeyUseCase'; -import * as keys from '../../shared/utils/keys'; +import Key from '../domains/Key';  export default class MarkKeyController {    private markUseCase: MarkUseCase; @@ -15,7 +15,7 @@ export default class MarkKeyController {      this.markKeyUseCase = markKeyUseCase;    } -  press(key: keys.Key): boolean { +  press(key: Key): boolean {      if (this.markKeyUseCase.isSetMode()) {        this.markUseCase.set(key.key);        this.markKeyUseCase.disableSetMode(); diff --git a/src/shared/utils/keys.ts b/src/content/domains/Key.ts index e9b0365..fbbb4bb 100644 --- a/src/shared/utils/keys.ts +++ b/src/content/domains/Key.ts @@ -1,9 +1,11 @@ -export interface Key { -    key: string; -    shiftKey: boolean | undefined; -    ctrlKey: boolean | undefined; -    altKey: boolean | undefined; -    metaKey: boolean | undefined; +export default interface Key { +  key: string; +  shiftKey?: boolean; +  ctrlKey?: boolean; +  altKey?: boolean; +  metaKey?: boolean; + +  // eslint-disable-next-line semi  }  const modifiedKeyName = (name: string): string => { @@ -18,7 +20,7 @@ const modifiedKeyName = (name: string): string => {    return name;  }; -const fromKeyboardEvent = (e: KeyboardEvent): Key => { +export const fromKeyboardEvent = (e: KeyboardEvent): Key => {    let key = modifiedKeyName(e.key);    let shift = e.shiftKey;    if (key.length === 1 && key.toUpperCase() === key.toLowerCase()) { @@ -36,7 +38,7 @@ const fromKeyboardEvent = (e: KeyboardEvent): Key => {    };  }; -const fromMapKey = (key: string): Key => { +export const fromMapKey = (key: string): Key => {    if (key.startsWith('<') && key.endsWith('>')) {      let inner = key.slice(1, -1);      let shift = inner.includes('S-'); @@ -63,37 +65,10 @@ const fromMapKey = (key: string): Key => {    };  }; -const fromMapKeys = (keys: string): Key[] => { -  const fromMapKeysRecursive = ( -    remainings: string, mappedKeys: Key[], -  ): Key[] => { -    if (remainings.length === 0) { -      return mappedKeys; -    } - -    let nextPos = 1; -    if (remainings.startsWith('<')) { -      let ltPos = remainings.indexOf('>'); -      if (ltPos > 0) { -        nextPos = ltPos + 1; -      } -    } - -    return fromMapKeysRecursive( -      remainings.slice(nextPos), -      mappedKeys.concat([fromMapKey(remainings.slice(0, nextPos))]) -    ); -  }; - -  return fromMapKeysRecursive(keys, []); -}; - -const equals = (e1: Key, e2: Key): boolean => { +export const equals = (e1: Key, e2: Key): boolean => {    return e1.key === e2.key &&      e1.ctrlKey === e2.ctrlKey &&      e1.metaKey === e2.metaKey &&      e1.altKey === e2.altKey &&      e1.shiftKey === e2.shiftKey;  }; - -export { fromKeyboardEvent, fromMapKey, fromMapKeys, equals }; diff --git a/src/content/domains/KeySequence.ts b/src/content/domains/KeySequence.ts new file mode 100644 index 0000000..6a05c2f --- /dev/null +++ b/src/content/domains/KeySequence.ts @@ -0,0 +1,64 @@ +import Key, * as keyUtils from './Key'; + +export default class KeySequence { +  private keys: Key[]; + +  private constructor(keys: Key[]) { +    this.keys = keys; +  } + +  static from(keys: Key[]): KeySequence { +    return new KeySequence(keys); +  } + +  push(key: Key): number { +    return this.keys.push(key); +  } + +  length(): number { +    return this.keys.length; +  } + +  startsWith(o: KeySequence): boolean { +    if (this.keys.length < o.keys.length) { +      return false; +    } +    for (let i = 0; i < o.keys.length; ++i) { +      if (!keyUtils.equals(this.keys[i], o.keys[i])) { +        return false; +      } +    } +    return true; +  } + +  getKeyArray(): Key[] { +    return this.keys; +  } +} + +export const fromMapKeys = (keys: string): KeySequence => { +  const fromMapKeysRecursive = ( +    remainings: string, mappedKeys: Key[], +  ): Key[] => { +    if (remainings.length === 0) { +      return mappedKeys; +    } + +    let nextPos = 1; +    if (remainings.startsWith('<')) { +      let ltPos = remainings.indexOf('>'); +      if (ltPos > 0) { +        nextPos = ltPos + 1; +      } +    } + +    return fromMapKeysRecursive( +      remainings.slice(nextPos), +      mappedKeys.concat([keyUtils.fromMapKey(remainings.slice(0, nextPos))]) +    ); +  }; + +  let data = fromMapKeysRecursive(keys, []); +  return KeySequence.from(data); +}; + diff --git a/src/content/reducers/input.ts b/src/content/reducers/input.ts index 35b9075..800a8f0 100644 --- a/src/content/reducers/input.ts +++ b/src/content/reducers/input.ts @@ -1,8 +1,8 @@  import * as actions from '../actions'; -import * as keyUtils from '../../shared/utils/keys'; +import Key from '../domains/Key';  export interface State { -  keys: keyUtils.Key[], +  keys: Key[],  }  const defaultState: State = { diff --git a/src/content/repositories/KeymapRepository.ts b/src/content/repositories/KeymapRepository.ts index 081cc54..770ba0b 100644 --- a/src/content/repositories/KeymapRepository.ts +++ b/src/content/repositories/KeymapRepository.ts @@ -1,23 +1,24 @@ -import { Key } from '../../shared/utils/keys'; +import Key from '../domains/Key'; +import KeySequence from '../domains/KeySequence';  export default interface KeymapRepository { -  enqueueKey(key: Key): Key[]; +  enqueueKey(key: Key): KeySequence;    clear(): void;    // eslint-disable-next-line semi  } -let current: Key[] = []; +let current: KeySequence = KeySequence.from([]);  export class KeymapRepositoryImpl { -  enqueueKey(key: Key): Key[] { +  enqueueKey(key: Key): KeySequence {      current.push(key);      return current;    }    clear(): void { -    current = []; +    current = KeySequence.from([]);    }  } diff --git a/src/content/usecases/KeymapUseCase.ts b/src/content/usecases/KeymapUseCase.ts index a4f9c36..af0ad77 100644 --- a/src/content/usecases/KeymapUseCase.ts +++ b/src/content/usecases/KeymapUseCase.ts @@ -7,29 +7,16 @@ import AddonEnabledRepository, { AddonEnabledRepositoryImpl }  import * as operations from '../../shared/operations';  import { Keymaps } from '../../shared/Settings'; -import * as keyUtils from '../../shared/utils/keys'; +import Key from '../domains/Key'; +import KeySequence, * as keySequenceUtils from '../domains/KeySequence'; -type KeymapEntityMap = Map<keyUtils.Key[], operations.Operation>; +type KeymapEntityMap = Map<KeySequence, operations.Operation>;  const reservedKeymaps: Keymaps = {    '<Esc>': { type: operations.CANCEL },    '<C-[>': { type: operations.CANCEL },  }; -const mapStartsWith = ( -  mapping: keyUtils.Key[], -  keys: keyUtils.Key[], -): boolean => { -  if (mapping.length < keys.length) { -    return false; -  } -  for (let i = 0; i < keys.length; ++i) { -    if (!keyUtils.equals(mapping[i], keys[i])) { -      return false; -    } -  } -  return true; -};  export default class KeymapUseCase {    private repository: KeymapRepository; @@ -48,13 +35,13 @@ export default class KeymapUseCase {      this.addonEnabledRepository = addonEnabledRepository;    } -  nextOp(key: keyUtils.Key): operations.Operation | null { -    let keys = this.repository.enqueueKey(key); +  nextOp(key: Key): operations.Operation | null { +    let sequence = this.repository.enqueueKey(key);      let keymaps = this.keymapEntityMap();      let matched = Array.from(keymaps.keys()).filter( -      (mapping: keyUtils.Key[]) => { -        return mapStartsWith(mapping, keys); +      (mapping: KeySequence) => { +        return mapping.startsWith(sequence);        });      if (!this.addonEnabledRepository.get()) {        // available keymaps are only ADDON_ENABLE and ADDON_TOGGLE_ENABLED if @@ -70,7 +57,7 @@ export default class KeymapUseCase {        this.repository.clear();        return null;      } else if (matched.length > 1 || -      matched.length === 1 && keys.length < matched[0].length) { +      matched.length === 1 && sequence.length() < matched[0].length()) {        // More than one operations are matched        return null;      } @@ -91,10 +78,10 @@ export default class KeymapUseCase {      };      let entries = Object.entries(keymaps).map((entry) => {        return [ -        keyUtils.fromMapKeys(entry[0]), +        keySequenceUtils.fromMapKeys(entry[0]),          entry[1],        ]; -    }) as [keyUtils.Key[], operations.Operation][]; -    return new Map<keyUtils.Key[], operations.Operation>(entries); +    }) as [KeySequence, operations.Operation][]; +    return new Map<KeySequence, operations.Operation>(entries);    }  }  | 
