@lsst/pik-plugin-select 0.6.6 → 0.7.0

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/README.md CHANGED
@@ -43,7 +43,9 @@ pik select set <name> <option> # Set directly
43
43
  ## Marker Syntax
44
44
 
45
45
  - `@pik:select <name>` - Defines a selector group
46
- - `@pik:option <name>` - Marks an option within a selector
46
+ - `@pik:option <name>` - Marks a single-line option within a selector
47
+ - `@pik:block-start <name>` - Starts a multi-line block option
48
+ - `@pik:block-end` - Ends a multi-line block option
47
49
 
48
50
  ### Inline Style
49
51
 
@@ -67,6 +69,28 @@ Marker on its own line, content on the next line (useful for HTML):
67
69
  <!-- <script src="http://localhost:3000/viewer.js"></script> -->
68
70
  ```
69
71
 
72
+ ### Block Style
73
+
74
+ For multi-line options where you need to switch entire blocks of configuration:
75
+
76
+ ```bash
77
+ # @pik:select Environment
78
+ # @pik:block-start Development
79
+ API_URL=http://localhost:3000
80
+ DEBUG=true
81
+ LOG_LEVEL=debug
82
+ # @pik:block-end
83
+ # @pik:block-start Production
84
+ # API_URL=https://api.example.com
85
+ # DEBUG=false
86
+ # LOG_LEVEL=error
87
+ # @pik:block-end
88
+ ```
89
+
90
+ When switching blocks:
91
+ - The selected block's content lines are uncommented
92
+ - All other blocks' content lines are commented out
93
+
70
94
  ## Supported File Types
71
95
 
72
96
  | Extensions | Comment Style |
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Command } from "commander";
2
2
  import pc from "picocolors";
3
- import { relative, extname } from "path";
4
- import { Parser, loadConfig, SingleSwitcher } from "@lsst/pik-core";
3
+ import { relative } from "path";
4
+ import { Parser, loadConfig, BlockSwitcher, SingleSwitcher } from "@lsst/pik-core";
5
5
  import { readFile, writeFile } from "fs/promises";
6
6
  import { glob } from "glob";
7
7
  import { select, Separator } from "@inquirer/prompts";
@@ -27,6 +27,21 @@ class Scanner {
27
27
  return results;
28
28
  }
29
29
  }
30
+ function hasBlockOptions$2(selector) {
31
+ return selector.blockOptions.length > 0;
32
+ }
33
+ function getActiveOptionName$1(selector) {
34
+ if (hasBlockOptions$2(selector)) {
35
+ return selector.blockOptions.find((b) => b.isActive)?.name ?? null;
36
+ }
37
+ return selector.options.find((o) => o.isActive)?.name ?? null;
38
+ }
39
+ function getAllOptions$1(selector) {
40
+ if (hasBlockOptions$2(selector)) {
41
+ return selector.blockOptions.map((b) => ({ name: b.name, isActive: b.isActive }));
42
+ }
43
+ return selector.options.map((o) => ({ name: o.name, isActive: o.isActive }));
44
+ }
30
45
  const listCommand = new Command("list").alias("ls").description("List all selectors and their current state").option("--json", "Output in JSON format").action(async (options) => {
31
46
  const config = await loadConfig();
32
47
  if (!config?.select) {
@@ -45,11 +60,9 @@ const listCommand = new Command("list").alias("ls").description("List all select
45
60
  name: selector.name,
46
61
  file: relative(process.cwd(), file.path),
47
62
  line: selector.line,
48
- activeOption: selector.options.find((o) => o.isActive)?.name ?? null,
49
- options: selector.options.map((o) => ({
50
- name: o.name,
51
- isActive: o.isActive
52
- }))
63
+ activeOption: getActiveOptionName$1(selector),
64
+ isBlock: hasBlockOptions$2(selector),
65
+ options: getAllOptions$1(selector)
53
66
  }))
54
67
  );
55
68
  console.log(JSON.stringify(jsonOutput, null, 2));
@@ -63,10 +76,11 @@ const listCommand = new Command("list").alias("ls").description("List all select
63
76
  const relativePath = relative(process.cwd(), file.path);
64
77
  console.log(pc.cyan(relativePath));
65
78
  for (const selector of file.selectors) {
66
- const activeOption = selector.options.find((o) => o.isActive);
67
- const activeLabel = activeOption ? pc.green(activeOption.name) : pc.yellow("none");
68
- console.log(` ${pc.bold(selector.name)}: ${activeLabel}`);
69
- for (const option of selector.options) {
79
+ const activeOptionName = getActiveOptionName$1(selector);
80
+ const activeLabel = activeOptionName ? pc.green(activeOptionName) : pc.yellow("none");
81
+ const blockIndicator = hasBlockOptions$2(selector) ? pc.dim(" [block]") : "";
82
+ console.log(` ${pc.bold(selector.name)}${blockIndicator}: ${activeLabel}`);
83
+ for (const option of getAllOptions$1(selector)) {
70
84
  const marker = option.isActive ? pc.green("●") : pc.dim("○");
71
85
  console.log(` ${marker} ${option.name}`);
72
86
  }
@@ -74,6 +88,9 @@ const listCommand = new Command("list").alias("ls").description("List all select
74
88
  console.log();
75
89
  }
76
90
  });
91
+ function hasBlockOptions$1(selector) {
92
+ return selector.blockOptions.length > 0;
93
+ }
77
94
  const setCommand = new Command("set").description("Set a specific option for a selector").argument("<selector>", "Selector name").argument("<option>", "Option to activate").action(async (selectorName, optionName) => {
78
95
  const config = await loadConfig();
79
96
  if (!config?.select) {
@@ -87,10 +104,15 @@ const setCommand = new Command("set").description("Set a specific option for a s
87
104
  const selector = file.selectors.find((s) => s.name === selectorName);
88
105
  if (selector) {
89
106
  found = true;
90
- const extension = extname(file.path);
91
- const switcher = SingleSwitcher.forExtension(extension);
92
107
  try {
93
- const newContent = switcher.switch(file.content, selector, optionName);
108
+ let newContent;
109
+ if (hasBlockOptions$1(selector)) {
110
+ const switcher = BlockSwitcher.forFilePath(file.path);
111
+ newContent = switcher.switch(file.content, selector, optionName);
112
+ } else {
113
+ const switcher = SingleSwitcher.forFilePath(file.path);
114
+ newContent = switcher.switch(file.content, selector, optionName);
115
+ }
94
116
  await writeFile(file.path, newContent);
95
117
  const relativePath = relative(process.cwd(), file.path);
96
118
  console.log(
@@ -113,6 +135,21 @@ const BACK_VALUE = /* @__PURE__ */ Symbol("back");
113
135
  function isExitPromptError(error) {
114
136
  return error instanceof Error && error.name === "ExitPromptError";
115
137
  }
138
+ function hasBlockOptions(selector) {
139
+ return selector.blockOptions.length > 0;
140
+ }
141
+ function getActiveOptionName(selector) {
142
+ if (hasBlockOptions(selector)) {
143
+ return selector.blockOptions.find((b) => b.isActive)?.name ?? null;
144
+ }
145
+ return selector.options.find((o) => o.isActive)?.name ?? null;
146
+ }
147
+ function getAllOptions(selector) {
148
+ if (hasBlockOptions(selector)) {
149
+ return selector.blockOptions.map((b) => ({ name: b.name, isActive: b.isActive }));
150
+ }
151
+ return selector.options.map((o) => ({ name: o.name, isActive: o.isActive }));
152
+ }
116
153
  const switchCommand = new Command("switch").alias("sw").description("Interactively switch options").action(async () => {
117
154
  const config = await loadConfig();
118
155
  if (!config?.select) {
@@ -139,10 +176,11 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
139
176
  choices: [
140
177
  ...choices.map((choice) => {
141
178
  const relativePath2 = relative(process.cwd(), choice.file.path);
142
- const activeOption = choice.selector.options.find((o) => o.isActive);
143
- const current = activeOption ? pc.dim(` (${activeOption.name})`) : "";
179
+ const activeOptionName = getActiveOptionName(choice.selector);
180
+ const current = activeOptionName ? pc.dim(` (${activeOptionName})`) : "";
181
+ const blockIndicator = hasBlockOptions(choice.selector) ? pc.dim(" [block]") : "";
144
182
  return {
145
- name: `${choice.selector.name}${current} ${pc.dim(`- ${relativePath2}`)}`,
183
+ name: `${choice.selector.name}${blockIndicator}${current} ${pc.dim(`- ${relativePath2}`)}`,
146
184
  value: choice
147
185
  };
148
186
  }),
@@ -160,11 +198,12 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
160
198
  return;
161
199
  }
162
200
  let selectedOption;
201
+ const allOptions = getAllOptions(selectedChoice.selector);
163
202
  try {
164
203
  selectedOption = await select({
165
204
  message: `Select option for ${pc.bold(selectedChoice.selector.name)}`,
166
205
  choices: [
167
- ...selectedChoice.selector.options.map((option) => ({
206
+ ...allOptions.map((option) => ({
168
207
  name: option.isActive ? `${option.name} ${pc.green("(current)")}` : option.name,
169
208
  value: option.name
170
209
  })),
@@ -181,12 +220,22 @@ const switchCommand = new Command("switch").alias("sw").description("Interactive
181
220
  if (selectedOption === BACK_VALUE) {
182
221
  continue;
183
222
  }
184
- const switcher = SingleSwitcher.forFilePath(selectedChoice.file.path);
185
- const newContent = switcher.switch(
186
- selectedChoice.file.content,
187
- selectedChoice.selector,
188
- selectedOption
189
- );
223
+ let newContent;
224
+ if (hasBlockOptions(selectedChoice.selector)) {
225
+ const switcher = BlockSwitcher.forFilePath(selectedChoice.file.path);
226
+ newContent = switcher.switch(
227
+ selectedChoice.file.content,
228
+ selectedChoice.selector,
229
+ selectedOption
230
+ );
231
+ } else {
232
+ const switcher = SingleSwitcher.forFilePath(selectedChoice.file.path);
233
+ newContent = switcher.switch(
234
+ selectedChoice.file.content,
235
+ selectedChoice.selector,
236
+ selectedOption
237
+ );
238
+ }
190
239
  await writeFile(selectedChoice.file.path, newContent);
191
240
  const relativePath = relative(process.cwd(), selectedChoice.file.path);
192
241
  console.log(
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,aAAa,CAAC;AAMrB,eAAO,MAAM,WAAW,SA6DpB,CAAC"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,OAAO,aAAa,CAAC;AAiCrB,eAAO,MAAM,WAAW,SA4DpB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,OAAO,aAAa,CAAC;AAErB,eAAO,MAAM,UAAU,SA8CnB,CAAC"}
1
+ {"version":3,"file":"set.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,OAAO,aAAa,CAAC;AASrB,eAAO,MAAM,UAAU,SAqDnB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,aAAa,CAAC;AAarB,eAAO,MAAM,aAAa,SAyGtB,CAAC"}
1
+ {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,OAAO,aAAa,CAAC;AAwCrB,eAAO,MAAM,aAAa,SAuHtB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lsst/pik-plugin-select",
3
- "version": "0.6.6",
3
+ "version": "0.7.0",
4
4
  "description": "Config selector plugin for pik CLI",
5
5
  "type": "module",
6
6
  "license": "MIT",