git-stack-cli 2.9.6 → 2.9.8
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.
- package/dist/js/index.js +71 -71
- package/package.json +1 -1
- package/src/app/DebugOutput.tsx +3 -11
- package/src/app/MultiSelect.tsx +11 -0
- package/src/app/Output.tsx +2 -1
- package/src/app/SelectCommitRanges.tsx +146 -140
- package/src/core/render_node.tsx +37 -0
package/package.json
CHANGED
package/src/app/DebugOutput.tsx
CHANGED
|
@@ -3,6 +3,8 @@ import * as React from "react";
|
|
|
3
3
|
import * as Ink from "ink-cjs";
|
|
4
4
|
import { DateTime } from "luxon";
|
|
5
5
|
|
|
6
|
+
import { render_node } from "~/core/render_node";
|
|
7
|
+
|
|
6
8
|
type Props = {
|
|
7
9
|
node: React.ReactNode;
|
|
8
10
|
};
|
|
@@ -14,17 +16,7 @@ export function DebugOutput(props: Props) {
|
|
|
14
16
|
const timestamp = DateTime.now().toFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
|
15
17
|
const content_width = available_width - timestamp.length - 2;
|
|
16
18
|
|
|
17
|
-
const content = (
|
|
18
|
-
switch (typeof props.node) {
|
|
19
|
-
case "boolean":
|
|
20
|
-
case "number":
|
|
21
|
-
case "string": {
|
|
22
|
-
return <Ink.Text dimColor>{String(props.node)}</Ink.Text>;
|
|
23
|
-
}
|
|
24
|
-
default:
|
|
25
|
-
return props.node;
|
|
26
|
-
}
|
|
27
|
-
})();
|
|
19
|
+
const content = render_node(props.node);
|
|
28
20
|
|
|
29
21
|
return (
|
|
30
22
|
<Ink.Box flexDirection="column">
|
package/src/app/MultiSelect.tsx
CHANGED
|
@@ -92,6 +92,7 @@ export function MultiSelect<T>(props: Props<T>) {
|
|
|
92
92
|
React.useEffect(ensure_selectable_focus, [props.items]);
|
|
93
93
|
function ensure_selectable_focus() {
|
|
94
94
|
const current = props.items[index];
|
|
95
|
+
|
|
95
96
|
if (current && !current.disabled) {
|
|
96
97
|
return;
|
|
97
98
|
}
|
|
@@ -115,6 +116,11 @@ export function MultiSelect<T>(props: Props<T>) {
|
|
|
115
116
|
return;
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
// prevent accessing `.value` of undefined item
|
|
120
|
+
if (!props.items[index]) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
118
124
|
const item = props.items[index].value;
|
|
119
125
|
const selected_list = Array.from(selected_set);
|
|
120
126
|
const selected = selected_set.has(index);
|
|
@@ -125,6 +131,11 @@ export function MultiSelect<T>(props: Props<T>) {
|
|
|
125
131
|
}, [selected_set]);
|
|
126
132
|
|
|
127
133
|
React.useEffect(() => {
|
|
134
|
+
// prevent accessing `.value` of undefined item
|
|
135
|
+
if (!props.items[index]) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
128
139
|
const item = props.items[index].value;
|
|
129
140
|
const selected_list = Array.from(selected_set);
|
|
130
141
|
const selected = selected_set.has(index);
|
package/src/app/Output.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import * as Ink from "ink-cjs";
|
|
|
4
4
|
|
|
5
5
|
import { DebugOutput } from "~/app/DebugOutput";
|
|
6
6
|
import { Store } from "~/app/Store";
|
|
7
|
+
import { render_node } from "~/core/render_node";
|
|
7
8
|
|
|
8
9
|
export function Output() {
|
|
9
10
|
const output = Store.useState((state) => state.output);
|
|
@@ -14,7 +15,7 @@ export function Output() {
|
|
|
14
15
|
<Ink.Static items={output}>
|
|
15
16
|
{(entry) => {
|
|
16
17
|
const [id, node] = entry;
|
|
17
|
-
return <Ink.Box key={id}>{node}</Ink.Box>;
|
|
18
|
+
return <Ink.Box key={id}>{render_node(node)}</Ink.Box>;
|
|
18
19
|
}}
|
|
19
20
|
</Ink.Static>
|
|
20
21
|
|
|
@@ -107,18 +107,24 @@ export function SelectCommitRanges() {
|
|
|
107
107
|
Ink.useInput((input, key) => {
|
|
108
108
|
const input_lower = input.toLowerCase();
|
|
109
109
|
|
|
110
|
-
// only allow pr select when on unassigned group
|
|
111
|
-
if (has_unassigned_commits && input_lower === SYMBOL.p) {
|
|
112
|
-
set_pr_select((v) => !v);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
110
|
// allow cancelling pr select with esc
|
|
116
111
|
if (pr_select && key.escape) {
|
|
117
112
|
set_pr_select(false);
|
|
118
113
|
return;
|
|
119
114
|
}
|
|
120
115
|
|
|
121
|
-
//
|
|
116
|
+
// only allow pr select when…
|
|
117
|
+
// 1. we have unassigned commits
|
|
118
|
+
// 2. not inputting group
|
|
119
|
+
// 3. at least one existing prs exists
|
|
120
|
+
if (has_unassigned_commits && !group_input && existing_pr_list.length > 0) {
|
|
121
|
+
if (input_lower === SYMBOL.p) {
|
|
122
|
+
set_pr_select((v) => !v);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// disable key handlers below when inputting
|
|
122
128
|
if (is_input_mode) {
|
|
123
129
|
return;
|
|
124
130
|
}
|
|
@@ -298,23 +304,25 @@ export function SelectCommitRanges() {
|
|
|
298
304
|
/>
|
|
299
305
|
</Ink.Text>
|
|
300
306
|
|
|
301
|
-
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
<
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
307
|
+
{existing_pr_list.length === 0 ? null : (
|
|
308
|
+
<Ink.Text color={colors.blue}>
|
|
309
|
+
<FormatText
|
|
310
|
+
message="Press {p} to {pick} an existing PR"
|
|
311
|
+
values={{
|
|
312
|
+
p: (
|
|
313
|
+
<Ink.Text bold color={colors.green}>
|
|
314
|
+
p
|
|
315
|
+
</Ink.Text>
|
|
316
|
+
),
|
|
317
|
+
pick: (
|
|
318
|
+
<Ink.Text bold color={colors.green}>
|
|
319
|
+
<Parens>p</Parens>pick
|
|
320
|
+
</Ink.Text>
|
|
321
|
+
),
|
|
322
|
+
}}
|
|
323
|
+
/>
|
|
324
|
+
</Ink.Text>
|
|
325
|
+
)}
|
|
318
326
|
</Ink.Box>
|
|
319
327
|
)}
|
|
320
328
|
|
|
@@ -386,7 +394,7 @@ export function SelectCommitRanges() {
|
|
|
386
394
|
</React.Fragment>
|
|
387
395
|
)}
|
|
388
396
|
|
|
389
|
-
{!pr_select ? null : (
|
|
397
|
+
{!pr_select || !existing_pr_list.length ? null : (
|
|
390
398
|
<React.Fragment>
|
|
391
399
|
<FormatText
|
|
392
400
|
wrapper={<Ink.Text color={colors.gray} />}
|
|
@@ -460,6 +468,8 @@ export function SelectCommitRanges() {
|
|
|
460
468
|
</React.Fragment>
|
|
461
469
|
)}
|
|
462
470
|
|
|
471
|
+
{is_input_mode ? null : <React.Fragment></React.Fragment>}
|
|
472
|
+
|
|
463
473
|
<Ink.Box height={1} />
|
|
464
474
|
|
|
465
475
|
<MultiSelect
|
|
@@ -489,143 +499,139 @@ export function SelectCommitRanges() {
|
|
|
489
499
|
}}
|
|
490
500
|
/>
|
|
491
501
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
{has_unassigned_commits ? (
|
|
502
|
+
{is_input_mode ? null : (
|
|
495
503
|
<React.Fragment>
|
|
504
|
+
<Ink.Box height={1} />
|
|
505
|
+
|
|
506
|
+
{has_unassigned_commits ? (
|
|
507
|
+
<React.Fragment>
|
|
508
|
+
<FormatText
|
|
509
|
+
wrapper={<Ink.Text color={colors.gray} />}
|
|
510
|
+
message="{count} unassigned commits"
|
|
511
|
+
values={{
|
|
512
|
+
count: (
|
|
513
|
+
<Ink.Text color={colors.yellow} bold>
|
|
514
|
+
{unassigned_count}
|
|
515
|
+
</Ink.Text>
|
|
516
|
+
),
|
|
517
|
+
}}
|
|
518
|
+
/>
|
|
519
|
+
|
|
520
|
+
<FormatText
|
|
521
|
+
wrapper={<Ink.Text color={colors.gray} />}
|
|
522
|
+
message="Press {c} to {create} a new PR"
|
|
523
|
+
values={{
|
|
524
|
+
c: (
|
|
525
|
+
<Ink.Text bold color={colors.green}>
|
|
526
|
+
c
|
|
527
|
+
</Ink.Text>
|
|
528
|
+
),
|
|
529
|
+
create: (
|
|
530
|
+
<Ink.Text bold color={colors.green}>
|
|
531
|
+
<Parens>c</Parens>reate
|
|
532
|
+
</Ink.Text>
|
|
533
|
+
),
|
|
534
|
+
}}
|
|
535
|
+
/>
|
|
536
|
+
|
|
537
|
+
{existing_pr_list.length === 0 ? null : (
|
|
538
|
+
<FormatText
|
|
539
|
+
wrapper={<Ink.Text color={colors.gray} />}
|
|
540
|
+
message="Press {p} to {pick} an existing PR"
|
|
541
|
+
values={{
|
|
542
|
+
p: (
|
|
543
|
+
<Ink.Text bold color={colors.green}>
|
|
544
|
+
p
|
|
545
|
+
</Ink.Text>
|
|
546
|
+
),
|
|
547
|
+
pick: (
|
|
548
|
+
<Ink.Text bold color={colors.green}>
|
|
549
|
+
<Parens>p</Parens>pick
|
|
550
|
+
</Ink.Text>
|
|
551
|
+
),
|
|
552
|
+
}}
|
|
553
|
+
/>
|
|
554
|
+
)}
|
|
555
|
+
|
|
556
|
+
{sync_status !== "allow_unassigned" ? null : (
|
|
557
|
+
<FormatText
|
|
558
|
+
wrapper={<Ink.Text color={colors.gray} />}
|
|
559
|
+
message={
|
|
560
|
+
argv.sync
|
|
561
|
+
? "Press {s} to {sync} the {count} assigned commits to Github"
|
|
562
|
+
: "Press {s} to {sync} the {count} assigned commits locally"
|
|
563
|
+
}
|
|
564
|
+
values={{
|
|
565
|
+
...S_TO_SYNC_VALUES,
|
|
566
|
+
count: (
|
|
567
|
+
<Ink.Text color={colors.yellow} bold>
|
|
568
|
+
{assigned_count}
|
|
569
|
+
</Ink.Text>
|
|
570
|
+
),
|
|
571
|
+
}}
|
|
572
|
+
/>
|
|
573
|
+
)}
|
|
574
|
+
</React.Fragment>
|
|
575
|
+
) : (
|
|
576
|
+
<FormatText
|
|
577
|
+
wrapper={<Ink.Text color={colors.blue} />}
|
|
578
|
+
message={
|
|
579
|
+
argv.sync
|
|
580
|
+
? "🎉 Done! Press {s} to {sync} the PRs to Github"
|
|
581
|
+
: "🎉 Done! Press {s} to {sync} the PRs locally"
|
|
582
|
+
}
|
|
583
|
+
values={S_TO_SYNC_VALUES}
|
|
584
|
+
/>
|
|
585
|
+
)}
|
|
586
|
+
|
|
496
587
|
<FormatText
|
|
497
588
|
wrapper={<Ink.Text color={colors.gray} />}
|
|
498
|
-
message="{
|
|
589
|
+
message="Press {left} and {right} to view PRs"
|
|
499
590
|
values={{
|
|
500
|
-
|
|
501
|
-
<Ink.Text color={colors.
|
|
502
|
-
{
|
|
591
|
+
left: (
|
|
592
|
+
<Ink.Text bold color={colors.green}>
|
|
593
|
+
{SYMBOL.left}
|
|
594
|
+
</Ink.Text>
|
|
595
|
+
),
|
|
596
|
+
right: (
|
|
597
|
+
<Ink.Text bold color={colors.green}>
|
|
598
|
+
{SYMBOL.right}
|
|
503
599
|
</Ink.Text>
|
|
504
600
|
),
|
|
505
601
|
}}
|
|
506
602
|
/>
|
|
507
603
|
|
|
508
|
-
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
<Ink.Text bold color={colors.green}>
|
|
520
|
-
<Parens>c</Parens>reate
|
|
521
|
-
</Ink.Text>
|
|
522
|
-
),
|
|
523
|
-
}}
|
|
524
|
-
/>
|
|
525
|
-
)}
|
|
526
|
-
|
|
527
|
-
{is_input_mode ? null : (
|
|
528
|
-
<FormatText
|
|
529
|
-
wrapper={<Ink.Text color={colors.gray} />}
|
|
530
|
-
message="Press {p} to {pick} an existing PR"
|
|
531
|
-
values={{
|
|
532
|
-
p: (
|
|
533
|
-
<Ink.Text bold color={colors.green}>
|
|
534
|
-
p
|
|
535
|
-
</Ink.Text>
|
|
536
|
-
),
|
|
537
|
-
pick: (
|
|
538
|
-
<Ink.Text bold color={colors.green}>
|
|
539
|
-
<Parens>p</Parens>pick
|
|
540
|
-
</Ink.Text>
|
|
541
|
-
),
|
|
542
|
-
}}
|
|
543
|
-
/>
|
|
544
|
-
)}
|
|
604
|
+
<FormatText
|
|
605
|
+
wrapper={<Ink.Text color={colors.gray} />}
|
|
606
|
+
message="Press {enter} to toggle commit selection"
|
|
607
|
+
values={{
|
|
608
|
+
enter: (
|
|
609
|
+
<Ink.Text bold color={colors.green}>
|
|
610
|
+
{SYMBOL.enter}
|
|
611
|
+
</Ink.Text>
|
|
612
|
+
),
|
|
613
|
+
}}
|
|
614
|
+
/>
|
|
545
615
|
|
|
546
|
-
{
|
|
616
|
+
{group.id === commit_range.UNASSIGNED ? null : (
|
|
547
617
|
<FormatText
|
|
548
618
|
wrapper={<Ink.Text color={colors.gray} />}
|
|
549
619
|
message={
|
|
550
|
-
|
|
551
|
-
? "Press {
|
|
552
|
-
: "Press {
|
|
620
|
+
is_master_base
|
|
621
|
+
? "Press {m} to {reset} current PR base to stack position"
|
|
622
|
+
: "Press {m} to set current PR base to master"
|
|
553
623
|
}
|
|
554
624
|
values={{
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
{assigned_count}
|
|
625
|
+
m: (
|
|
626
|
+
<Ink.Text bold color={colors.green}>
|
|
627
|
+
{SYMBOL.m}
|
|
559
628
|
</Ink.Text>
|
|
560
629
|
),
|
|
630
|
+
reset: <Ink.Text color={colors.yellow}>reset</Ink.Text>,
|
|
561
631
|
}}
|
|
562
632
|
/>
|
|
563
633
|
)}
|
|
564
634
|
</React.Fragment>
|
|
565
|
-
) : (
|
|
566
|
-
<FormatText
|
|
567
|
-
wrapper={<Ink.Text />}
|
|
568
|
-
message={
|
|
569
|
-
argv.sync
|
|
570
|
-
? "🎉 Done! Press {s} to {sync} the PRs to Github"
|
|
571
|
-
: "🎉 Done! Press {s} to {sync} the PRs locally"
|
|
572
|
-
}
|
|
573
|
-
values={S_TO_SYNC_VALUES}
|
|
574
|
-
/>
|
|
575
|
-
)}
|
|
576
|
-
|
|
577
|
-
<Ink.Box>
|
|
578
|
-
<FormatText
|
|
579
|
-
wrapper={<Ink.Text color={colors.gray} />}
|
|
580
|
-
message="Press {left} and {right} to view PRs"
|
|
581
|
-
values={{
|
|
582
|
-
left: (
|
|
583
|
-
<Ink.Text bold color={colors.green}>
|
|
584
|
-
{SYMBOL.left}
|
|
585
|
-
</Ink.Text>
|
|
586
|
-
),
|
|
587
|
-
right: (
|
|
588
|
-
<Ink.Text bold color={colors.green}>
|
|
589
|
-
{SYMBOL.right}
|
|
590
|
-
</Ink.Text>
|
|
591
|
-
),
|
|
592
|
-
}}
|
|
593
|
-
/>
|
|
594
|
-
</Ink.Box>
|
|
595
|
-
|
|
596
|
-
<Ink.Box>
|
|
597
|
-
<FormatText
|
|
598
|
-
wrapper={<Ink.Text color={colors.gray} />}
|
|
599
|
-
message="Press {enter} to toggle commit selection"
|
|
600
|
-
values={{
|
|
601
|
-
enter: (
|
|
602
|
-
<Ink.Text bold color={colors.green}>
|
|
603
|
-
{SYMBOL.enter}
|
|
604
|
-
</Ink.Text>
|
|
605
|
-
),
|
|
606
|
-
}}
|
|
607
|
-
/>
|
|
608
|
-
</Ink.Box>
|
|
609
|
-
|
|
610
|
-
{group.id === commit_range.UNASSIGNED ? null : (
|
|
611
|
-
<Ink.Box>
|
|
612
|
-
<FormatText
|
|
613
|
-
wrapper={<Ink.Text color={colors.gray} />}
|
|
614
|
-
message={
|
|
615
|
-
is_master_base
|
|
616
|
-
? "Press {m} to {reset} current PR base to stack position"
|
|
617
|
-
: "Press {m} to set current PR base to master"
|
|
618
|
-
}
|
|
619
|
-
values={{
|
|
620
|
-
m: (
|
|
621
|
-
<Ink.Text bold color={colors.green}>
|
|
622
|
-
{SYMBOL.m}
|
|
623
|
-
</Ink.Text>
|
|
624
|
-
),
|
|
625
|
-
reset: <Ink.Text color={colors.yellow}>reset</Ink.Text>,
|
|
626
|
-
}}
|
|
627
|
-
/>
|
|
628
|
-
</Ink.Box>
|
|
629
635
|
)}
|
|
630
636
|
</Ink.Box>
|
|
631
637
|
);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import * as Ink from "ink-cjs";
|
|
4
|
+
|
|
5
|
+
import { Store } from "~/app/Store";
|
|
6
|
+
|
|
7
|
+
export function render_node(node: React.ReactNode) {
|
|
8
|
+
const actions = Store.getState().actions;
|
|
9
|
+
|
|
10
|
+
if (node == null) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (React.isValidElement(node)) {
|
|
15
|
+
return node;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (Array.isArray(node)) {
|
|
19
|
+
return (
|
|
20
|
+
<React.Fragment>
|
|
21
|
+
{node.map((entry, index) => (
|
|
22
|
+
<React.Fragment key={index}>{render_node(entry)}</React.Fragment>
|
|
23
|
+
))}
|
|
24
|
+
</React.Fragment>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (typeof node) {
|
|
29
|
+
case "string":
|
|
30
|
+
case "number":
|
|
31
|
+
case "boolean":
|
|
32
|
+
return <Ink.Text>{String(node)}</Ink.Text>;
|
|
33
|
+
default:
|
|
34
|
+
actions.debug(`unhandled node ${typeof node}`);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|