epiq 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/app.js +10 -4
  2. package/dist/board/components/Board.js +4 -12
  3. package/dist/board/components/CommandLine.d.ts +2 -0
  4. package/dist/board/components/CommandLine.js +26 -0
  5. package/dist/{components/Help.d.ts → board/components/ContextBar.d.ts} +1 -1
  6. package/dist/board/components/ContextBar.js +17 -0
  7. package/dist/board/components/Help.js +19 -12
  8. package/dist/board/components/Swimlane.d.ts +1 -0
  9. package/dist/board/components/Swimlane.js +6 -4
  10. package/dist/board/components/Swimlanes.js +8 -11
  11. package/dist/board/components/TextInput.d.ts +6 -0
  12. package/dist/board/components/TextInput.js +9 -0
  13. package/dist/board/components/TicketListItem.js +6 -5
  14. package/dist/board/components/TicketUI.js +6 -7
  15. package/dist/board/hints/hints.d.ts +7 -0
  16. package/dist/board/hints/hints.js +21 -0
  17. package/dist/board/mock/board.js +73 -27
  18. package/dist/cli.d.ts +2 -1
  19. package/dist/cli.js +21 -39
  20. package/dist/debug-logger.d.ts +2 -0
  21. package/dist/debug-logger.js +16 -0
  22. package/dist/init-project.d.ts +1 -0
  23. package/dist/init-project.js +1 -0
  24. package/dist/navigation/actions/add/add-actions.d.ts +2 -0
  25. package/dist/navigation/actions/add/add-actions.js +25 -0
  26. package/dist/navigation/actions/add/add-item-actions.d.ts +2 -0
  27. package/dist/navigation/actions/add/add-item-actions.js +25 -0
  28. package/dist/navigation/actions/add-item/add-item-actions.d.ts +3 -0
  29. package/dist/navigation/actions/add-item/add-item-actions.js +45 -0
  30. package/dist/navigation/actions/board-action-map.d.ts +10 -0
  31. package/dist/navigation/actions/board-action-map.js +12 -0
  32. package/dist/navigation/actions/default/default-action-utils.d.ts +8 -0
  33. package/dist/navigation/actions/default/default-action-utils.js +101 -0
  34. package/dist/navigation/actions/default/default-actions.d.ts +2 -0
  35. package/dist/navigation/actions/default/default-actions.js +64 -0
  36. package/dist/navigation/actions/default/navigation-action-utils.d.ts +16 -0
  37. package/dist/navigation/actions/default/navigation-action-utils.js +109 -0
  38. package/dist/navigation/actions/input/command-line-input.d.ts +2 -0
  39. package/dist/navigation/actions/input/command-line-input.js +18 -0
  40. package/dist/navigation/actions/input/input-actions-utils.d.ts +8 -0
  41. package/dist/navigation/actions/input/input-actions-utils.js +47 -0
  42. package/dist/navigation/actions/input/input-actions.d.ts +2 -0
  43. package/dist/navigation/actions/input/input-actions.js +44 -0
  44. package/dist/navigation/actions/move/move-actions-routes.d.ts +4 -0
  45. package/dist/navigation/actions/move/move-actions-routes.js +55 -0
  46. package/dist/navigation/actions/move/move-actions-utils.d.ts +4 -0
  47. package/dist/navigation/actions/move/move-actions-utils.js +66 -0
  48. package/dist/navigation/actions/move/move-actions.d.ts +4 -0
  49. package/dist/navigation/actions/move/move-actions.js +59 -0
  50. package/dist/{lib/utils/default-action-utils.d.ts → navigation/actions/navigate/navigation-action-utils.d.ts} +1 -1
  51. package/dist/navigation/actions/navigate/navigation-actions.d.ts +2 -0
  52. package/dist/navigation/actions/navigate/navigation-actions.js +78 -0
  53. package/dist/navigation/command-line/command-line-actions.d.ts +2 -0
  54. package/dist/navigation/command-line/command-line-actions.js +32 -0
  55. package/dist/navigation/command-line/command-line-intent.d.ts +7 -0
  56. package/dist/navigation/command-line/command-line-intent.js +29 -0
  57. package/dist/navigation/command-line/command-line-sequence-actions.d.ts +2 -0
  58. package/dist/navigation/command-line/command-line-sequence-actions.js +44 -0
  59. package/dist/navigation/command-line/command-line-sequence-intent.d.ts +8 -0
  60. package/dist/navigation/command-line/command-line-sequence-intent.js +32 -0
  61. package/dist/navigation/command-line/commands.d.ts +2 -0
  62. package/dist/navigation/command-line/commands.js +58 -0
  63. package/dist/navigation/keypress-listener.d.ts +1 -0
  64. package/dist/navigation/keypress-listener.js +33 -0
  65. package/dist/navigation/model/action-map.model.d.ts +17 -5
  66. package/dist/navigation/model/action-map.model.js +2 -0
  67. package/dist/navigation/model/navigation-ctx.model.d.ts +1 -16
  68. package/dist/navigation/model/navigation-ctx.model.js +0 -1
  69. package/dist/navigation/model/navigation-tree.model.d.ts +3 -1
  70. package/dist/navigation/navigation.d.ts +3 -10
  71. package/dist/navigation/navigation.js +74 -66
  72. package/dist/navigation/state/command-line.state.d.ts +18 -0
  73. package/dist/navigation/state/command-line.state.js +60 -0
  74. package/dist/navigation/state/state.d.ts +18 -9
  75. package/dist/navigation/state/state.js +36 -8
  76. package/dist/navigation/utils/get-command-line-intent.d.ts +3 -0
  77. package/dist/navigation/utils/get-command-line-intent.js +17 -0
  78. package/dist/navigation/utils/getKeyIntent.d.ts +5 -0
  79. package/dist/navigation/utils/getKeyIntent.js +71 -0
  80. package/dist/navigation/utils/key-intent.d.ts +21 -12
  81. package/dist/navigation/utils/key-intent.js +104 -50
  82. package/package.json +3 -3
  83. package/dist/board/actions/board-action-map.d.ts +0 -11
  84. package/dist/board/actions/board-action-map.js +0 -11
  85. package/dist/board/actions/move-actions-routes.d.ts +0 -4
  86. package/dist/board/actions/move-actions-routes.js +0 -31
  87. package/dist/board/actions/move-actions.d.ts +0 -5
  88. package/dist/board/actions/move-actions.js +0 -49
  89. package/dist/board/board-action-map.d.ts +0 -9
  90. package/dist/board/board-action-map.js +0 -7
  91. package/dist/board/move-actions-routes.d.ts +0 -4
  92. package/dist/board/move-actions-routes.js +0 -31
  93. package/dist/board/move-actions.d.ts +0 -5
  94. package/dist/board/move-actions.js +0 -49
  95. package/dist/components/Board.d.ts +0 -6
  96. package/dist/components/Board.js +0 -15
  97. package/dist/components/Help.js +0 -21
  98. package/dist/components/Swimlane.d.ts +0 -8
  99. package/dist/components/Swimlane.js +0 -10
  100. package/dist/components/TicketListItem.d.ts +0 -6
  101. package/dist/components/TicketListItem.js +0 -12
  102. package/dist/lib/actions/board-action-map.d.ts +0 -9
  103. package/dist/lib/actions/board-action-map.js +0 -7
  104. package/dist/lib/actions/move-actions-utils.d.ts +0 -5
  105. package/dist/lib/actions/move-actions-utils.js +0 -43
  106. package/dist/lib/actions/move-actions.d.ts +0 -4
  107. package/dist/lib/actions/move-actions.js +0 -31
  108. package/dist/lib/board/board-action-map.d.ts +0 -9
  109. package/dist/lib/board/board-action-map.js +0 -7
  110. package/dist/lib/board/move-actions-routes.d.ts +0 -4
  111. package/dist/lib/board/move-actions-routes.js +0 -31
  112. package/dist/lib/board/move-actions.d.ts +0 -5
  113. package/dist/lib/board/move-actions.js +0 -43
  114. package/dist/lib/board-utils.d.ts +0 -7
  115. package/dist/lib/board-utils.js +0 -33
  116. package/dist/lib/default-actions-routes.d.ts +0 -4
  117. package/dist/lib/default-actions-routes.js +0 -47
  118. package/dist/lib/default-actions.d.ts +0 -4
  119. package/dist/lib/default-actions.js +0 -47
  120. package/dist/lib/navigation-context.d.ts +0 -16
  121. package/dist/lib/navigation.d.ts +0 -10
  122. package/dist/lib/navigation.js +0 -74
  123. package/dist/lib/render-utils.d.ts +0 -10
  124. package/dist/lib/render-utils.js +0 -12
  125. package/dist/lib/state.d.ts +0 -8
  126. package/dist/lib/state.js +0 -8
  127. package/dist/lib/types/action-map.model.d.ts +0 -14
  128. package/dist/lib/types/action-map.model.js +0 -4
  129. package/dist/lib/types/board.model.d.ts +0 -21
  130. package/dist/lib/types/board.model.js +0 -5
  131. package/dist/lib/types/navigation.model.d.ts +0 -9
  132. package/dist/lib/utils/array-utils.d.ts +0 -5
  133. package/dist/lib/utils/array-utils.js +0 -7
  134. package/dist/lib/utils/default-action-utils.js +0 -50
  135. package/dist/lib/utils/default-actions.d.ts +0 -7
  136. package/dist/lib/utils/default-actions.js +0 -50
  137. package/dist/lib/utils/key-intent.d.ts +0 -16
  138. package/dist/lib/utils/key-intent.js +0 -65
  139. package/dist/lib/utils.d.ts +0 -10
  140. package/dist/lib/utils.js +0 -12
  141. package/dist/mock/board.d.ts +0 -2
  142. package/dist/mock/board.js +0 -139
  143. package/dist/navigation/actions/default-actions-routes.d.ts +0 -4
  144. package/dist/navigation/actions/default-actions-routes.js +0 -47
  145. package/dist/navigation/actions/default-actions.d.ts +0 -7
  146. /package/dist/navigation/actions/{default-actions.js → navigate/navigation-action-utils.js} +0 -0
  147. /package/dist/{lib/navigation-context.js → navigation/navigation-ctx.d.ts} +0 -0
  148. /package/dist/{lib/types/navigation.model.js → navigation/navigation-ctx.js} +0 -0
@@ -1,9 +1,11 @@
1
+ import { BoardItemTypes } from '../../board/model/board.model.js';
1
2
  export type NavigationTree<TMeta = Record<string, unknown>> = {
2
3
  id: string;
3
4
  isSelected: boolean;
4
5
  childrenRenderAxis: 'vertical' | 'horizontal';
5
6
  name: string;
7
+ description?: string;
6
8
  children: NavigationTree<unknown>[];
7
- actionContext: string;
9
+ actionContext: (typeof BoardItemTypes)[keyof typeof BoardItemTypes];
8
10
  enableChildNavigationAcrossContainers?: boolean;
9
11
  } & TMeta;
@@ -1,10 +1,3 @@
1
- import { NavigationTree } from './model/navigation-tree.model.js';
2
- export declare function navigate<T extends NavigationTree>({ index, breadCrumb, callbacks, }: {
3
- index: number;
4
- breadCrumb: Array<NavigationTree<NavigationTree>>;
5
- callbacks: Partial<{
6
- render: () => void;
7
- onSelectChange: (s: T['children'][number], breadCrumb: T['children']) => void;
8
- onConfirm: (s: T['children'][number]) => void;
9
- }>;
10
- }): void;
1
+ import { NavigateUtils } from './model/navigation-ctx.model.js';
2
+ export declare const navigationUtils: NavigateUtils;
3
+ export declare function initListeners(): void;
@@ -1,74 +1,82 @@
1
1
  import readline from 'readline';
2
- import { navigationState } from './state/state.js';
2
+ import { appState, patchState, updateState } from './state/state.js';
3
3
  import { getKeyIntent } from './utils/key-intent.js';
4
- export function navigate({ index = 0, breadCrumb, callbacks, }) {
5
- const { render = () => { }, onSelectChange = () => { }, onConfirm = () => { }, } = callbacks;
6
- const ctx = {
7
- breadCrumb,
8
- get navigationNode() {
9
- return this.breadCrumb.at(-1);
10
- },
11
- get children() {
12
- return this.navigationNode.children ?? [];
13
- },
14
- selectNone: () => {
15
- ctx.select(-1);
16
- },
17
- _selectedIndex: 0,
18
- getSelectedIndex() {
19
- return this._selectedIndex;
20
- },
21
- select(i) {
22
- this._selectedIndex = i;
23
- updateSelection(ctx.navigationNode, breadCrumb, i, onSelectChange);
24
- },
25
- render,
26
- reInvokeNavigate(index, breadCrumb) {
27
- return reInvokeNavigate(index, breadCrumb);
28
- },
29
- confirm: sel => onConfirm(sel),
30
- exit: () => {
31
- cleanup();
32
- process.exit(0);
33
- },
34
- enterChildNode: node => reInvokeNavigate(0, [...breadCrumb, node]),
35
- enterParentNode: () => {
36
- ctx.select(-1); // Clear all on this level
37
- if (breadCrumb.length < 2)
38
- return; // Need at least grandparent + parent
39
- const ancestors = breadCrumb;
40
- const parent = ancestors[ancestors.length - 1];
41
- const grandParent = ancestors[ancestors.length - 2];
42
- if (!parent || !grandParent)
43
- return;
44
- const parentIndex = grandParent?.children.findIndex(x => parent.id === x.id);
45
- reInvokeNavigate(parentIndex, breadCrumb.slice(0, -1)); // Go to parent level
46
- },
47
- };
48
- ctx.select(index);
49
- function onKeyPress(_, key) {
50
- if (key.ctrl && key.name === 'c')
51
- return ctx.exit();
52
- const filteredActions = navigationState.availableActions.filter(x => x.mode === navigationState.mode);
53
- const action = filteredActions?.find(actionMeta => {
54
- const intent = getKeyIntent(key, ctx);
55
- return intent === actionMeta.intent;
4
+ let currentKeypressListener;
5
+ export const navigationUtils = {
6
+ updateSelection: (idx) => {
7
+ updateState(oldState => {
8
+ const currentNode = oldState.breadCrumb.at(-1) ?? oldState.breadCrumb[0];
9
+ if (!currentNode)
10
+ return oldState;
11
+ currentNode.children?.forEach((child, i) => (child.isSelected = i === idx));
12
+ return {
13
+ ...oldState,
14
+ selectedIndex: idx,
15
+ currentNode: currentNode, // keep currentNode in sync
16
+ breadCrumb: [...oldState.breadCrumb], // keep reference fresh if you rely on it
17
+ };
56
18
  });
57
- action?.action?.(ctx);
58
- ctx.render();
59
- }
60
- const cleanup = () => process.stdin.removeListener('keypress', onKeyPress);
61
- const reInvokeNavigate = (idx, crumb) => {
62
- cleanup();
63
- navigate({ index: idx, breadCrumb: [...crumb], callbacks });
19
+ },
20
+ selectNone() {
21
+ this.updateSelection(-1);
22
+ },
23
+ confirm(sel) {
24
+ console.log(sel);
25
+ },
26
+ exit() {
27
+ process.exit(0);
28
+ },
29
+ enterChildNode(childNode) {
30
+ patchState({
31
+ breadCrumb: [...appState.breadCrumb, childNode],
32
+ currentNode: childNode,
33
+ selectedIndex: 0,
34
+ });
35
+ this.updateSelection(0);
36
+ },
37
+ enterParentNode() {
38
+ const crumb = appState.breadCrumb;
39
+ if (crumb.length < 2)
40
+ return;
41
+ const newCrumb = crumb.slice(0, -1);
42
+ const parentLevelNode = newCrumb.at(-1);
43
+ // find old parent index inside grandparent
44
+ const grandParent = newCrumb.at(-2);
45
+ const parentIndex = grandParent?.children?.findIndex(x => x.id === parentLevelNode.id) ?? 0;
46
+ patchState({
47
+ breadCrumb: newCrumb,
48
+ currentNode: parentLevelNode,
49
+ selectedIndex: parentIndex,
50
+ });
51
+ this.updateSelection(parentIndex);
52
+ },
53
+ };
54
+ const getKeyPressListener = () => {
55
+ navigationUtils.updateSelection(appState.selectedIndex ?? 0);
56
+ return async function onKeyPress(_, key) {
57
+ if (key.ctrl && key.name === 'c')
58
+ return navigationUtils.exit();
59
+ const filteredActions = appState.availableActions.filter(a => a.mode === appState.mode);
60
+ const actionMeta = filteredActions.find(({ intent, mode }) => getKeyIntent(key, mode) === intent);
61
+ if (!actionMeta?.action)
62
+ return;
63
+ try {
64
+ const res = actionMeta.action(navigationUtils, actionMeta, key);
65
+ if (res instanceof Promise)
66
+ await res;
67
+ }
68
+ catch (err) {
69
+ console.error(err);
70
+ }
64
71
  };
65
- render();
72
+ };
73
+ export function initListeners() {
74
+ if (currentKeypressListener) {
75
+ process.stdin.removeListener('keypress', currentKeypressListener);
76
+ }
77
+ currentKeypressListener = getKeyPressListener();
66
78
  readline.emitKeypressEvents(process.stdin);
67
79
  if (process.stdin.isTTY)
68
80
  process.stdin.setRawMode(true);
69
- process.stdin.on('keypress', onKeyPress);
70
- }
71
- function updateSelection({ children }, breadCrumb, idx, onSelectChange) {
72
- children.forEach((c, i) => (c.isSelected = i === idx));
73
- onSelectChange(children[idx], breadCrumb);
81
+ process.stdin.on('keypress', currentKeypressListener);
74
82
  }
@@ -0,0 +1,18 @@
1
+ export declare const commandDelimiter = " ";
2
+ export type CommandLineState = {
3
+ value: string;
4
+ commandHistory: string[];
5
+ commandHistoryIndex: number;
6
+ };
7
+ export declare let commandLineState: CommandLineState;
8
+ type Listener = () => void;
9
+ export declare const subscribeCommandLineState: (listener: Listener) => () => boolean;
10
+ export declare const updateCommandLineState: (cb: (old: CommandLineState) => CommandLineState) => void;
11
+ export declare const updateCommandLineInput: (cb: (previous: string) => string) => void;
12
+ export declare const updateCommandHistory: () => void;
13
+ export declare const getPrevCommand: () => void;
14
+ export declare const getNextCommand: () => void;
15
+ export declare const clearCommandLine: () => void;
16
+ export declare const getCommandLineInput: () => string;
17
+ export declare const getCommandLineArgumentValue: () => string;
18
+ export {};
@@ -0,0 +1,60 @@
1
+ export const commandDelimiter = ' ';
2
+ export let commandLineState = {
3
+ commandHistory: [],
4
+ value: '',
5
+ commandHistoryIndex: -1,
6
+ };
7
+ const listeners = new Set();
8
+ const notify = () => {
9
+ for (const l of listeners)
10
+ l();
11
+ };
12
+ export const subscribeCommandLineState = (listener) => {
13
+ listeners.add(listener);
14
+ return () => listeners.delete(listener);
15
+ };
16
+ // ===== Updates =====
17
+ export const updateCommandLineState = (cb) => {
18
+ const next = cb(structuredClone(commandLineState));
19
+ commandLineState = next;
20
+ notify();
21
+ };
22
+ export const updateCommandLineInput = (cb) => {
23
+ updateCommandLineState(state => ({
24
+ ...state,
25
+ value: cb(state.value),
26
+ }));
27
+ };
28
+ export const updateCommandHistory = () => {
29
+ updateCommandLineState(state => ({
30
+ ...state,
31
+ commandHistory: [state.value, ...state.commandHistory].slice(0, 20),
32
+ }));
33
+ };
34
+ export const getPrevCommand = () => {
35
+ updateCommandLineState(s => {
36
+ const nextIndex = Math.min(s.commandHistoryIndex + 1, s.commandHistory.length - 1);
37
+ return {
38
+ ...s,
39
+ commandHistoryIndex: nextIndex,
40
+ value: s.commandHistory[nextIndex] ?? '',
41
+ };
42
+ });
43
+ };
44
+ export const getNextCommand = () => {
45
+ updateCommandLineState(s => {
46
+ // typically you want to clamp down to -1 (meaning "no selection")
47
+ const nextIndex = Math.max(s.commandHistoryIndex - 1, -1);
48
+ return {
49
+ ...s,
50
+ commandHistoryIndex: nextIndex,
51
+ value: nextIndex === -1 ? '' : s.commandHistory[nextIndex] ?? '',
52
+ };
53
+ });
54
+ };
55
+ export const clearCommandLine = () => updateCommandLineInput(() => '');
56
+ export const getCommandLineInput = () => commandLineState.value;
57
+ export const getCommandLineArgumentValue = () => {
58
+ const [_, ...rest] = commandLineState.value.split(commandDelimiter);
59
+ return rest.join(commandDelimiter);
60
+ };
@@ -1,11 +1,20 @@
1
- import { ActionEntry, ModeOptions } from '../model/action-map.model.js';
2
- import { NavigateCtx } from '../model/navigation-ctx.model.js';
1
+ import { Board } from '../../board/model/board.model.js';
2
+ import { ActionEntry, ModeUnion } from '../model/action-map.model.js';
3
3
  import { NavigationTree } from '../model/navigation-tree.model.js';
4
- export declare let navigationState: {
5
- mode: ModeOptions;
6
- availableActions: ActionEntry<[NavigateCtx]>[];
7
- viewHelp: boolean;
8
- currentNode: NavigationTree<NavigationTree> | null;
9
- breadCrumb: NavigationTree<NavigationTree>[];
4
+ export type AppState = {
5
+ readonly selectedIndex: number;
6
+ readonly mode: ModeUnion;
7
+ readonly availableActions: ActionEntry[];
8
+ readonly availableHints: readonly string[];
9
+ readonly currentNode: NavigationTree<NavigationTree>;
10
+ readonly breadCrumb: NavigationTree<NavigationTree>[];
11
+ readonly rootNode: Board;
10
12
  };
11
- export declare const setState: (cb: (oldState: typeof navigationState) => typeof navigationState) => void;
13
+ export declare let appState: AppState;
14
+ export declare const initAppState: (board: Board) => void;
15
+ export declare const updateState: (cb: (oldState: typeof appState) => typeof appState, opts?: {
16
+ render?: boolean;
17
+ }) => void;
18
+ export declare const patchState: (patch: Partial<typeof appState>, opts?: {
19
+ render?: boolean;
20
+ }) => void;
@@ -1,10 +1,38 @@
1
- export let navigationState = {
2
- mode: 'default',
3
- availableActions: [],
4
- viewHelp: false,
5
- currentNode: null,
6
- breadCrumb: [],
1
+ import { Hints } from '../../board/hints/hints.js';
2
+ import { renderBoard } from '../../cli.js';
3
+ import { ContextualActionMap } from '../actions/board-action-map.js';
4
+ import { DefaultActions } from '../actions/default/default-actions.js';
5
+ import { inputActions } from '../actions/input/input-actions.js';
6
+ export let appState;
7
+ const derived = (state) => {
8
+ const { currentNode, mode } = state;
9
+ const availableHints = Hints[currentNode.actionContext + mode] ?? Hints[currentNode.actionContext];
10
+ const actionContext = currentNode?.actionContext;
11
+ const availableActions = [
12
+ ...DefaultActions,
13
+ ...ContextualActionMap[actionContext],
14
+ ...inputActions,
15
+ ];
16
+ return {
17
+ ...state,
18
+ availableHints,
19
+ availableActions,
20
+ };
7
21
  };
8
- export const setState = (cb) => {
9
- navigationState = cb(navigationState);
22
+ export const initAppState = (board) => {
23
+ appState = derived({
24
+ ...appState,
25
+ rootNode: board,
26
+ breadCrumb: [board],
27
+ selectedIndex: 0,
28
+ mode: 'default',
29
+ currentNode: board,
30
+ });
31
+ renderBoard();
10
32
  };
33
+ export const updateState = (cb, opts = { render: true }) => {
34
+ appState = derived(cb(appState));
35
+ if (opts.render)
36
+ renderBoard();
37
+ };
38
+ export const patchState = (patch, opts = { render: true }) => updateState(old => ({ ...old, ...patch }), opts);
@@ -0,0 +1,3 @@
1
+ import { Intent } from './key-intent.js';
2
+ import readline from 'readline';
3
+ export declare const getCommandLineIntent: (key: readline.Key) => Intent.Confirm | Intent.ToggleCommandLine | Intent.CaptureInput | Intent.EraseInput | Intent.GetLastCommandFromHistory | Intent.GetNextCommandFromHistory;
@@ -0,0 +1,17 @@
1
+ import { Intent } from './key-intent.js';
2
+ export const getCommandLineIntent = (key) => {
3
+ switch (key.name) {
4
+ case 'up':
5
+ return Intent.GetLastCommandFromHistory;
6
+ case 'down':
7
+ return Intent.GetNextCommandFromHistory;
8
+ case 'return':
9
+ return Intent.Confirm;
10
+ case 'backspace':
11
+ return Intent.EraseInput;
12
+ case 'escape':
13
+ return Intent.ToggleCommandLine;
14
+ default:
15
+ return Intent.CaptureInput;
16
+ }
17
+ };
@@ -0,0 +1,5 @@
1
+ import readline from 'readline';
2
+ import { ModeUnion } from '../model/action-map.model.js';
3
+ import { NavigateCtx } from '../model/navigation-ctx.model.js';
4
+ import { KeyIntent } from './key-intent.js';
5
+ export declare function getKeyIntent(key: readline.Key, ctx: NavigateCtx, mode: ModeUnion): KeyIntent | null;
@@ -0,0 +1,71 @@
1
+ import { Mode } from '../model/action-map.model.js';
2
+ import { KeyIntent, getDir, mapDirectionalIntent } from './key-intent.js';
3
+ export function getKeyIntent(key, ctx, mode) {
4
+ if (key.sequence === ':') {
5
+ return KeyIntent.ToggleCommandLine;
6
+ }
7
+ if (mode === Mode.COMMAND_LINE) {
8
+ switch (key.name) {
9
+ case 'return':
10
+ return KeyIntent.Confirm;
11
+ case 'backspace':
12
+ return KeyIntent.EraseInput;
13
+ case 'escape':
14
+ return KeyIntent.ToggleCommandLine;
15
+ default:
16
+ return KeyIntent.CaptureInput;
17
+ }
18
+ }
19
+ const axis = ctx.navigationNode.childrenRenderAxis;
20
+ const enableAcrossContainers = ctx.navigationNode.enableChildNavigationAcrossContainers;
21
+ if (key.name === 'escape' && mode === Mode.HELP) {
22
+ return KeyIntent.ToggleHelp;
23
+ }
24
+ // Hard exits
25
+ if (key.ctrl && key.name === 'c')
26
+ return KeyIntent.Exit;
27
+ if (key.name === 'escape')
28
+ return KeyIntent.Exit;
29
+ // Move mode
30
+ if (mode === Mode.MOVE) {
31
+ if (key.name === 'y')
32
+ return KeyIntent.ToggleMove;
33
+ const dir = getDir(key);
34
+ if (!dir)
35
+ return null;
36
+ return mapDirectionalIntent(dir, axis, Boolean(enableAcrossContainers), {
37
+ prevItem: KeyIntent.MovePreviousItem,
38
+ nextItem: KeyIntent.MoveNextItem,
39
+ prevContainer: KeyIntent.MoveToPreviousContainer,
40
+ nextContainer: KeyIntent.MoveToNextContainer,
41
+ });
42
+ }
43
+ // Normal mode
44
+ if (key.name === 'y')
45
+ return KeyIntent.ToggleMove;
46
+ // Edit (vim-ish)
47
+ if (key.name === 'i')
48
+ return KeyIntent.Edit;
49
+ // Navigation (arrows + vim hjkl)
50
+ const dir = getDir(key);
51
+ if (dir) {
52
+ return mapDirectionalIntent(dir, axis, Boolean(enableAcrossContainers), {
53
+ prevItem: KeyIntent.NavPreviousItem,
54
+ nextItem: KeyIntent.NavNextItem,
55
+ prevContainer: KeyIntent.NavToPreviousContainer,
56
+ nextContainer: KeyIntent.NavToNextContainer,
57
+ });
58
+ }
59
+ // Actions
60
+ switch (key.name) {
61
+ case 'a':
62
+ return KeyIntent.AddItem;
63
+ case 'return':
64
+ case 'e':
65
+ return KeyIntent.Confirm;
66
+ case 'q':
67
+ return KeyIntent.Exit;
68
+ default:
69
+ return null;
70
+ }
71
+ }
@@ -1,16 +1,25 @@
1
1
  import readline from 'readline';
2
- import { NavigateCtx } from '../model/navigation-ctx.model.js';
3
- export declare enum KeyIntent {
4
- NavPreviousItem = "nav-previous-item",
5
- NavNextItem = "nav-next-item",
6
- NavToPreviousContainer = "nav-to-previous-container",
7
- NavToNextContainer = "nav-to-next-container",
8
- MovePreviousItem = "move-previous-item",
9
- MoveNextItem = "move-next-item",
10
- MoveToPreviousContainer = "move-to-previous-container",
11
- MoveToNextContainer = "move-to-next-container",
2
+ import { ModeUnion } from '../model/action-map.model.js';
3
+ export declare enum Intent {
4
+ NavPreviousItem = "navPreviousItem",
5
+ NavNextItem = "navNextItem",
6
+ NavToPreviousContainer = "navToPreviousContainer",
7
+ NavToNextContainer = "navToNextContainer",
8
+ MovePreviousItem = "movePreviousItem",
9
+ MoveNextItem = "moveNextItem",
10
+ MoveToPreviousContainer = "moveToPreviousContainer",
11
+ MoveToNextContainer = "moveToNextContainer",
12
12
  Confirm = "confirm",
13
+ Edit = "edit",
13
14
  Exit = "exit",
14
- ToggleHelp = "toggle-help"
15
+ ViewHelp = "viewHelp",
16
+ HideHelp = "hideHelp",
17
+ InitMove = "initMove",
18
+ ToggleCommandLine = "toggleCommandLine",
19
+ CaptureInput = "captureInput",
20
+ EraseInput = "eraseInput",
21
+ AddItem = "addItem",
22
+ GetLastCommandFromHistory = "getLastCommandFromHistory",
23
+ GetNextCommandFromHistory = "getNextCommandFromHistory"
15
24
  }
16
- export declare function getKeyIntent(key: readline.Key, ctx: NavigateCtx): KeyIntent | null;
25
+ export declare function getKeyIntent(key: readline.Key, mode: ModeUnion): Intent | null;
@@ -1,64 +1,118 @@
1
- export var KeyIntent;
2
- (function (KeyIntent) {
3
- KeyIntent["NavPreviousItem"] = "nav-previous-item";
4
- KeyIntent["NavNextItem"] = "nav-next-item";
5
- KeyIntent["NavToPreviousContainer"] = "nav-to-previous-container";
6
- KeyIntent["NavToNextContainer"] = "nav-to-next-container";
7
- KeyIntent["MovePreviousItem"] = "move-previous-item";
8
- KeyIntent["MoveNextItem"] = "move-next-item";
9
- KeyIntent["MoveToPreviousContainer"] = "move-to-previous-container";
10
- KeyIntent["MoveToNextContainer"] = "move-to-next-container";
11
- KeyIntent["Confirm"] = "confirm";
12
- KeyIntent["Exit"] = "exit";
13
- KeyIntent["ToggleHelp"] = "toggle-help";
14
- })(KeyIntent || (KeyIntent = {}));
15
- export function getKeyIntent(key, ctx) {
16
- const axis = ctx.navigationNode.childrenRenderAxis;
17
- if (key.shift) {
18
- switch (key.name) {
19
- case 'up':
20
- return axis === 'vertical' ? KeyIntent.MovePreviousItem : null;
21
- case 'down':
22
- return axis === 'vertical' ? KeyIntent.MoveNextItem : null;
23
- case 'left':
24
- return axis === 'horizontal'
25
- ? KeyIntent.MovePreviousItem
26
- : ctx.navigationNode.enableChildNavigationAcrossContainers
27
- ? KeyIntent.MoveToPreviousContainer
28
- : null;
29
- case 'right':
30
- return axis === 'horizontal'
31
- ? KeyIntent.MoveNextItem
32
- : ctx.navigationNode.enableChildNavigationAcrossContainers
33
- ? KeyIntent.MoveToNextContainer
34
- : null;
35
- default:
36
- return null;
37
- }
38
- }
1
+ import { Mode } from '../model/action-map.model.js';
2
+ import { appState } from '../state/state.js';
3
+ import { getCommandLineIntent } from './get-command-line-intent.js';
4
+ export var Intent;
5
+ (function (Intent) {
6
+ Intent["NavPreviousItem"] = "navPreviousItem";
7
+ Intent["NavNextItem"] = "navNextItem";
8
+ Intent["NavToPreviousContainer"] = "navToPreviousContainer";
9
+ Intent["NavToNextContainer"] = "navToNextContainer";
10
+ Intent["MovePreviousItem"] = "movePreviousItem";
11
+ Intent["MoveNextItem"] = "moveNextItem";
12
+ Intent["MoveToPreviousContainer"] = "moveToPreviousContainer";
13
+ Intent["MoveToNextContainer"] = "moveToNextContainer";
14
+ Intent["Confirm"] = "confirm";
15
+ Intent["Edit"] = "edit";
16
+ Intent["Exit"] = "exit";
17
+ Intent["ViewHelp"] = "viewHelp";
18
+ Intent["HideHelp"] = "hideHelp";
19
+ Intent["InitMove"] = "initMove";
20
+ // Command line
21
+ Intent["ToggleCommandLine"] = "toggleCommandLine";
22
+ Intent["CaptureInput"] = "captureInput";
23
+ Intent["EraseInput"] = "eraseInput";
24
+ Intent["AddItem"] = "addItem";
25
+ Intent["GetLastCommandFromHistory"] = "getLastCommandFromHistory";
26
+ Intent["GetNextCommandFromHistory"] = "getNextCommandFromHistory";
27
+ })(Intent || (Intent = {}));
28
+ function getDir(key) {
39
29
  switch (key.name) {
30
+ // arrows
31
+ case 'up':
32
+ case 'down':
33
+ case 'left':
34
+ case 'right':
35
+ return key.name;
36
+ // vim
37
+ case 'k':
38
+ return 'up';
39
+ case 'j':
40
+ return 'down';
40
41
  case 'h':
41
- return KeyIntent.ToggleHelp;
42
+ return 'left';
43
+ case 'l':
44
+ return 'right';
45
+ default:
46
+ return null;
47
+ }
48
+ }
49
+ function mapDirectionalIntent(axis, dir, intents) {
50
+ const enableAcrossContainers = appState.currentNode.enableChildNavigationAcrossContainers;
51
+ switch (dir) {
42
52
  case 'up':
43
- return axis === 'vertical' ? KeyIntent.NavPreviousItem : null;
53
+ return axis === 'vertical'
54
+ ? intents.prevItem
55
+ : enableAcrossContainers
56
+ ? intents.prevContainer
57
+ : null;
44
58
  case 'down':
45
- return axis === 'vertical' ? KeyIntent.NavNextItem : null;
59
+ return axis === 'vertical'
60
+ ? intents.nextItem
61
+ : enableAcrossContainers
62
+ ? intents.nextContainer
63
+ : null;
46
64
  case 'left':
47
65
  return axis === 'horizontal'
48
- ? KeyIntent.NavPreviousItem
49
- : ctx.navigationNode.enableChildNavigationAcrossContainers
50
- ? KeyIntent.NavToPreviousContainer
66
+ ? intents.prevItem
67
+ : enableAcrossContainers
68
+ ? intents.prevContainer
51
69
  : null;
52
70
  case 'right':
53
71
  return axis === 'horizontal'
54
- ? KeyIntent.NavNextItem
55
- : ctx.navigationNode.enableChildNavigationAcrossContainers
56
- ? KeyIntent.NavToNextContainer
72
+ ? intents.nextItem
73
+ : enableAcrossContainers
74
+ ? intents.nextContainer
57
75
  : null;
58
- case 'return':
59
- return KeyIntent.Confirm;
76
+ }
77
+ }
78
+ export function getKeyIntent(key, mode) {
79
+ if (key.sequence === ':')
80
+ return Intent.ToggleCommandLine;
81
+ if (mode === Mode.COMMAND_LINE)
82
+ return getCommandLineIntent(key);
83
+ // Navigation keys
84
+ const dir = getDir(key);
85
+ if (dir) {
86
+ let dirMap = mode === Mode.MOVE
87
+ ? {
88
+ prevItem: Intent.MovePreviousItem,
89
+ nextItem: Intent.MoveNextItem,
90
+ prevContainer: Intent.MoveToPreviousContainer,
91
+ nextContainer: Intent.MoveToNextContainer,
92
+ }
93
+ : {
94
+ prevItem: Intent.NavPreviousItem,
95
+ nextItem: Intent.NavNextItem,
96
+ prevContainer: Intent.NavToPreviousContainer,
97
+ nextContainer: Intent.NavToNextContainer,
98
+ };
99
+ return mapDirectionalIntent(appState.currentNode.childrenRenderAxis, dir, dirMap);
100
+ }
101
+ // Hard exit
102
+ if (key.ctrl && key.name === 'c')
103
+ return Intent.Exit;
104
+ // Default actions
105
+ switch (key.name) {
106
+ case 'i':
107
+ return Intent.Edit;
108
+ case 'y':
109
+ return Intent.InitMove;
60
110
  case 'e':
61
- return KeyIntent.Exit;
111
+ case 'return':
112
+ return Intent.Confirm;
113
+ case 'q':
114
+ case 'escape':
115
+ return Intent.Exit;
62
116
  default:
63
117
  return null;
64
118
  }