Skip to content

Commit 97c0bde

Browse files
committed
feat: show env in flag help
1 parent 8df097a commit 97c0bde

File tree

2 files changed

+266
-2
lines changed

2 files changed

+266
-2
lines changed

src/help/command.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,25 @@ export class CommandHelp extends HelpFormatter {
190190
if (noChar) left = left.replace(' ', '')
191191

192192
let right = flag.summary || flag.description || ''
193+
194+
// Build metadata string (default, env, or both)
195+
const metadata: string[] = []
193196
const canBeCached = !(this.opts.respectNoCacheDefault === true && flag.noCacheDefault === true)
194-
if (flag.type === 'option' && flag.default && canBeCached) {
195-
right = `${colorize(this.config?.theme?.flagDefaultValue, `[default: ${flag.default}]`)} ${right}`
197+
198+
if (flag.type === 'option') {
199+
if (flag.default && canBeCached) {
200+
metadata.push(`default: ${flag.default}`)
201+
}
202+
203+
if (flag.env) {
204+
metadata.push(`env: ${flag.env}`)
205+
}
206+
} else if (flag.type === 'boolean' && flag.env) {
207+
metadata.push(`env: ${flag.env}`)
208+
}
209+
210+
if (metadata.length > 0) {
211+
right = `${colorize(this.config?.theme?.flagDefaultValue, `[${metadata.join(', ')}]`)} ${right}`
196212
}
197213

198214
if (flag.required) right = `${colorize(this.config?.theme?.flagRequired, '(required)')} ${right}`

test/help/format-command.test.ts

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,3 +967,251 @@ FLAGS
967967
-c, --cFlag=<value>`)
968968
})
969969
})
970+
971+
describe('formatCommand with env and default values', () => {
972+
let config: Config
973+
let help: TestHelp
974+
975+
before(async () => {
976+
config = await Config.load(process.cwd())
977+
})
978+
979+
beforeEach(() => {
980+
help = new TestHelp(config)
981+
})
982+
983+
describe('option flags', () => {
984+
it('should show default value for option flag with default', async () => {
985+
const cmd = await makeLoadable(
986+
makeCommandClass({
987+
id: 'test:cmd',
988+
flags: {
989+
myFlag: flags.string({default: 'myDefault', description: 'my flag'}),
990+
},
991+
}),
992+
)
993+
994+
const output = help.formatCommand(cmd)
995+
expect(output).to.equal(`USAGE
996+
$ oclif test:cmd [--myFlag <value>]
997+
998+
FLAGS
999+
--myFlag=<value> [default: myDefault] my flag`)
1000+
})
1001+
1002+
it('should show env variable for option flag with env', async () => {
1003+
const cmd = await makeLoadable(
1004+
makeCommandClass({
1005+
id: 'test:cmd',
1006+
flags: {
1007+
myFlag: flags.string({env: 'MY_FLAG', description: 'my flag'}),
1008+
},
1009+
}),
1010+
)
1011+
1012+
const output = help.formatCommand(cmd)
1013+
expect(output).to.equal(`USAGE
1014+
$ oclif test:cmd [--myFlag <value>]
1015+
1016+
FLAGS
1017+
--myFlag=<value> [env: MY_FLAG] my flag`)
1018+
})
1019+
1020+
it('should show both default and env for option flag with both', async () => {
1021+
const cmd = await makeLoadable(
1022+
makeCommandClass({
1023+
id: 'test:cmd',
1024+
flags: {
1025+
myFlag: flags.string({default: 'myDefault', env: 'MY_FLAG', description: 'my flag'}),
1026+
},
1027+
}),
1028+
)
1029+
1030+
const output = help.formatCommand(cmd)
1031+
expect(output).to.equal(`USAGE
1032+
$ oclif test:cmd [--myFlag <value>]
1033+
1034+
FLAGS
1035+
--myFlag=<value> [default: myDefault, env: MY_FLAG] my flag`)
1036+
})
1037+
1038+
it('should not show default when noCacheDefault is true and respectNoCacheDefault is true', async () => {
1039+
const helpWithRespectNoCache = new TestHelp(config, {respectNoCacheDefault: true})
1040+
const cmd = await makeLoadable(
1041+
makeCommandClass({
1042+
id: 'test:cmd',
1043+
flags: {
1044+
myFlag: flags.string({default: 'secret', noCacheDefault: true, description: 'my flag'}),
1045+
},
1046+
}),
1047+
)
1048+
1049+
const output = helpWithRespectNoCache.formatCommand(cmd)
1050+
expect(output).to.equal(`USAGE
1051+
$ oclif test:cmd [--myFlag <value>]
1052+
1053+
FLAGS
1054+
--myFlag=<value> my flag`)
1055+
})
1056+
1057+
it('should show env but not default when noCacheDefault is true and respectNoCacheDefault is true', async () => {
1058+
const helpWithRespectNoCache = new TestHelp(config, {respectNoCacheDefault: true})
1059+
const cmd = await makeLoadable(
1060+
makeCommandClass({
1061+
id: 'test:cmd',
1062+
flags: {
1063+
myFlag: flags.string({
1064+
default: 'secret',
1065+
env: 'MY_FLAG',
1066+
noCacheDefault: true,
1067+
description: 'my flag',
1068+
}),
1069+
},
1070+
}),
1071+
)
1072+
1073+
const output = helpWithRespectNoCache.formatCommand(cmd)
1074+
expect(output).to.equal(`USAGE
1075+
$ oclif test:cmd [--myFlag <value>]
1076+
1077+
FLAGS
1078+
--myFlag=<value> [env: MY_FLAG] my flag`)
1079+
})
1080+
1081+
it('should show default value when noCacheDefault is true but respectNoCacheDefault is not set', async () => {
1082+
const cmd = await makeLoadable(
1083+
makeCommandClass({
1084+
id: 'test:cmd',
1085+
flags: {
1086+
myFlag: flags.string({default: 'myDefault', noCacheDefault: true, description: 'my flag'}),
1087+
},
1088+
}),
1089+
)
1090+
1091+
const output = help.formatCommand(cmd)
1092+
expect(output).to.equal(`USAGE
1093+
$ oclif test:cmd [--myFlag <value>]
1094+
1095+
FLAGS
1096+
--myFlag=<value> [default: myDefault] my flag`)
1097+
})
1098+
})
1099+
1100+
describe('boolean flags', () => {
1101+
it('should show env variable for boolean flag with env', async () => {
1102+
const cmd = await makeLoadable(
1103+
makeCommandClass({
1104+
id: 'test:cmd',
1105+
flags: {
1106+
myFlag: flags.boolean({env: 'MY_FLAG', description: 'my flag'}),
1107+
},
1108+
}),
1109+
)
1110+
1111+
const output = help.formatCommand(cmd)
1112+
expect(output).to.equal(`USAGE
1113+
$ oclif test:cmd [--myFlag]
1114+
1115+
FLAGS
1116+
--myFlag [env: MY_FLAG] my flag`)
1117+
})
1118+
1119+
it('should not show default for boolean flag (even if it has one)', async () => {
1120+
const cmd = await makeLoadable(
1121+
makeCommandClass({
1122+
id: 'test:cmd',
1123+
flags: {
1124+
myFlag: flags.boolean({default: false, description: 'my flag'}),
1125+
},
1126+
}),
1127+
)
1128+
1129+
const output = help.formatCommand(cmd)
1130+
expect(output).to.equal(`USAGE
1131+
$ oclif test:cmd [--myFlag]
1132+
1133+
FLAGS
1134+
--myFlag my flag`)
1135+
})
1136+
1137+
it('should show env for boolean flag with env, ignoring default', async () => {
1138+
const cmd = await makeLoadable(
1139+
makeCommandClass({
1140+
id: 'test:cmd',
1141+
flags: {
1142+
myFlag: flags.boolean({default: false, env: 'MY_FLAG', description: 'my flag'}),
1143+
},
1144+
}),
1145+
)
1146+
1147+
const output = help.formatCommand(cmd)
1148+
expect(output).to.equal(`USAGE
1149+
$ oclif test:cmd [--myFlag]
1150+
1151+
FLAGS
1152+
--myFlag [env: MY_FLAG] my flag`)
1153+
})
1154+
})
1155+
1156+
describe('multiple flags with mixed configurations', () => {
1157+
it('should handle multiple flags with different configurations', async () => {
1158+
const cmd = await makeLoadable(
1159+
makeCommandClass({
1160+
id: 'test:cmd',
1161+
flags: {
1162+
optionWithDefault: flags.string({default: 'defaultValue', description: 'option with default'}),
1163+
optionWithEnv: flags.string({env: 'OPTION_ENV', description: 'option with env'}),
1164+
optionWithBoth: flags.string({
1165+
default: 'defaultValue',
1166+
env: 'OPTION_BOTH',
1167+
description: 'option with both',
1168+
}),
1169+
booleanWithEnv: flags.boolean({env: 'BOOL_ENV', description: 'boolean with env'}),
1170+
plainOption: flags.string({description: 'plain option'}),
1171+
plainBoolean: flags.boolean({description: 'plain boolean'}),
1172+
},
1173+
}),
1174+
)
1175+
1176+
const output = help.formatCommand(cmd)
1177+
expect(output).to.equal(`USAGE
1178+
$ oclif test:cmd [--optionWithDefault <value>] [--optionWithEnv
1179+
<value>] [--optionWithBoth <value>] [--booleanWithEnv] [--plainOption
1180+
<value>] [--plainBoolean]
1181+
1182+
FLAGS
1183+
--booleanWithEnv [env: BOOL_ENV] boolean with env
1184+
--optionWithBoth=<value> [default: defaultValue, env: OPTION_BOTH] option
1185+
with both
1186+
--optionWithDefault=<value> [default: defaultValue] option with default
1187+
--optionWithEnv=<value> [env: OPTION_ENV] option with env
1188+
--plainBoolean plain boolean
1189+
--plainOption=<value> plain option`)
1190+
})
1191+
})
1192+
1193+
describe('with required flags', () => {
1194+
it('should show required after default and env', async () => {
1195+
const cmd = await makeLoadable(
1196+
makeCommandClass({
1197+
id: 'test:cmd',
1198+
flags: {
1199+
myFlag: flags.string({
1200+
default: 'defaultValue',
1201+
env: 'MY_FLAG',
1202+
required: true,
1203+
description: 'my flag',
1204+
}),
1205+
},
1206+
}),
1207+
)
1208+
1209+
const output = help.formatCommand(cmd)
1210+
expect(output).to.equal(`USAGE
1211+
$ oclif test:cmd --myFlag <value>
1212+
1213+
FLAGS
1214+
--myFlag=<value> (required) [default: defaultValue, env: MY_FLAG] my flag`)
1215+
})
1216+
})
1217+
})

0 commit comments

Comments
 (0)