@oclif/plugin-search 1.2.12-dev.0 → 1.2.12

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
@@ -22,7 +22,7 @@ $ npm install -g @oclif/plugin-search
22
22
  $ @oclif/plugin-search COMMAND
23
23
  running command...
24
24
  $ @oclif/plugin-search (--version)
25
- @oclif/plugin-search/1.2.12-dev.0 linux-x64 node-v20.17.0
25
+ @oclif/plugin-search/1.2.12 linux-x64 node-v20.17.0
26
26
  $ @oclif/plugin-search --help [COMMAND]
27
27
  USAGE
28
28
  $ @oclif/plugin-search COMMAND
@@ -41,11 +41,7 @@ Search for a command.
41
41
 
42
42
  ```
43
43
  USAGE
44
- $ @oclif/plugin-search search [-a help|copy|doctor|source|npm]
45
-
46
- FLAGS
47
- -a, --action=<option> Action to take on the selected command
48
- <options: help|copy|doctor|source|npm>
44
+ $ @oclif/plugin-search search
49
45
 
50
46
  DESCRIPTION
51
47
  Search for a command.
@@ -53,7 +49,7 @@ DESCRIPTION
53
49
  Once you select a command, hit enter and it will show the help for that command.
54
50
  ```
55
51
 
56
- _See code: [src/commands/search.ts](https://github.com/oclif/plugin-search/blob/v1.2.12-dev.0/src/commands/search.ts)_
52
+ _See code: [src/commands/search.ts](https://github.com/oclif/plugin-search/blob/v1.2.12/src/commands/search.ts)_
57
53
  <!-- commandsstop -->
58
54
 
59
55
  # Contributing
@@ -1,10 +1,6 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Search extends Command {
3
3
  static description: string;
4
- static readonly flags: {
5
- action: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
- };
7
- static readonly strict = false;
8
4
  static summary: string;
9
5
  run(): Promise<unknown>;
10
6
  }
@@ -4,36 +4,15 @@
4
4
  * Licensed under the BSD 3-Clause license.
5
5
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
- import search from '@inquirer/search';
8
- import { Command, Flags, loadHelpClass, toConfiguredId, toStandardizedId, ux } from '@oclif/core';
9
- import { bold } from 'ansis';
10
- import clipboard from 'clipboardy';
11
- import fuzzysort from 'fuzzysort';
12
- import { got } from 'got';
7
+ import { Command, loadHelpClass, toConfiguredId, toStandardizedId, ux } from '@oclif/core';
8
+ import ansiEscapes from 'ansi-escapes';
9
+ import autocomplete from 'inquirer-autocomplete-standalone';
13
10
  import readline from 'node:readline';
14
- import open from 'open';
15
11
  export default class Search extends Command {
16
12
  static description = 'Once you select a command, hit enter and it will show the help for that command.';
17
- static flags = {
18
- action: Flags.string({
19
- char: 'a',
20
- options: ['help', 'copy', 'doctor', 'source', 'npm'],
21
- summary: 'Action to take on the selected command',
22
- }),
23
- };
24
- static strict = false;
25
13
  static summary = 'Search for a command.';
26
14
  async run() {
27
- const { argv, flags } = await this.parse(Search);
28
- // Join the args together into a string so you can pass something like 'dep sta' to fuzzy search
29
- const args = argv.join(' ');
30
- const theme = {
31
- helpMode: 'never',
32
- prefix: ux.colorize('cyan', `Use ${ux.colorize('bold', '↑')} and ${ux.colorize('bold', '↓')} keys or type to search for a command.\nPress ${ux.colorize('bold', 'ENTER')} to view help. Press ${ux.colorize('bold', 'ESC')} to exit.\n\n`),
33
- style: {
34
- description: (desc) => `\n${ux.colorize('cyan', desc)}`, // Give the description a little extra padding
35
- },
36
- };
15
+ this.log(ux.colorize('cyan', `Use ${ux.colorize('bold', '↑')} and ${ux.colorize('bold', '↓')} keys or type to search for a command.\nPress ${ux.colorize('bold', 'ENTER')} to view help. Press ${ux.colorize('bold', 'ESC')} to exit.\n`));
37
16
  const commandChoices = this.config.commands
38
17
  .filter((c) => !c.hidden && !c.aliases.includes(c.id))
39
18
  .sort((a, b) => a.id.localeCompare(b.id))
@@ -46,37 +25,26 @@ export default class Search extends Command {
46
25
  };
47
26
  });
48
27
  const pageSize = Math.floor(process.stdout.rows < 20 ? process.stdout.rows / 2 : 10);
49
- const commandPromise = search({
28
+ const commandPromise = autocomplete({
29
+ emptyText: 'Nothing found!',
50
30
  message: 'Search for a command',
51
31
  pageSize,
52
32
  async source(input) {
53
- // TODO: There is a bug here somewhere:
54
- // - pass an arg
55
- // - hit down arrow
56
- // - hit any other character with clear the input
57
- // - hitting delete will clear input, but keep the fuzzy results
58
- if (input === undefined && args)
59
- input = args;
60
- const results = fuzzysort.go(input, commandChoices, { all: true, key: 'name' });
61
- return results.map((r) => ({
62
- description: r.obj.description,
63
- name: r.highlight(bold.open, bold.close),
64
- value: r.obj.value,
65
- }));
33
+ return input ? commandChoices.filter((c) => c.name.includes(input)) : commandChoices;
66
34
  },
67
- // @ts-expect-error Not sure why this is complaining about the helpMode type
68
- theme,
69
- }, { clearPromptOnDone: true });
35
+ });
36
+ function cancel() {
37
+ commandPromise.cancel();
38
+ // erase the list of commands
39
+ process.stdout.write(ansiEscapes.eraseLines(pageSize + 3));
40
+ }
70
41
  readline.emitKeypressEvents(process.stdin);
71
42
  process.stdin.setRawMode(true);
72
- // If args were passed in, we "replay" the key presses to populate the search
73
- if (args)
74
- process.stdin.emit('data', args);
75
- // Allow the user to exit the search with the escape key or with ctrl+c
76
43
  process.stdin.on('keypress', (_, key) => {
77
- if ((key.name === 'escape' || (key.name === 'c' && key.ctrl)) && commandPromise) {
78
- commandPromise.cancel();
79
- }
44
+ if (key.name === 'escape')
45
+ cancel();
46
+ if (key.name === 'c' && key.ctrl)
47
+ cancel();
80
48
  });
81
49
  const command = await commandPromise
82
50
  .catch((error) => {
@@ -87,120 +55,8 @@ export default class Search extends Command {
87
55
  .then((result) => result);
88
56
  if (!command)
89
57
  return;
90
- // eslint-disable-next-line unicorn/consistent-function-scoping
91
- const getPluginDetails = (command) => {
92
- const commandId = toStandardizedId(command, this.config);
93
- const commandConfig = this.config.findCommand(commandId);
94
- const pluginName = commandConfig?.pluginName;
95
- if (!pluginName)
96
- this.error('Key `pluginName` not found in the config for this command.');
97
- const commandPjson = this.config.plugins.get(pluginName)?.pjson;
98
- const homepage = commandPjson?.homepage;
99
- // TODO: add a check for homepage
100
- const commandVersion = commandPjson?.version;
101
- return { commandConfig, commandId, commandPjson, commandVersion, homepage, pluginName };
102
- };
103
- const getSourceUrl = async (homepage, commandId, commandVersion) => {
104
- if (!homepage)
105
- return;
106
- const commandToPath = `${commandId.replaceAll(':', '/')}.ts`;
107
- // TODO: do we need to take into account directory level index.ts command files?
108
- // TODO: talk to Mike about dynamically built command paths
109
- const urls = [
110
- `/blob/${commandVersion}/src/commands/${commandToPath}`,
111
- `/blob/v${commandVersion}/src/commands/${commandToPath}`,
112
- `/blob/-/src/commands/${commandToPath}`,
113
- `/blob/main/src/commands/${commandToPath}`,
114
- `/blob/master/src/commands/${commandToPath}`,
115
- ];
116
- const responses = await Promise.all(urls.map((url) => got(`${homepage}${url}`, { throwHttpErrors: false })));
117
- return responses.find((r) => r.statusCode === 200)?.url ?? undefined;
118
- };
119
- const { commandId, commandVersion, homepage, pluginName } = getPluginDetails(command);
120
- const sourceUrl = await getSourceUrl(homepage, commandId, commandVersion);
121
- let actionPrompt;
122
- if (!flags.action) {
123
- const actions = [
124
- {
125
- description: 'Show the help text for this command',
126
- name: 'Show help',
127
- value: 'help',
128
- },
129
- {
130
- description: 'Copy the command to your clipboard',
131
- name: 'Copy command',
132
- value: 'copy',
133
- },
134
- {
135
- description: 'Copy the command to your clipboard for use with the doctor command',
136
- name: 'Copy command for doctor',
137
- value: 'doctor',
138
- },
139
- {
140
- description: 'Open the source code for this command on GitHub',
141
- disabled: sourceUrl ? false : '(Unable to resolve source code URL)',
142
- name: 'Go to source code',
143
- value: 'source',
144
- },
145
- {
146
- description: 'View the npm details for this package',
147
- name: 'View package on npm',
148
- value: 'npm',
149
- },
150
- ];
151
- const actionPromise = search({
152
- message: `Select an action for: ${ux.colorize('dim', '$ sf ' + command)}`,
153
- pageSize,
154
- async source(input) {
155
- const results = fuzzysort.go(input, actions, { all: true, key: 'name' });
156
- return results.map((r) => ({
157
- description: r.obj.description,
158
- disabled: r.obj.disabled,
159
- name: r.highlight(bold.open, bold.close),
160
- value: r.obj.value,
161
- }));
162
- },
163
- // @ts-expect-error Not sure why this is complaining about the helpMode type
164
- theme,
165
- }, { clearPromptOnDone: true });
166
- // Allow the user to exit the search with the escape key or with ctrl+c
167
- process.stdin.on('keypress', (_, key) => {
168
- if ((key.name === 'escape' || (key.name === 'c' && key.ctrl)) && actionPromise) {
169
- actionPromise.cancel();
170
- }
171
- });
172
- actionPrompt = await actionPromise
173
- .catch((error) => {
174
- if (error.message === 'Prompt was canceled')
175
- return;
176
- throw error;
177
- })
178
- .then((result) => result);
179
- }
180
- switch (flags.action ?? actionPrompt) {
181
- case 'help': {
182
- const Help = await loadHelpClass(this.config);
183
- const help = new Help(this.config, this.config.pjson.oclif.helpOptions ?? this.config.pjson.helpOptions);
184
- return help.showHelp([toStandardizedId(command, this.config)]);
185
- }
186
- case 'copy': {
187
- clipboard.writeSync(`sf ${command} `);
188
- this.log(ux.colorize('green', 'Command copied to clipboard!'));
189
- break;
190
- }
191
- case 'doctor': {
192
- clipboard.writeSync(`sf doctor --command "${command}"`);
193
- this.log(ux.colorize('green', 'Command copied to clipboard!'));
194
- break;
195
- }
196
- case 'npm': {
197
- open(`https://www.npmjs.com/package/${pluginName}/v/${commandVersion}`);
198
- break;
199
- }
200
- case 'source': {
201
- open(sourceUrl);
202
- break;
203
- }
204
- }
58
+ const Help = await loadHelpClass(this.config);
59
+ const help = new Help(this.config, this.config.pjson.oclif.helpOptions ?? this.config.pjson.helpOptions);
60
+ return help.showHelp([toStandardizedId(command, this.config)]);
205
61
  }
206
62
  }
@@ -4,30 +4,14 @@
4
4
  "aliases": [],
5
5
  "args": {},
6
6
  "description": "Once you select a command, hit enter and it will show the help for that command.",
7
- "flags": {
8
- "action": {
9
- "char": "a",
10
- "name": "action",
11
- "summary": "Action to take on the selected command",
12
- "hasDynamicHelp": false,
13
- "multiple": false,
14
- "options": [
15
- "help",
16
- "copy",
17
- "doctor",
18
- "source",
19
- "npm"
20
- ],
21
- "type": "option"
22
- }
23
- },
7
+ "flags": {},
24
8
  "hasDynamicHelp": false,
25
9
  "hiddenAliases": [],
26
10
  "id": "search",
27
11
  "pluginAlias": "@oclif/plugin-search",
28
12
  "pluginName": "@oclif/plugin-search",
29
13
  "pluginType": "core",
30
- "strict": false,
14
+ "strict": true,
31
15
  "summary": "Search for a command.",
32
16
  "enableJsonFlag": false,
33
17
  "isESM": true,
@@ -42,5 +26,5 @@
42
26
  ]
43
27
  }
44
28
  },
45
- "version": "1.2.12-dev.0"
29
+ "version": "1.2.12"
46
30
  }
package/package.json CHANGED
@@ -1,17 +1,13 @@
1
1
  {
2
2
  "name": "@oclif/plugin-search",
3
- "version": "1.2.12-dev.0",
3
+ "version": "1.2.12",
4
4
  "description": "A command for searching commands",
5
5
  "author": "Salesforce",
6
6
  "bugs": "https://github.com/oclif/plugin-search/issues",
7
7
  "dependencies": {
8
- "@inquirer/search": "^2.0.1",
9
8
  "@oclif/core": "^4",
10
- "ansis": "^3.3.2",
11
- "clipboardy": "^4.0.0",
12
- "fuzzysort": "^3.0.2",
13
- "got": "^13.0.0",
14
- "open": "^10.1.0"
9
+ "ansi-escapes": "^7.0.0",
10
+ "inquirer-autocomplete-standalone": "^0.8.1"
15
11
  },
16
12
  "devDependencies": {
17
13
  "@commitlint/config-conventional": "^19",
@@ -20,18 +16,18 @@
20
16
  "@oclif/prettier-config": "^0.2.1",
21
17
  "@types/chai": "^4",
22
18
  "@types/inquirer": "^8.2.10",
23
- "@types/mocha": "^10.0.8",
19
+ "@types/mocha": "^10.0.9",
24
20
  "@types/node": "^18",
25
21
  "chai": "^4",
26
22
  "commitlint": "^19",
27
23
  "eslint": "^8.57.1",
28
24
  "eslint-config-oclif": "^5.2.1",
29
- "eslint-config-oclif-typescript": "^3.1.11",
25
+ "eslint-config-oclif-typescript": "^3.1.12",
30
26
  "eslint-config-prettier": "^9.1.0",
31
27
  "husky": "^9.1.6",
32
28
  "lint-staged": "^15",
33
29
  "mocha": "^10.7.3",
34
- "oclif": "^4.15.3",
30
+ "oclif": "^4.15.6",
35
31
  "prettier": "^3.3.3",
36
32
  "shx": "^0.3.3",
37
33
  "ts-node": "^10.9.2",