Пример #1
0
        internal static (string cmd, List <string> args) Run(string yourPrompt, BasePromptApp yourApp)
        {
            // for result
            var cmd  = "";
            var args = new List <string>();

            // for history
            var inputHistoryPosition = inputHistory.Count;

            // for auto completer
            var argOrder       = 0;
            var completeTarget = "";
            IEnumerator <string> matchedList = null;

            // for input
            Console.ForegroundColor = PromptActive.Theme.PromptColor;
            Console.Write($"{Environment.NewLine}{yourPrompt} ");
            var input         = new List <char>();
            var inputPosition = 0;

            CurLeft = Console.CursorLeft;
            CurTop  = Console.CursorTop;
            int startLeft = CurLeft;

            ReWrite(startLeft, input);
            Console.SetCursorPosition(startLeft, CurTop);

            var key       = new ConsoleKeyInfo();
            var isRunning = true;

            while (isRunning)
            {
                key = Console.ReadKey(true);
                switch (key.Key)
                {
                case ConsoleKey.LeftArrow:
                    if (CurLeft - 1 >= startLeft)
                    {
                        inputPosition--;
                        CurLeft--;
                        Console.SetCursorPosition(CurLeft, CurTop);
                    }
                    break;

                case ConsoleKey.RightArrow:
                    if (inputPosition + 1 <= input.Count)
                    {
                        inputPosition++;
                        CurLeft++;
                        Console.SetCursorPosition(CurLeft, CurTop);
                    }
                    break;

                case ConsoleKey.Backspace:
                    if (CurLeft - 1 >= startLeft)
                    {
                        inputPosition--;
                        CurLeft--;
                        input.RemoveAt(inputPosition);

                        ReWrite(startLeft, input);
                    }
                    break;

                case ConsoleKey.Delete:
                    if (CurLeft - startLeft < input.Count)
                    {
                        input.RemoveAt(CurLeft - startLeft);

                        ReWrite(startLeft, input);
                    }
                    break;

                case ConsoleKey.Home:
                {
                    inputPosition = 0;
                    CurLeft       = startLeft;

                    Console.SetCursorPosition(CurLeft, CurTop);
                }
                break;

                case ConsoleKey.End:
                {
                    inputPosition = input.Count;
                    CurLeft       = startLeft + inputPosition;

                    Console.SetCursorPosition(CurLeft, CurTop);
                }
                break;

                case ConsoleKey.UpArrow:
                    if (inputHistory.Count > 0 && inputHistoryPosition - 1 >= 0)
                    {
                        // history
                        inputHistoryPosition--;
                        input         = inputHistory[inputHistoryPosition].ToList();
                        inputPosition = input.Count;
                        CurLeft       = startLeft + inputPosition;

                        ReWrite(startLeft, input);
                    }
                    break;

                case ConsoleKey.DownArrow:
                    if (inputHistoryPosition + 1 < inputHistory.Count)
                    {
                        // history
                        inputHistoryPosition++;
                        input         = inputHistory[inputHistoryPosition].ToList();
                        inputPosition = input.Count;
                        CurLeft       = startLeft + inputPosition;

                        ReWrite(startLeft, input);
                    }
                    else if (inputHistoryPosition + 1 == inputHistory.Count)
                    {
                        inputHistoryPosition = inputHistory.Count;
                        input.Clear();
                        inputPosition = input.Count;
                        CurLeft       = startLeft + inputPosition;

                        ReWrite(startLeft, input);
                    }
                    break;

                case ConsoleKey.Tab:
                {
                    args     = string.Concat(input).TrimStart().Split(' ').ToList();
                    argOrder = args.Count - 1;
                    cmd      = argOrder == 0 ? "" : args[0];

                    // autocomplete
                    if (lastKey.Key != ConsoleKey.Tab)
                    {
                        if (yourApp.AutoCompleteList.ContainsKey(cmd) &&
                            yourApp.AutoCompleteList[cmd].ContainsKey(argOrder))
                        {
                            var thisCompleteList = yourApp.AutoCompleteList[cmd][argOrder];
                            completeTarget = args[argOrder];
                            matchedList    = GetMatch(thisCompleteList, completeTarget).GetEnumerator();
                        }
                        else
                        {
                            matchedList = null;
                        }
                    }

                    var before = "";
                    for (int i = 0; i < args.Count - 1; i++)
                    {
                        before = $"{before}{args[i]} ";
                    }

                    if (matchedList != null)
                    {
                        matchedList.MoveNext();
                        while (string.IsNullOrEmpty(matchedList.Current))
                        {
                            matchedList.MoveNext();
                        }
                        input = $"{before}{matchedList.Current}".ToCharArray().ToList();
                    }

                    inputPosition = input.Count;
                    CurLeft       = startLeft + inputPosition;

                    ReWrite(startLeft, input);
                }
                break;

                case ConsoleKey.Escape:
                {
                    if (lastKey.Key == ConsoleKey.Escape)
                    {
                        throw new InvalidOperationException("Escape");
                    }
                    else
                    {
                        throw new OperationCanceledException("Escape");
                    }
                }

                case ConsoleKey.Enter:
                {
                    // input insert
                    args     = string.Concat(input).Trim().Split(' ').ToList();
                    argOrder = args.Count - 1;
                    cmd      = args[0];

                    if (!string.IsNullOrWhiteSpace(cmd))
                    {
                        inputHistory.Add(input);
                    }
                    isRunning = false;
                }
                break;

                case ConsoleKey.Spacebar:
                {
                    if (lastKey.Key != ConsoleKey.Spacebar)
                    {
                        // input insert
                        input.Insert(inputPosition++, key.KeyChar);
                        CurLeft++;

                        ReWrite(startLeft, input);
                    }
                    // show hint
                    args     = string.Concat(input).Trim().Split(' ').ToList();
                    argOrder = args.Count - 1;
                    cmd      = args[0];

                    if (argOrder == 0 && yourApp.HintList.ContainsKey(cmd))
                    {
                        var hint = yourApp.HintList[cmd];
                        if (!string.IsNullOrEmpty(hint))
                        {
                            ReWrite(startLeft, input);
                            Console.ForegroundColor = PromptActive.Theme.HintColor;
                            Console.Write(hint);
                            Console.SetCursorPosition(CurLeft, CurTop);
                        }
                    }
                }
                break;

                default:
                {
                    // input insert
                    input.Insert(inputPosition++, key.KeyChar);
                    CurLeft++;

                    ReWrite(startLeft, input);
                }
                break;
                }
                // maxbuffer check
                if (startLeft + input.Count >= Console.BufferWidth)
                {
                    throw new OverflowException("Console");
                }

                lastKey = key;
            }
            return(cmd, args);
        }
Пример #2
0
        //private static void Setup<T>(T app) where T : BasePromptApp
        private static void Setup(BasePromptApp yourApp)
        {
            // 1) Create CommandList
            var kvm = yourApp.GetType().GetMethods()
                      ?.Where(x => x.GetCustomAttribute <PromptCommandAttribute>() != null)
                      ?.Select(x => new KeyValuePair <string, MethodInfo>(x.Name, x));

            if (kvm != null)
            {
                foreach (var kv in kvm)
                {
                    yourApp.AutoCompleteList[""][0].Add(kv.Key);
                    yourApp.CommandList.Add(kv.Key, kv.Value);
                }
            }
            // 2) Create HintList
            foreach (var item in yourApp.CommandList)
            {
                // 2-1) Description list
                var description = item.Value.GetCustomAttribute <DescriptionAttribute>()?.Description;
                description = string.IsNullOrEmpty(description) ? "Not defined." : description;
                yourApp.DescriptionList.Add(item.Key, description);
                // 2-2) Custim hint available
                var customhint = item.Value.GetCustomAttribute <CustomHintAttribute>()?.Hint;
                if (!string.IsNullOrEmpty(customhint))
                {
                    yourApp.HintList.Add(item.Key, customhint);
                    continue;
                }
                // 2-2) Hint list
                var args = item.Value.GetParameters();
                var sb   = "";
                if (args != null)
                {
                    for (int i = 0; i < args.Count(); i++)
                    {
                        var type   = args[i].ParameterType;
                        var type_s = "";
                        if (type.IsEnum)
                        {
                            // enum
                            // Autocomplete add
                            var enumNames = type.GetEnumNames().ToList();
                            if (!yourApp.AutoCompleteList.ContainsKey(item.Key))
                            {
                                yourApp.AutoCompleteList.Add(item.Key, new Dictionary <int, List <string> >());
                            }
                            yourApp.AutoCompleteList[item.Key][i + 1] = enumNames;

                            foreach (var e in enumNames)
                            {
                                type_s = $"{type_s}|{e}";
                            }
                            type_s = new string(type_s.Skip(1).ToArray());
                        }
                        else
                        {
                            type_s = type.Name;
                        }

                        if (args[i].IsOptional)
                        {
                            // optional
                            sb = $"{sb}[{args[i].Name}<{type_s}>] ";
                        }
                        else
                        {
                            sb = $"{sb}{args[i].Name}<{type_s}> ";
                        }
                    }
                }
                yourApp.HintList.Add(item.Key, sb);
            }
            // 3) Create Autocomplete list
            var kvp = yourApp.GetType().GetProperties();

            foreach (var item in kvp)
            {
                var ps = item.GetCustomAttributes <AutocompleteAttribute>();
                foreach (var p in ps)
                {
                    if (!yourApp.AutoCompleteList.ContainsKey(p.Function))
                    {
                        yourApp.AutoCompleteList.Add(p.Function, new Dictionary <int, List <string> >());
                    }
                    yourApp.AutoCompleteList[p.Function][p.Order] = item.GetValue(yourApp) as List <string>;
                }
            }
        }