Code Monkey home page Code Monkey logo

sharprompt's Introduction

Sharprompt

Build Downloads NuGet License

Interactive command-line based application framework for C#

sharprompt

Features

  • Multi-platform support
  • Supports the popular prompts (Input / Password / Select / etc)
  • Supports model-based prompts
  • Validation of input value
  • Automatic generation of data source using Enum type
  • Customizable symbols and color schema
  • Unicode support (Multi-byte characters and Emoji๐Ÿ˜€๐ŸŽ‰)

Installation

Install-Package Sharprompt
dotnet add package Sharprompt
// Simple input
var name = Prompt.Input<string>("What's your name?");
Console.WriteLine($"Hello, {name}!");

// Password input
var secret = Prompt.Password("Type new password", validators: new[] { Validators.Required(), Validators.MinLength(8) });
Console.WriteLine("Password OK");

// Confirmation
var answer = Prompt.Confirm("Are you ready?", defaultValue: true);
Console.WriteLine($"Your answer is {answer}");

Examples

The project in the folder Sharprompt.Example contains all the samples. Please check it.

dotnet run --project Sharprompt.Example

Prompt types

Input

Takes a generic type parameter and performs type conversion as appropriate.

var name = Prompt.Input<string>("What's your name?");
Console.WriteLine($"Hello, {name}!");

var number = Prompt.Input<int>("Enter any number");
Console.WriteLine($"Input = {number}");

input

Confirm

var answer = Prompt.Confirm("Are you ready?");
Console.WriteLine($"Your answer is {answer}");

confirm

Password

var secret = Prompt.Password("Type new password");
Console.WriteLine("Password OK");

password

Select

var city = Prompt.Select("Select your city", new[] { "Seattle", "London", "Tokyo" });
Console.WriteLine($"Hello, {city}!");

select

MultiSelect (Checkbox)

var cities = Prompt.MultiSelect("Which cities would you like to visit?", new[] { "Seattle", "London", "Tokyo", "New York", "Singapore", "Shanghai" }, pageSize: 3);
Console.WriteLine($"You picked {string.Join(", ", cities)}");

multiselect

List

var value = Prompt.List<string>("Please add item(s)");
Console.WriteLine($"You picked {string.Join(", ", value)}");

list

Bind (Model-based prompts)

// Input model definition
public class MyFormModel
{
    [Display(Name = "What's your name?")]
    [Required]
    public string Name { get; set; }

    [Display(Name = "Type new password")]
    [DataType(DataType.Password)]
    [Required]
    [MinLength(8)]
    public string Password { get; set; }

    [Display(Name = "Select your city")]
    [Required]
    [InlineItems("Seattle", "London", "Tokyo")]
    public string City { get; set; }

    [Display(Name = "Are you ready?")]
    public bool? Ready { get; set; }
}

var result = Prompt.Bind<MyFormModel>();

Configuration

Symbols

Prompt.Symbols.Prompt = new Symbol("๐Ÿค”", "?");
Prompt.Symbols.Done = new Symbol("๐Ÿ˜Ž", "V");
Prompt.Symbols.Error = new Symbol("๐Ÿ˜ฑ", ">>");

var name = Prompt.Input<string>("What's your name?");
Console.WriteLine($"Hello, {name}!");

Color schema

Prompt.ColorSchema.Answer = ConsoleColor.DarkRed;
Prompt.ColorSchema.Select = ConsoleColor.DarkCyan;

var name = Prompt.Input<string>("What's your name?");
Console.WriteLine($"Hello, {name}!");

Cancellation support

// Throw an exception when canceling with Ctrl-C
Prompt.ThrowExceptionOnCancel = true;

try
{
    var name = Prompt.Input<string>("What's your name?");
    Console.WriteLine($"Hello, {name}!");
}
catch (PromptCanceledException ex)
{
    Console.WriteLine("Prompt canceled");
}

Features

Enum type support

public enum MyEnum
{
    [Display(Name = "First value")]
    First,
    [Display(Name = "Second value")]
    Second,
    [Display(Name = "Third value")]
    Third
}

var value = Prompt.Select<MyEnum>("Select enum value");
Console.WriteLine($"You selected {value}");

Unicode support

// Prefer UTF-8 as the output encoding
Console.OutputEncoding = Encoding.UTF8;

var name = Prompt.Input<string>("What's your name?");
Console.WriteLine($"Hello, {name}!");

unicode support

Fluent interface support

using Sharprompt.Fluent;

// Use fluent interface
var city = Prompt.Select<string>(o => o.WithMessage("Select your city")
                                       .WithItems(new[] { "Seattle", "London", "Tokyo" })
                                       .WithDefaultValue("Seattle"));

Supported platforms

  • Windows
    • Command Prompt
    • PowerShell
    • Windows Terminal
  • Linux (Ubuntu, etc)
    • Windows Terminal (WSL 2)
  • macOS
    • Terminal.app

License

This project is licensed under the MIT License

sharprompt's People

Contributors

0xflotus avatar dependabot[bot] avatar ibexpeak avatar kimsey0 avatar m-nab avatar masatoru avatar pitysoft avatar rhotav avatar rodrigopiccelli avatar ryfu-msft avatar shibayan avatar volkanpaksoy avatar wischi-chr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sharprompt's Issues

Don't delete text input when it fails validation

If using for example the MinLength validator with a decently large minimum length, you might type a long, but not quite long enough, sentence, click Enter, then get an error message saying the Value is too short, then see your message deleted and have no way to recover it.

The user experience here could be improved if, after showing the error message, either the entered value is kept or it is possible to recover it in some way, for example by clicking the up arrow, like in most command line interfaces.

Customizable mask characters for password input

Make it possible to change the mask character when entering passwords.

Proposal

// Default '*'
// e.g. Type new password: ********
Prompt.Password("Type new password", passwordChar: '*');

// Override
// e.g. Type new password: โ—โ—โ—โ—โ—โ—โ—โ—
Prompt.Password("Type new password", passwordChar: 'โ—');

// Hidden
// e.g. Type new password: 
Prompt.Password("Type new password", passwordChar: null);

Pasting large text in prompt causes slow rendering and flickering

I believe that this might be related to #80, but when pasting an extremely large text into the prompt, The words are rendered slowly and the console begins flickering until all of the characters are visible.

Repro steps:

  • Copy text with greater than ~300 words
  • When prompt appears in console, paste text as response.

[Prompt] What is your name? :

Behavior:

  • Repeated flickering of the console while the words are being rendered.
  • Rendering is slower than normal until all words from the pasted text are visible.

Defining our own values for the Done Symbol (and other symbols)

The tool only provides getters to the symbols and since I'm working on a windows machine, unicode is not readily available thus resulting in the letter 'V' representing done. Would it be possible to add a setter to allow for more customization for how the done symbol is represented.

Renderer does not take into account overflowing values

Describe the bug

When value text overflows the line (appends to next line) pressing the 'down' error key will redraw the first line. This is because the 'reset' function does not take into account any overflowing lines. Since it uses an internal counter.

To Reproduce

Steps to reproduce the behavior:

  1. Using this version of ASP.NET Core 2.2
  2. Running on Windows 7 x64 Ultimate
  3. Using Cmd (externalTerminal --> launch.json)
  4. Append options that have too many charatcers for the current line
  5. Press the down key.

Expected behavior

Render should only show the change in selected value.

Screenshots

If applicable, add screenshots to help explain your problem.
image

Prompt.Select and Prompt.MultiSelect fail on Windows 10 in Git Bash

Prompt.Select and Prompt.MultiSelect fail on Windows 10 in Git Bash (the one installed with Git version 2.24.1.2)

Sharprompt Version 1.0.4

Example

Prompt.Select("Select value", new [] { "Value 1", "Value 2" });

Exception

Unhandled exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.IOException: The handle is invalid.
   at System.ConsolePal.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
   at System.Console.get_CursorLeft()
   at Sharprompt.ConsoleRenderer.Close()
   at Sharprompt.Select`1.Start()
   at Sharprompt.Prompt.Select[T](String message, IEnumerable`1 items, Object defaultValue, Int32 pageSize, Func`2 valueSelector)
   at Console.Commands.SystemCommand.DoCommand(String system) in C:\---\SystemCommand.cs:line 27
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at System.CommandLine.Invocation.ModelBindingCommandHandler.InvokeAsync(InvocationContext context)
   at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseErrorReporting>b__19_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass14_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseVersionOption>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass21_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__20_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseDirective>b__18_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseDebugDirective>b__10_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__9_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass12_0.<<UseExceptionHandler>b__0>d.MoveNext()

Adding a new List prompt

Hey @shibayan,

I had a idea to build a List form input that would take in values and append them to an existing list. For example:

What would you like to add to your grocery list? : Banana

  • Apple
  • Orange

Pressing ENTER would append Banana to the end of this list and ask again.

What would you like to add to your grocery list? :

  • Apple
  • Orange
  • Banana

If the user presses ENTER without any value, the prompt would end.

Please let me know what you think and if you like it, I would like to try working on this.

Add better Null Reference Type support

Adopt NRT as a required condition for the value. I need to use NullabilityInfoContext which will probably be added in NET 6.
https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-7/#getting-top-level-nullability-information

Proposal

// Value is required
var intValue = Prompt.Input<int>("Integer value");
var strValue = Prompt.Input<string>("String value");

// Value is optional
var optionalIntValue = Prompt.Input<int?>("Optional integer value");
var optionalStrValue = Prompt.Input<string?>("Optional string value");

Pasting U+30FB with InputForm does not work.

When pasting U+30FB ( only one character ) with InputForm, it works well. But it doesn't work with more than two characters( U+30FB and other characters ).

  • Sharpromt: 2.3.2
  • Framework: .NET5
  • OS: Windows11 (Mac(M1), Ubuntu(18.04) works well.)

Thanks.
P.S. I always appreciate Sharpromt.

Prompts should be cancellable

At the moment, it is impossible to cancel an input request. It would be nice if a CancellationToken could be passed to the input functions to cancel the input request. I imagine the input function would simply throw when it is cancelled.

Allow ConsoleDriver to be customizable

The current DefaultConsoleDriver implementation is internal and makes it impossible to override any of the behaviors of the DefaultConsoleDriver class to fit my needs. Some suggestions that I have would be:

  • Make the IConsoleDriver interface and DefaultConsoleDriver class public so that subclasses could inherit and override the method's behaviors.
  • Plumb through a way to override the ConsoleDriver property , so that we could specify our own custom implementation of a ConsoleDriver

I believe that these changes builds on such a neat tool and would make the tool more fun and flexible for users to play around with.

Revamp the input validation mechanism

  • Unify the behavior of Nullable types
  • Bringing the Validator implementation closer to the standard (same direction as data annotations)
  • Indicator display of validation results #76

AutoForms feature

  • Feature to automatically create forms on a model-based
  • Declarative validation with DataAnnotations
  • Specify the form type with the DataType attribute

Update README.md

  • Build status badge
  • NuGet information (PackageId, latest version)
  • Getting Started
  • Example project
  • License

Add Test suite

  • Run test case on Azure Pipelines
    • Windows / Ubuntu / macOS
  • Emulate input key and validate output

Support for better prompt cancellation

I can't think of a use case where interactive console input would require a timeout. In most cases, if you can handle the behavior after sending Ctrl+C, you should be fine.

I haven't checked if it is possible to implement it, but it looks like the following code would be good.

Proposal

try
{
    // Needs `throwExceptionOnCancel` set `true`
    var name = Prompt.Input<string>("What's your name?", throwExceptionOnCancel: true);

    Console.WriteLine($"Hello, {name}!");
}
catch (PromptCancelledException ex)
{
    // handling
}

Additional context

Navigating to previous prompts

I currently have a loop that asks a series of prompts. I want to have a way to return to a previous prompt even when answering the current prompt in case a user realizes that one of the past responses was incorrect. How would I go about doing this? Does Sharprompt support historical navigation?

Weird behavior on Windows terminals

The new interface for the prompt seems to broke my terminals, especially the one that doesn't have a unicode support.
It produces this weird character on the beginning of the line after I type the answer, or submitting the answer.
image

It also occurs on Powershell 7
image

The code was a simple yes/no input and the usual input

using Sharprompt;
using System;

namespace ConsolePlayground
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var confirmOverwrite = Prompt.Confirm("Existing configuration already exists! Overwrite file?", false);
            if (!confirmOverwrite) return;
            var Testvar1 = Prompt.Input<string>("Input a string");
            var Testvar2 = Prompt.Password("Input another string");
        }
    }
}

Also, here's the video demo about the issue.

output.mp4

The required validator always return "Value is required" if the input type is not a string

The Validators.Required() can be added to input on a type different than string.

The Required validators only check string attributes and return Value is required if the type is different than a string, even if the value is correct.

image

Solution:
Update the Required validator by adding a check on a type different than string.

public static Func<object, ValidationResult> Required()
{
return input =>
{
if (input is string strValue && !string.IsNullOrEmpty(strValue))
{
return ValidationResult.Success;
}
return new ValidationResult("Value is required");
};

Reduce flickering during console rendering

Flickering on Ubuntu (WSL 2) + Windows Terminal

  • Improved latency of text rendering process
  • Improved console line erasure process
  • Review and improve the rendering order
  • Redraw only the parts that have been changed

Prompt.MultiSelect does not allow 0 selected items

It' is possible to call Prompt.MultiSelect(message, list, min: 0), but this does not actually allow zero items to be selected. It will fail with the message "A minimum selection of 0 items is required".

Default values for string Input prompt are not passed to validators

If a defaultValue is specified in a Prompt.Input<string> call that also specifies validators, pressing Enter on the prompt sends an empty string to the validators, not the default value. For example:

var userName = Sharprompt.Prompt.Input<string>("Please enter a name", "default", validators: new[] { Sharprompt.Validations.Validators.Required()});

will fail unless providing a non-default value, since an empty string is passed to validators, rather than the default value specified by defaultValue.


I've created an oversimplified repro in this repo

Enum ordering

Please provide for select enum ordering
For examle using [Display(Name = "End",Order =1)]

Support for cancellable prompts, two new controls and many enhancement

This fork (https://github.com/FRACerqueira/Sharprompt) at master
adds support for cancellable prompts, two new controls and many enhancement

Resume:

  • Support Cancelation Token for all promts (enhancement)
  • Custom Prompter custom messages for all promts (enhancement)
  • Revised behavior/navigator of all prompts with Interative result (enhancement)
  • Prompt List with support to remove item and paging (enhancement)
  • Prompt Anykey (new - Simple any key-press)
  • Prompt FileBrowser (new - Browser file/folder)

Preview prompts :

Prompt_FileBrowser

Prompt_FolderBrowser

Prompt_Input

Prompt_List

Prompt_MultSelect

Prompt_Password

Prompt_Select

Prompt_Confirm

Prompt_EnumMultSelect

Prompt_EnumSelect

Exception in Prompt.Select<MyEnum> if DispalyName.Order is not set

With #82 the following regression was introduced:

When using Prompt.Select<MyEnum>("My Prompt"). I.e. with the automatic choice generation from enums.
When the Enum fields are decorated with Display(Name="choice display text") but the Order parameter is not specified, the code will fail with:

The Order property has not been set. Use the GetOrder method to get the value

Apparently one is not supposed to use displayAttribute.Order if the Order field has not been explicitly set.
referencesource

This should be an easy fix in EnumValue.cs

v2.0 Release checklist

  • ReadLine multi-byte support (#67)
  • Unicode support (#62)
  • Ctrl+C Interrupts support (#66)
  • Update documents
    • Unicode support (#65)
    • Enum support
    • Breaking changes
  • Bug fixes (#68)

UX enh: select single filtered item

It would be nice if when the select list of items has been filtered down to a single entry, ENTER commits its value even if the user hasn't "selected" it using the arrow key.

For example, given this list:

1. Red
2. Green
3. Blue

It feels natural to type 1 (only Red remains) and Enter but that doesn't work.
Currently you need to do 1, Down, Enter.

Clean up properly when application exits

At the moment if Ctrl-C is hit in the middle of an input, the terminal is left in a strange state (e.g. the cursor is no longer visible).

Would it be possible to clean up properly when the application exits?

Select with enums does not support default value

An error is thrown if you use an enumeration type as the generic argument and provide a default value for the Prompt.Select() method.

Program.cs

using Sharprompt;
using System;
using System.ComponentModel.DataAnnotations;

namespace SharpromptSelectEnumBug
{
    class Program
    {
        static void Main(string[] args)
        {
            var value = Prompt.Select<MyEnum>("Select enum value", defaultValue: MyEnum.Bar);
            Console.WriteLine($"You selected {value}");
        }
    }

    public enum MyEnum
    {
        Foo,
        Bar,
        Baz
    }
}

Project.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Sharprompt" Version="2.1.1" />
  </ItemGroup>

</Project>

When executing the Prompt.Select method, the following exception is thrown:

System.InvalidCastException
Unable to cast object of type 'SharpromptSelectEnumBug.MyEnum' to type 'Sharprompt.Internal.EnumValue`1[SharpromptSelectEnumBug.MyEnum]'.
  Source=System.Private.CoreLib
  StackTrace:
   at System.Runtime.CompilerServices.CastHelpers.ChkCastAny(Void* toTypeHnd, Object obj)
   at Sharprompt.Internal.Selector`1.InitializeDefaults(Object defaultValue)
   at Sharprompt.Internal.Selector`1..ctor(IEnumerable`1 items, Nullable`1 pageSize, Object defaultValue, Func`2 valueSelector)
   at Sharprompt.Forms.Select`1..ctor(String message, IEnumerable`1 items, Nullable`1 pageSize, Object defaultValue, Func`2 valueSelector)
   at Sharprompt.Prompt.Select[T](String message, Nullable`1 pageSize, Nullable`1 defaultValue)
   at SharpromptSelectEnumBug.Program.Main(String[] args) in C:\.......\Program.cs:line 14

This does work correctly for simple string-based entries. For example with this code:

var city = Prompt.Select("Select your city", new[] { "Seattle", "London", "Tokyo" }, defaultValue: "London");

"London" will correctly be selected by default when showing the prompt.

Allow pagination to be customizable

For Select and MultiSelect prompt.

Proposal

Prompt.Select<MyEnum>(options =>
{
    options.Message = "Select a item?";
    options.PaginationCallback = (total, current, page) => $"({total} items, {current}/{page} pages)";
});

or

Prompt.Select<MyEnum>(options =>
{
    options.Message = "Select a item?";
    options.PaginationTemplate ="({0} items, {1}/{2} pages)";
});

Add support for as-you-type validation

For the MinLength and MaxLength validators, it would be useful to have the possibility of seeing an indication of how many of the allowed or required characters you have used up, for example in parentheses after the message: Type new password (3/8): ***
The indicator could be colored based on whether the current input is valid or not.

For the RegularExpression validator, it may be harder to show a usable indicator, but it could still say โœ…/valid or โŒ/invalid.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.