pickem 1.0.0 → 1.0.1
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 +66 -69
- package/package.json +1 -9
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# pickem
|
|
2
2
|
|
|
3
|
-
Usage-sorted searchable autocomplete for CLI tools
|
|
3
|
+
**Usage-sorted, searchable autocomplete for CLI tools.** Give every command-line tool the same fast, interactive picker: type to filter, arrow to choose — and the options you reach for most float to the top on their own.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
  
|
|
6
|
+
|
|
7
|
+
- **Search as you type** — filter on labels, descriptions, or any field you name
|
|
8
|
+
- **Usage-aware ordering** — frequently chosen items sort to the top automatically
|
|
9
|
+
- **Single- and multi-select** — with optional free-text entry for ad-hoc values
|
|
10
|
+
- **Wizard flows** — chain prompts with branching and conditional steps
|
|
11
|
+
- **Light and fully typed** — one runtime dependency, ESM, ships with types
|
|
6
12
|
|
|
7
13
|
## Install
|
|
8
14
|
|
|
@@ -10,30 +16,23 @@ pickem runs on its **own native picker engine** — no `@inquirer`, no prompt-li
|
|
|
10
16
|
npm install pickem
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
An interactive tour of every feature ships with the repo:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
git clone https://github.com/calebogden/pickem
|
|
19
|
-
cd pickem && npm install && npm run demo
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Quick Start
|
|
19
|
+
## Quick start
|
|
23
20
|
|
|
24
21
|
```typescript
|
|
25
22
|
import { pickem } from 'pickem'
|
|
26
23
|
|
|
27
24
|
const choice = await pickem([
|
|
28
25
|
{ label: 'Deploy', value: 'deploy', description: 'Push to production' },
|
|
29
|
-
{ label: 'Test',
|
|
30
|
-
{ label: 'Lint',
|
|
26
|
+
{ label: 'Test', value: 'test', description: 'Run test suite' },
|
|
27
|
+
{ label: 'Lint', value: 'lint', description: 'Check formatting' },
|
|
31
28
|
])
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
Type to filter, arrow keys to move, Enter to choose. The selected value is returned.
|
|
32
|
+
|
|
33
|
+
## Multi-select
|
|
35
34
|
|
|
36
|
-
`pickem.checkbox(items, opts)` returns
|
|
35
|
+
`pickem.checkbox(items, opts)` returns the values of every checked item.
|
|
37
36
|
|
|
38
37
|
```typescript
|
|
39
38
|
import { pickem } from 'pickem'
|
|
@@ -46,35 +45,37 @@ const choices = await pickem.checkbox([
|
|
|
46
45
|
// => ['deploy', 'test']
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
Space toggles a selection, Enter submits, type to filter, Esc clears the filter, Backspace removes filter characters.
|
|
50
49
|
|
|
51
|
-
Pass `searchable: false` to fall back to
|
|
50
|
+
Pass `searchable: false` to fall back to a plain checkbox list with no search bar:
|
|
52
51
|
|
|
53
52
|
```typescript
|
|
54
53
|
const choices = await pickem.checkbox(items, { searchable: false })
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
Pass `
|
|
56
|
+
Pass `allowFreeText: true` to let users add ad-hoc entries: type text that matches nothing, press Enter, and it's appended to the list as a checked item — the filter clears and the picker stays open so they can keep going.
|
|
58
57
|
|
|
59
58
|
```typescript
|
|
60
59
|
const tags = await pickem.checkbox(KNOWN_TAGS, { allowFreeText: true })
|
|
61
60
|
```
|
|
62
61
|
|
|
63
|
-
## Usage
|
|
62
|
+
## Usage-aware ordering
|
|
64
63
|
|
|
65
|
-
Items sort by how often they'
|
|
64
|
+
Items sort by how often they've been chosen, so the picker adapts to how each user actually works. Enable it with `track: true`:
|
|
66
65
|
|
|
67
66
|
```typescript
|
|
68
67
|
const choice = await pickem(items, {
|
|
69
|
-
track: true,
|
|
70
|
-
// or:
|
|
68
|
+
track: true, // stored in ~/.pickem/usage.json
|
|
69
|
+
// or point it somewhere of your own:
|
|
71
70
|
track: { storePath: '~/.myapp/usage.json' },
|
|
72
71
|
})
|
|
73
72
|
```
|
|
74
73
|
|
|
75
|
-
3-tier sort: count
|
|
74
|
+
Ordering is a 3-tier sort: usage count, then most-recently-used, then alphabetical.
|
|
76
75
|
|
|
77
|
-
## Multiple
|
|
76
|
+
## Multiple sources
|
|
77
|
+
|
|
78
|
+
Pull items from several places at once — they load in parallel and merge into one picker.
|
|
78
79
|
|
|
79
80
|
```typescript
|
|
80
81
|
import { pickem, defineSource } from 'pickem'
|
|
@@ -86,45 +87,45 @@ const scripts = defineSource('scripts', async () => [
|
|
|
86
87
|
|
|
87
88
|
const npm = defineSource('npm', async () => [
|
|
88
89
|
{ label: 'build', value: 'npm run build' },
|
|
89
|
-
{ label: 'test',
|
|
90
|
+
{ label: 'test', value: 'npm test' },
|
|
90
91
|
])
|
|
91
92
|
|
|
92
93
|
const choice = await pickem.from([scripts, npm], { track: true })
|
|
93
|
-
//
|
|
94
|
+
// Set badgeStyle to label each item by source, e.g. [scripts], [npm]
|
|
94
95
|
```
|
|
95
96
|
|
|
96
|
-
## Wizard
|
|
97
|
+
## Wizard flows
|
|
97
98
|
|
|
98
|
-
Chain multiple prompts with branching
|
|
99
|
+
Chain multiple prompts together, with branching and conditional steps.
|
|
99
100
|
|
|
100
101
|
```typescript
|
|
101
102
|
import { wizard } from 'pickem'
|
|
102
103
|
|
|
103
104
|
const result = await wizard([
|
|
104
|
-
{ id: 'action', type: 'pick',
|
|
105
|
-
{ id: 'env',
|
|
105
|
+
{ id: 'action', type: 'pick', message: 'What to do?', items: allScripts },
|
|
106
|
+
{ id: 'env', type: 'select', message: 'Environment:', choices: [
|
|
106
107
|
{ label: 'Production', value: 'prod' },
|
|
107
|
-
{ label: 'Staging',
|
|
108
|
+
{ label: 'Staging', value: 'staging' },
|
|
108
109
|
], when: ctx => ctx.action === 'deploy' },
|
|
109
110
|
{ id: 'confirm', type: 'confirm', message: 'Are you sure?' },
|
|
110
|
-
{ id: 'route',
|
|
111
|
+
{ id: 'route', type: 'branch', on: ctx => ctx.confirm ? 'done' : 'action' },
|
|
111
112
|
])
|
|
112
113
|
```
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
|
117
|
-
|------|---------|
|
|
118
|
-
| `pick` | Searchable usage-sorted selection |
|
|
115
|
+
| Step type | Purpose |
|
|
116
|
+
|------------|---------|
|
|
117
|
+
| `pick` | Searchable, usage-sorted selection |
|
|
119
118
|
| `checkbox` | Searchable multi-select, returns an array |
|
|
120
|
-
| `select`
|
|
121
|
-
| `input`
|
|
122
|
-
| `confirm`
|
|
123
|
-
| `branch`
|
|
119
|
+
| `select` | Simple choice list |
|
|
120
|
+
| `input` | Free text entry |
|
|
121
|
+
| `confirm` | Yes / no |
|
|
122
|
+
| `branch` | Route to a step ID or inject steps dynamically |
|
|
124
123
|
|
|
125
|
-
|
|
124
|
+
Every step supports `when` (run conditionally) and `before` (a pre-step hook).
|
|
126
125
|
|
|
127
|
-
## Standalone
|
|
126
|
+
## Standalone usage tracker
|
|
127
|
+
|
|
128
|
+
The usage tracker works on its own, too — handy for ranking anything by frequency.
|
|
128
129
|
|
|
129
130
|
```typescript
|
|
130
131
|
import { UsageTracker } from 'pickem'
|
|
@@ -134,26 +135,26 @@ await tracker.track('deploy')
|
|
|
134
135
|
await tracker.track('deploy')
|
|
135
136
|
|
|
136
137
|
const sorted = await tracker.sortItems(items)
|
|
137
|
-
const top
|
|
138
|
-
const stats
|
|
138
|
+
const top = await tracker.getTop(10)
|
|
139
|
+
const stats = await tracker.getStats('deploy') // { count: 2, lastUsed: ... }
|
|
139
140
|
```
|
|
140
141
|
|
|
141
142
|
## Options
|
|
142
143
|
|
|
143
144
|
```typescript
|
|
144
145
|
await pickem(items, {
|
|
145
|
-
message: 'Pick one:',
|
|
146
|
-
pageSize: 15,
|
|
147
|
-
track: true
|
|
148
|
-
searchable: true,
|
|
149
|
-
searchFields: ['label', 'description'], // Fields to search (dot-notation for meta)
|
|
150
|
-
search: (item, term) => boolean, // Custom
|
|
151
|
-
format: (item, stats) => string, // Custom
|
|
152
|
-
badgeStyle: 'none' | 'bracket' | 'dot' | fn
|
|
153
|
-
badgeColors: { npm: 'red' },
|
|
154
|
-
sort: (a, b) => number,
|
|
155
|
-
onSelect: (item) => {},
|
|
156
|
-
allowFreeText:
|
|
146
|
+
message: 'Pick one:', // Prompt message
|
|
147
|
+
pageSize: 15, // Visible items per page
|
|
148
|
+
track: true, // Enable usage tracking (true | TrackOptions)
|
|
149
|
+
searchable: true, // false skips the search bar
|
|
150
|
+
searchFields: ['label', 'description'], // Fields to search (dot-notation for nested meta)
|
|
151
|
+
search: (item, term) => boolean, // Custom match function
|
|
152
|
+
format: (item, stats) => string, // Custom row formatter
|
|
153
|
+
badgeStyle: 'none', // Group badge style: 'none' | 'bracket' | 'dot' | fn
|
|
154
|
+
badgeColors: { npm: 'red' }, // Per-group badge colors
|
|
155
|
+
sort: (a, b) => number, // Tiebreaker applied after usage sort
|
|
156
|
+
onSelect: (item) => {}, // Callback fired on selection
|
|
157
|
+
allowFreeText: false, // Surface unmatched input as a selectable option
|
|
157
158
|
})
|
|
158
159
|
```
|
|
159
160
|
|
|
@@ -162,20 +163,16 @@ await pickem(items, {
|
|
|
162
163
|
```typescript
|
|
163
164
|
await pickem.checkbox(items, {
|
|
164
165
|
required: false, // Require at least one selection before Enter submits
|
|
165
|
-
defaultChecked: ['test'], //
|
|
166
|
-
allowFreeText: true, // Type unmatched text + Enter to add as a checked item
|
|
166
|
+
defaultChecked: ['test'], // Values checked on open
|
|
167
|
+
allowFreeText: true, // Type unmatched text + Enter to add it as a checked item
|
|
167
168
|
})
|
|
168
169
|
```
|
|
169
170
|
|
|
170
|
-
### `badgeStyle` default changed in v0.2.0
|
|
171
|
-
|
|
172
|
-
The default `badgeStyle` is now `'none'` — group labels are hidden unless you opt in. This is a breaking change if your code relied on the old default of `'bracket'`. To restore the previous behavior:
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
await pickem(items, { badgeStyle: 'bracket' })
|
|
176
|
-
```
|
|
177
|
-
|
|
178
171
|
## Requirements
|
|
179
172
|
|
|
180
|
-
- Node >= 18
|
|
173
|
+
- Node.js >= 18
|
|
181
174
|
- ESM only
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pickem",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Usage-sorted searchable autocomplete for CLI tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -21,14 +21,6 @@
|
|
|
21
21
|
"picker",
|
|
22
22
|
"wizard"
|
|
23
23
|
],
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "git+https://github.com/calebogden/pickem.git"
|
|
27
|
-
},
|
|
28
|
-
"bugs": {
|
|
29
|
-
"url": "https://github.com/calebogden/pickem/issues"
|
|
30
|
-
},
|
|
31
|
-
"homepage": "https://github.com/calebogden/pickem#readme",
|
|
32
24
|
"author": "Caleb Ogden <co@ogden.co>",
|
|
33
25
|
"license": "MIT",
|
|
34
26
|
"engines": {
|