natemoo-re / clack Goto Github PK
View Code? Open in Web Editor NEWEffortlessly build beautiful command-line apps
Home Page: https://clack.cc
Effortlessly build beautiful command-line apps
Home Page: https://clack.cc
@clack/core
: unstyled, extensible primitives for CLIs@clack/prompts
: beautiful, ready-to-use CLI prompt componentsInfrastructure
input
and output
to each prompt to mock)Stability:
Features:
prompts
/ inquirer
, but tree-shakeable)Is your feature request related to a problem? Please describe.
In some scenarios lists could be very long. therefor it would be nice to have a filter option built-in to view just a subset of items
Describe the solution you'd like
An element like the multiselect/select input but with a filter option on top so that a user can type and the list items update
Describe alternatives you've considered
Current alternative is to use a prompt and let the user enter a search term. on the next step just show items which maches. Not that nice from a UX perspective tbh.
Additional context
Thanks to the whole team for open sourcing/maintaining this tool 🙏
See the following Gif for behavior on my machine.
v1.6.0
System:
OS: MacOS
CPU: M1
Shell: ZSH
Binaries:
Node: 18.5.0
npm: 9.5.0
Is your feature request related to a problem? Please describe.
I ask the user for an account id. I like to validate this id by checking it against the db which I can't do sync.
Describe the solution you'd like
Make validate
compatible with async
.
Describe alternatives you've considered
Currently I load all the accounts before the prompt so I can validate the id sync. This doesn't scale though.
Additional context
That's it :)
and including return an particular step if ...
like prompt type but with chain question
(with text and can show the "final beard" choosen on result ... )
Environment
Describe the bug
The terminal duplicates options in a select when moving arrows up and down if the window is too small and the lines try to wrap. More of a rendering bug, because if you expand the terminal, it seems to start working normally, but the duplicates stay and aren't selectable.
To Reproduce
https://stackblitz.com/edit/node-omu3tm?file=prompts.js
Steps to reproduce the behavior:
Expected behavior
The select should behave normally, moving arrows up and down should not duplicate everything. This seems to be a limitation of the terminal itself, perhaps truncation and an ellipsis of the long options would help.
Is your feature request related to a problem? Please describe.
I would like to enter a folder directory input and I want it clack auto complete these folders like zsh
Describe the solution you'd like
Create a input type name with path input and handle it like zsh shell
I found a source related this
Thank you for this project. Do you consider adding support for inquirer
-like prompt?
Is your feature request related to a problem? Please describe.
It's kinda frustating to have to put a isCancel after each prompt.
Describe the solution you'd like
Somewhere I can define a onCancel, that always like exits the process for example.
Describe alternatives you've considered
Have an onCancel prop on each prompt, so that if you Ctrl + C it auto executes the function on the prop
Is your feature request related to a problem? Please describe.
Having a multi-select with some answers pre-defined
Describe the solution you'd like
Being able to pre-define a multi-select with selected: true
or something similar.
Describe alternatives you've considered
Using another library, unfortunately.
Additional context
Love this library, and thing it works great :)
Your project looks promising !
Would you consider to add a Multiline Text Input like in Gum (https://github.com/charmbracelet/gum#write) ?
Is your feature request related to a problem? Please describe.
sometimes CLI apps have "interactive mode" and so select features we want to run and stop thinking "what i should use for ...".
or some complex use case require to select many values on different categories ...
Describe the solution you'd like
have ast tree like this but just the square in the idea ... or not ...
return {path:..., value:string} maybe
minimal data will be
{
node:"parent",
children: [
node:"parent2",
children:[...]
]
}
Describe alternatives you've considered
Additional context
making cli app but wait until there is a hope from this package, it's dont exist on other npm package (or dont see).
use https://github.com/terkelg/prompts but thats very silly because dynamic props is too harsh (only on previous prompt, not the global result)
Let's say you have 5 prompts for installing a database. These prompts ask for things like host, port, user, password, etc.
I'd love for clack to be able to hide/remove the last prompt and cleanly display the next prompt. I think that this would allow the console to be cleaner and just show the user what they are currently interacting with/answering.
Describe the bug
appdetails.packagename = await text({
message: "Enter the Package name: ",
placeholder: "placeholder",
validate(value) {
if (!packegeRegex.test(value)) {
return "Invalid PackageName";
}
},
});
Here the appdetails.packagename type is "string". and shows this error
Type 'string | symbol' is not assignable to type 'string'.
It seems that multiselect requires at least one selected option. I hope there could be an option to determine if the multiselect allows zero chosen options.
Is your feature request related to a problem? Please describe.
When getting a value from a prompt that includes a placeholder
, it'd be nice if the user doesn't have to typoe it out explicitly. Other prompts allow pressing Tab to fill in the placeholder. Can we add this to Clack please?
import { text } from "@clack/prompts";
const value = await text({
message: "input text please",
placeholder: "default value do I have to type this out"
});
Describe the solution you'd like
When an input prompt is active and the placeholder
exists and .startsWith
the current typed text value (intentionally true for ""
), pressing Tab should set the current typed text value to the placeholder
.
Describe alternatives you've considered
🤷
Additional context
I'd love to send a PR! ❤️
Hi, Is it a bug that "multiselect" return undefined in this example, Or did I do something wrong?
Is your feature request related to a problem? Please describe.
The TypeScript types for select
and multiselect
options enforce that value
fields passed extend Readonly<string>
:
clack/packages/prompts/src/index.ts
Lines 118 to 120 in d366a1f
This can be a bit cumbersome to use with non-string values, as it requires stringifying to pass to select
+ parsing the result returned back.
Describe the solution you'd like
Ideally (assuming no technical blockers + context I'm missing), select
and multiselect
could support any type of value. (perhaps naively) it looks like this could be as simple as changing the code block above to support a looser Value
generic.
Describe alternatives you've considered
Stringifying + parsing as described above, though this isn't always feasible for more complex types.
Additional context
Interestingly, from my (relatively basic) testing, this only seems to be a type error. Passing in Date
values works as expected - are there other types of values which may break this?
If the fix is as simple as I'm imagining, I'd be happy to open a PR and take a stab at this! However, I'm still fairly early in my testing of this library so I may be missing some important context of why this limitation exists :)
Is your feature request related to a problem? Please describe.
I am using select like this.
const selectedMenuValue = await select({
message: "Options",
options: options,
});
my options is quite big, I know this is not good idea
Describe the solution you'd like
Is there any pagination feature to auto split the options so in the options will be automatically added such as "More options" so user can navigate the large options.
Environment
Describe the bug
As README mentions, multi-select returns an array with all selected value
props, but it returns options selected.
To Reproduce
Expected behavior
multi-select should return array with values selected.
Is your feature request related to a problem? Please describe.
no
Describe the solution you'd like
Blink the cursor to prompt the user for input when text
Describe alternatives you've considered
no
Additional context
no
Looks like the import of ansi-regex
in @clack/prompts/dist/index.cjs
causes my CommonJs project to crash.
/Users/severinbuhler/git/synonym/blocktank-instant/node_modules/@clack/prompts/dist/index.cjs:1
"use strict";const core=require("@clack/core"),color=require("picocolors"),sisteransi=require("sisteransi"),ansiRegex=require("ansi-regex"),symbol=t=>{switch(t){case"initial":case"active":return color.cyan("\u25CF");case"cancel":return color.red("\u25A0");case"error":return color.yellow("\u25B2");case"submit":return color.green("\u25CB")}},barStart="\u250C",bar="\u2502",barEnd="\u2514",text=t=>new core.TextPrompt({validate:t.validate,placeholder:t.placeholder,render(){const i=`${color.gray(bar)}
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/severinbuhler/git/synonym/blocktank-instant/node_modules/@clack/prompts/node_modules/ansi-regex/index.js from /Users/severinbuhler/git/synonym/blocktank-instant/node_modules/@clack/prompts/dist/index.cjs not supported.
Instead change the require of index.js in /Users/severinbuhler/git/synonym/blocktank-instant/node_modules/@clack/prompts/dist/index.cjs to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/Users/severinbuhler/git/synonym/blocktank-instant/node_modules/@clack/prompts/dist/index.cjs:1:119)
at Object.<anonymous> (/Users/severinbuhler/git/synonym/blocktank-instant/dist/3_cli/index.js:26:29) {
code: 'ERR_REQUIRE_ESM'
}
Node.js v18.12.1
Attempted to run the small example code in the README file but got an error.
Node version 17.9.1
OS: Mac OS Ventura
Create a new project (npm init
then insteall @clock/core
, copy and paste the first code block in this bug report and attempt to run it
node index.mjs
on the following file called index.mjs
import { TextPrompt, isCancel } from "@clack/core";
const p = new TextPrompt({
render() {
return `What's your name?\n${this.valueWithCursor}`;
},
});
const name = await p.prompt();
if (isCancel(name)) {
return;
}
fails with the following error:
~/Downloads/test-scripts/clack-cli-test node index.mjs
file:///Users/cfajardo/Downloads/test-scripts/clack-cli-test/index.mjs:11
return;
^^^^^^
SyntaxError: Illegal return statement
at ESMLoader.moduleStrategy (node:internal/modules/esm/translators:117:18)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:361:14)
at async link (node:internal/modules/esm/module_job:70:21)
It seems the problem is with the isCancel
because this works fine:
// index.mjs`
import { TextPrompt, isCancel } from "@clack/core";
const p = new TextPrompt({
render() {
return `What's your name?\n${this.valueWithCursor}`;
},
});
const name = await p.prompt();
//if (isCancel(name)) {
//return;
//}
Currently there is not (or I couldn't find) a way to append arbitraty entries as part of the current prompt chain.
You can add new prompts, notes or spinners, but not just a single line of text without breaking the left side bar.
I've hacked a way into it by creating a fake no-time spinner like so:
addText(text) {
const sp = spinner();
sp.start(text);
sp.stop(text);
}
// Using it like:
intro('Welcome to this tool')
const res = await text({
message: 'What's your name',
placeholder: 'your name'
});
addText('My custom text as part of the prompt line')
It would be nice to have a straightforward way to just append a line of text, no prompt, no fancy stuff, just text that doesn't break the line with a function called something else like message
or similar:
intro('Welcome to this tool')
const res = await text({
message: 'What's your name',
placeholder: 'your name'
});
message('my custom text')
I tested the example in your README:
const meaning = await text({
message: "What is the meaning of life?",
placeholder: "Not sure",
initialValue: "42",
validate(value) {
console.log('value', value)
if (value.length === 0) return `Value is required!`;
},
});
The value of the argument of validate method is the placeholder set in text
method options (printed by the console.log)
So, you can't validate an empty response from the user
And by the way, the option initialValue
is not available for this method and not working
Is your feature request related to a problem? Please describe.
multi-select prompt is requires at least one option, but in some cases, we may not select anything.
Describe the solution you'd like
How about allowing empty array in multi-select prompt?
Currently, it is possible with validate
, but it would be nice to allow them in option.
Describe alternatives you've considered
I also considered the possibility of specifying the minimum and maximum values that can be selected with options, but I thought it would complicate things a bit.
Is your feature request related to a problem? Please describe.
No
Describe the solution you'd like
Since prompts is super nice it would be since to see a way to either change the theme
of the prompts either containing theme within another repo that has those themes, but since prompts is one color and has default set of icons
. You could possibly create a way to customize the colors through config or maybe some type of system that can define these as a variant or theme. Since prompts
is more a granular term but could be perceived as an all in one alternative solution for CLI prompts.
Describe alternatives you've considered
N/A
Additional context
I would like to discuss more here but it's an idea. Even though @clack/prompts
is a wrapper for core
I foresee it being bigger package that is built off of core that can include many handy utils, functions, and prompts. Maybe it's the wrong package for it. I am kinda thinking of variants like astro-theme
, clack-theme
and these will drive icons, styles etc.
The select prompt currently returns undefined
instead of the selected options value.
const projectType = await select({
message: "TypeScript or JavaScript?",
options: [
{ value: "ts", label: "TypeScript", hint: "recommended" },
{ value: "js", label: "JavaScript" },
],
});
console.log(projectType) // undefined
Is your feature request related to a problem? Please describe.
No
Describe the solution you'd like
For Select and Multi-Select prompts, I'd like to mark individual options as disabled
.
Describe alternatives you've considered
An alternative is to remove the option. However, this impacts discoverability since users of the CLI wouldn't know that option existed.
Additional context
I imagine to use the hint
property for disabled options to inform why it is disabled.
Environment
Describe the bug
Some context: I believe 0.3.1 fixed this via wrap-ansi
for terminals such as item
or item2
On any terminal emulator such as: Alacritty, Kitty, Wezterm. -- Once a prompt begins to line wrap, it will repeatedly print the line every keypress (alternatively, resize the terminal to the point that text starts to wrap. once the resize
callback fires render
, the same effect will occur)
To Reproduce
Steps to reproduce the behavior:
Install any GPU accelerated terminal (alacritty, kitty, wezterm)
import { TextPrompt } from '@clack/core';
const po = new TextPrompt({
render() {
return `What's your name?\n${this.valueWithCursor}`;
},
});
Type enough text, or resize the terminal to where a line wrap occurs.
Expected behavior
How it behaves in iterm is the expected behavior. i.e. the line is not duplicated (see video)
Additional Information
I tried debugging this myself, I can tell the issue is happening when render
is being called in prompt.ts
. ansi-wrap doesn't seem to impact terminal emulators like alacritty/kitty. You can set the column wrap to a really low number (instead of process.stdout.columns
) and the wrap never seems to be enforced.
Environment
git 2.39.1.windows.1
v16
@clack/prompts
v0.4.4
Describe the bug
The second (and only that) confirm()
/select()
after a spinner()
breaks.
-> no reaction to left/right/up/down keys
pressing enter feeds a break, but still shows no text
left/right/up/down key then redraws the yes/no a line below (notable breaking the colored L
too)
To Reproduce
https://stackblitz.com/edit/node-bnwkvt?file=index.ts
not reproduceable on stackblitz -> this seems to be a windows-terminal issue maybe?...
Steps to reproduce the behavior:
npm i && npm run script
Expected behavior
Q4 should not print twice, and not need three keypresses (enter to void, arrow to render, enter to select)
Environment
@clack/prompts
, @clack/core
Describe the bug
ctrl + c dont working with spinner. Whenever I add spinnir code, all ctrl commands are disabled.
dont working terminal ctrl + c kill.
import { execa, execaSync } from 'execa'
const s = p.spinner()
s.start('Emulator başlatılıyor')
s.stop('Emulator başlatıldı')
execaSync('pnpm', ['dev:app'], { stdio: 'inherit', detached: true })
working
import { execa, execaSync } from 'execa'
execaSync('pnpm', ['dev:app'], { stdio: 'inherit', detached: true })
Is your feature request related to a problem? Please describe.
I would like to add functionality to toggle up or down using the Ctrl-n or Ctrl-p keys.
Describe the solution you'd like
type KeyAlias = {
key: string;
ctrl: boolean;
};
const aliases = new Map<string | KeyAlias, string>([
['k', 'up'],
['j', 'down'],
['h', 'left'],
['l', 'right'],
[{ key: 'n', ctrl: true }, 'down'],
[{ key: 'p', ctrl: true }, 'up'],
]);
I believe this code is functioning correctly.
Additional context
The Mac operating system universally employs this type of method for moving.
Environment
Describe the bug
I stumbled on some strange side effects, apparently the array that is passed in to initialValue
is modified in a multiselect
if you check in other values than the one you passed in to initialValue
To Reproduce
initialValue
.Expected behavior
The array should not be mutated.
Is your feature request related to a problem? Please describe.
Currently, the left decorative line is not displayed when using \n
line break.
import { confirm } from '@clack/prompts'
const msg = await confirm({
message: 'Hello,\nWorld!',
}),
◆ Hello,
World!
│ ● Yes / ○ No
└
Describe the solution you'd like
Let message accept string[]
, like this:
import { confirm } from '@clack/prompts'
const msg = await confirm({
message: ['Hello,', 'World!'],
}),
◆ Hello,
│ World!
│ ● Yes / ○ No
└
Is your feature request related to a problem? Please describe.
Having the option to provide secondary text to provide more details or instruction would allow for more succinct prompts.
Describe the solution you'd like
const myPrompt = await text({
message: 'This is the primary question:',
description: 'This is secondary text displayed between the message and where the user fills in the prompt`
})
Describe alternatives you've considered
I've tried writing longer prompts and getting clever with line breaks, but it takes away from Clack's gorgeous UI.
Additional context
N/A
Do you consider adding a file selection prompt with file-tree style?
Something like this: https://github.com/anc95/inquirer-file-tree-selection
Is your feature request related to a problem? Please describe.
I think have a onCancel
property will be better.
Currently I need to call isCanceled
in every prompts, I think it is troublesome.
Describe the solution you'd like
import { text, cancel } from '@clack/prompts'
const result = await text({
/* Other options */
onCancel() {
cancel('Operation canceled.')
process.exit(1)
}
})
I think this is a good feature in some scences.
Environment
Describe the bug
To Reproduce
https://stackblitz.com/edit/node-lbgrtu?file=index.js,package.json
Steps to reproduce the behavior:
Expected behavior
the box should wrap the text
Additional Information
If applicable, add screenshots to help explain your problem.
Is your feature request related to a problem? Please describe.
We've gotten feedback that the Symbol('clack:cancel')
approach and the onCancel
don't feel like the ideal API for handling cancellation, and I agree.
I'm opening this issue to continue the discussion about what an API for graceful cancellation could look like.
Describe the solution you'd like
Seems like AbortController
is designed specifically for this use case, so maybe there's some inspiration to take from the signal
pattern?
Describe alternatives you've considered
Open to discussion!
Additional context
See #68
Environment
@clack/prompts
, @clack/core
]Describe the bug
A clear and concise description of what the bug is.
To Reproduce
Include a link to a minimal reproduction using node.new
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Additional Information
If applicable, add screenshots to help explain your problem.
Environment
@clack/prompts
Describe the bug
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 end listeners added to [ReadStream]. Use emitter.setMaxListeners() to increase limit
To Reproduce
After using the await select
a lot, the warning message above shows up.
Expected behavior
Should not show up.
Let me know if you got questions. It's probably just even emitter listener cleanup.
Help wanted!
Would love ensure we have better support for terminals that do not support unicode. Likely will pull in is-unicode-supported
and provide fallback glyphs for the custom ones we're using.
Would like to request for the text component to accept an initial value for the user the edit.
Is your feature request related to a problem? Please describe.
When the logic between spinner.start()
& spinner.stop()
throws an error and terminates the process, it seems to cause issues with the terminal cursor:
So to work around this, the logic block needs to be wrapped in a try-finally
to call spinner.stop()
.
Describe the solution you'd like
An exit hook inside spinner
to cleanup the readline
prompt if the process is about to exit:
process.on('exit', () => {
if (spinnerActive) {
// terminate readline
}
})
Describe alternatives you've considered
Delegate try-finally
wrappers to user-land, but it's not very ergonomic to do this every time spinner
is used.
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
When trying to use hjkl (motion) to go through the options, nothing happens.
Describe the solution you'd like
Get to move through options using hjkl.
Additional context
e.g.: When I create a new React Native app, it gives me options to select and I'm able to use hjkl to move through them.
Environment: Tmux
I was trying to find a good way of getting a of if(isCancel(res))
in favor for hooks that can be wrapped for a better DX.
If the developer had more control over the hooks it can be more easily customized, intercept events and more.
"clark:input:cancel": () => {//... code here for exit }
I have a working POC on my local computer but I first wanted to see if it's viable to do so.
Additionally you could have other hooks for "clark:init", "clark:input:submit" and pass or modify additional parameters if need be or in the future create custom ways for users to create there own "preset" of the theme using clack.
Let me know what you think. @natemoo-re.
Thanks,
CP
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.