1- import { JJ } from "@array/core" ;
1+ import {
2+ CATEGORY_LABELS ,
3+ CATEGORY_ORDER ,
4+ type CommandInfo ,
5+ getCommandsByCategory ,
6+ getCoreCommands ,
7+ JJ ,
8+ } from "@array/core" ;
29import { abandon } from "./commands/abandon" ;
310import { auth } from "./commands/auth" ;
411import { bottom } from "./commands/bottom" ;
512import { checkout } from "./commands/checkout" ;
613import { config } from "./commands/config" ;
714import { conflicts } from "./commands/conflicts" ;
15+ import { continueCommand } from "./commands/continue" ;
816import { create } from "./commands/create" ;
17+ import { deleteChange } from "./commands/delete" ;
918import { disable } from "./commands/disable" ;
1019import { down } from "./commands/down" ;
1120import { edit } from "./commands/edit" ;
@@ -14,8 +23,10 @@ import { exit } from "./commands/exit";
1423import { init } from "./commands/init" ;
1524import { list } from "./commands/list" ;
1625import { log } from "./commands/log" ;
26+ import { merge } from "./commands/merge" ;
1727import { modify } from "./commands/modify" ;
1828import { restack } from "./commands/restack" ;
29+ import { stacks } from "./commands/stacks" ;
1930import { status } from "./commands/status" ;
2031import { submit } from "./commands/submit" ;
2132import { swap } from "./commands/swap" ;
@@ -37,60 +48,97 @@ import {
3748 resolveCommandAlias ,
3849} from "./utils/parser" ;
3950
51+ const CMD_WIDTH = 22 ;
52+
53+ const TAGLINE = `Array (arr) is a CLI for stacked PRs using Jujutsu (jj).
54+ It enables stacking changes on top of each other to keep you unblocked
55+ and your changes small, focused, and reviewable.` ;
56+
57+ const USAGE = `${ bold ( "USAGE" ) }
58+ $ arr <command> [flags]` ;
59+
60+ const TERMS = `${ bold ( "TERMS" ) }
61+ stack: A sequence of changes, each building off of its parent.
62+ ex: main <- "add API" <- "update frontend" <- "docs"
63+ trunk: The branch that stacks are merged into (e.g., main).
64+ change: A jj commit/revision. Unlike git, jj tracks the working
65+ copy as a change automatically.` ;
66+
67+ const GLOBAL_OPTIONS = `${ bold ( "GLOBAL OPTIONS" ) }
68+ --help Show help for a command.
69+ --help --all Show full command reference.
70+ --version Show arr version number.` ;
71+
72+ const JJ_PASSTHROUGH = `${ bold ( "JJ PASSTHROUGH" ) }
73+ Unrecognized commands are passed directly to jj (e.g., arr diff, arr show).` ;
74+
75+ const DOCS = `${ bold ( "DOCS" ) }
76+ Get started: https://github.com/posthog/array` ;
77+
78+ function formatCommand ( cmd : CommandInfo ) : string {
79+ const full = cmd . args ? `${ cmd . name } ${ cmd . args } ` : cmd . name ;
80+ const aliasStr = cmd . aliases ?. length
81+ ? ` ${ dim ( `[aliases: ${ cmd . aliases . join ( ", " ) } ]` ) } `
82+ : "" ;
83+ return ` ${ cyan ( full . padEnd ( CMD_WIDTH ) ) } ${ cmd . description } .${ aliasStr } ` ;
84+ }
85+
86+ function formatCoreCommand ( cmd : CommandInfo ) : string {
87+ const full = cmd . args ? `${ cmd . name } ${ cmd . args } ` : cmd . name ;
88+ return ` ${ cyan ( full . padEnd ( CMD_WIDTH ) ) } ${ cmd . description } .` ;
89+ }
90+
4091function printHelp ( ) : void {
41- console . log ( `
42- ${ bold ( "arr" ) } - Stacked PRs and changeset management with jj
43-
44- ${ bold ( "USAGE:" ) }
45- arr <command> [options]
46-
47- ${ bold ( "STACKING COMMANDS:" ) }
48- ${ cyan ( "create" ) } <desc> Create a new stacked change
49- ${ cyan ( "create" ) } -a <desc> Commit all changes, start new change
50- ${ cyan ( "modify" ) } Save current changes (auto with jj)
51- ${ cyan ( "checkout" ) } <id> Switch to any change
52- ${ cyan ( "up" ) } Move up the stack (to child)
53- ${ cyan ( "down" ) } Move down the stack (to parent)
54- ${ cyan ( "top" ) } Jump to top of stack
55- ${ cyan ( "bottom" ) } Jump to bottom of stack
56- ${ cyan ( "log" ) } Show visual stack overview
57- ${ cyan ( "submit" ) } Create PR for current change
58- ${ cyan ( "submit" ) } --stack Submit entire stack as linked PRs
59- ${ cyan ( "submit" ) } --draft Create draft PR(s)
60- ${ cyan ( "sync" ) } Fetch, rebase stack, cleanup merged
61- ${ cyan ( "restack" ) } Rebase stack onto main
62-
63- ${ bold ( "CHANGESET COMMANDS:" ) }
64- ${ cyan ( "status" ) } Show current preview state
65- ${ cyan ( "list" ) } List all changesets
66- ${ cyan ( "enable" ) } <id...> Enable changeset(s) in preview
67- ${ cyan ( "disable" ) } <id...> Disable changeset(s) from preview
68- ${ cyan ( "swap" ) } <id> Enable changeset, disable conflicts
69- ${ cyan ( "edit" ) } <id> Edit a changeset directly
70- ${ cyan ( "edit" ) } --done Exit editing, return to preview
71- ${ cyan ( "abandon" ) } <id> Delete a changeset
72- ${ cyan ( "conflicts" ) } [id...] Check for file conflicts
73- ${ cyan ( "undo" ) } Undo last operation
74-
75- ${ bold ( "SETUP:" ) }
76- ${ cyan ( "init" ) } Initialize Array in this repo
77- ${ cyan ( "auth" ) } Authenticate with GitHub
78- ${ cyan ( "config" ) } Configure preferences
79-
80- ${ bold ( "OTHER:" ) }
81- ${ cyan ( "exit" ) } Exit Array, return to normal git
82- ${ cyan ( "help" ) } Show this help message
83- ${ cyan ( "version" ) } Show version
84-
85- ${ bold ( "ALIASES:" ) }
86- ${ cyan ( "c" ) } = create, ${ cyan ( "s" ) } = submit, ${ cyan ( "m" ) } = modify, ${ cyan ( "l" ) } = log
87- ${ cyan ( "co" ) } = checkout, ${ cyan ( "e" ) } = enable, ${ cyan ( "d" ) } = disable, ${ cyan ( "st" ) } = status
88-
89- ${ bold ( "JJ PASSTHROUGH:" ) }
90- Any unrecognized command is passed to jj directly.
91- Example: arr diff, arr rebase
92-
93- ${ dim ( "For more info: https://github.com/posthog/array" ) }
92+ const coreCommands = getCoreCommands ( ) ;
93+
94+ console . log ( `${ TAGLINE }
95+
96+ ${ USAGE }
97+
98+ ${ TERMS }
99+
100+ ${ bold ( "CORE COMMANDS" ) }
101+ ${ coreCommands . map ( formatCoreCommand ) . join ( "\n" ) }
102+
103+ Run ${ cyan ( "arr --help --all" ) } for a full command reference.
104+ Pass --help to any command for details (e.g., ${ cyan ( "arr submit --help" ) } )
105+
106+ ${ bold ( "CORE WORKFLOW" ) }
107+ 1. ${ cyan ( 'arr create "add user auth"' ) } Create a new change
108+ 2. ${ dim ( "(make edits - jj tracks automatically)" ) }
109+ 3. ${ cyan ( 'arr create "add tests"' ) } Stack another change
110+ 4. ${ cyan ( "arr submit --stack" ) } Create PRs for the stack
111+ 5. ${ cyan ( "arr sync" ) } Fetch & rebase after reviews
112+
113+ ${ bold ( "LEARN MORE" ) }
114+ Documentation: https://github.com/posthog/array
115+ jj documentation: https://www.jj-vcs.dev/latest/
116+ ` ) ;
117+ }
118+
119+ function printHelpAll ( ) : void {
120+ const hidden = new Set ( [ "help" , "version" , "config" ] ) ;
121+ const sections = CATEGORY_ORDER . map ( ( category ) => {
122+ const commands = getCommandsByCategory ( category ) . filter (
123+ ( c ) => ! hidden . has ( c . name ) ,
124+ ) ;
125+ if ( commands . length === 0 ) return "" ;
126+ return `${ bold ( CATEGORY_LABELS [ category ] ) } \n${ commands . map ( formatCommand ) . join ( "\n" ) } ` ;
127+ } ) . filter ( Boolean ) ;
128+
129+ console . log ( `${ TAGLINE }
130+
131+ ${ USAGE }
132+
133+ ${ TERMS }
134+
135+ ${ sections . join ( "\n\n" ) }
136+
137+ ${ GLOBAL_OPTIONS }
138+
139+ ${ JJ_PASSTHROUGH }
140+
141+ ${ DOCS }
94142` ) ;
95143}
96144
@@ -161,7 +209,11 @@ export async function main(): Promise<void> {
161209 const command = resolveCommandAlias ( parsed . name ) ;
162210
163211 if ( parsed . flags . help || parsed . flags . h ) {
164- printHelp ( ) ;
212+ if ( parsed . flags . all ) {
213+ printHelpAll ( ) ;
214+ } else {
215+ printHelp ( ) ;
216+ }
165217 return ;
166218 }
167219
@@ -193,7 +245,7 @@ export async function main(): Promise<void> {
193245 break ;
194246 }
195247 case "init" :
196- await init ( ) ;
248+ await init ( parsed . flags ) ;
197249 break ;
198250 case "auth" :
199251 await auth ( ) ;
@@ -258,6 +310,18 @@ export async function main(): Promise<void> {
258310 case "checkout" :
259311 await checkout ( parsed . args [ 0 ] ) ;
260312 break ;
313+ case "delete" :
314+ await deleteChange ( parsed . args [ 0 ] ) ;
315+ break ;
316+ case "continue" :
317+ await continueCommand ( parsed . flags ) ;
318+ break ;
319+ case "merge" :
320+ await merge ( parsed . flags ) ;
321+ break ;
322+ case "stacks" :
323+ await stacks ( ) ;
324+ break ;
261325 case "undo" :
262326 await undo ( ) ;
263327 break ;
0 commit comments