Esempio n. 1
0
        public static List <Suggestion> GetCompletions(string sanitizedText, API.Shell shell, int cursorPos)
        {
            var INVOKE_IN_DIR = "." + Path.DirectorySeparatorChar;

            var executableSanitizedInput = sanitizedText.Remove(0, INVOKE_IN_DIR.Length);

            var basePath        = shell.WorkingDirectory;
            var startOfFilename = executableSanitizedInput;

            var lastDir = executableSanitizedInput.LastIndexOf(Path.DirectorySeparatorChar);

            if (lastDir != -1)
            {
                basePath        = Path.Combine(basePath, executableSanitizedInput.Substring(0, lastDir));
                startOfFilename = executableSanitizedInput.Remove(0, lastDir + 1);
            }

            return(GetFilesAndFolders(basePath)
                   .Where(x => x.StartsWith(startOfFilename))
                   // TODO we should check if the executable bit is set here
                   .Distinct()
                   .Select(x => new Suggestion()
            {
                Index = cursorPos, CompletionText = x.Remove(0, startOfFilename.Length), FullText = x
            })
                   .ToList());
        }
        internal static string ConvertToAbsolute(string dir, API.Shell shell)
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                dir = dir.Replace("~", shell.HomeDirectory);

                if (!dir.StartsWith(Path.DirectorySeparatorChar))
                {
                    dir = Path.Combine(shell.WorkingDirectory, dir);
                }

                return(Path.GetFullPath(dir));
            }
            else
            {
                return(Path.GetFullPath(dir.Replace("~", shell.HomeDirectory), shell.WorkingDirectory));
            }
        }
        private static List <Suggestion> GetMatchingFilesOrDirectories(string sanitizedText, API.Shell shell, int cursorPos)
        {
            // 'command arg1 arg2 /home/asdad/d<TAB>'

            var fsStart          = sanitizedText.LastIndexOf(' ', sanitizedText.Length - 1); // todo change to regex and match multiple chars?
            var startOfDirOrFile = sanitizedText.Remove(0, fsStart == -1 ? 0 : fsStart + 1); // +1 for the space

            var fullPath = ConvertToAbsolute(startOfDirOrFile, shell);

            var directoryName = Path.GetDirectoryName(fullPath);

            if (directoryName == null)
            {
                directoryName = Dotnet.Shell.API.Shell.BasePath;
            }

            var toMatch = Path.GetFileName(fullPath);

            // /ho<TAB>
            // ./home<TAB>
            // ../<TAB>
            // bob/asdads<TAB>

            // suggest a file or directory
            List <string> items = new();

            try
            {
                items.AddRange(Directory.GetFiles(directoryName).Select(x => Path.GetFileName(x)));
            }
            catch
            {
            }

            try
            {
                items.AddRange(Directory.GetDirectories(directoryName).Select(x => Path.GetFileName(x) + Path.DirectorySeparatorChar));
            }
            catch
            {
            }

            return(items
                   .Where(x => string.IsNullOrWhiteSpace(toMatch) || x.StartsWith(toMatch))
                   .Select(x => x.Remove(0, toMatch.Length))
                   .Distinct()
                   .Select(x => new Suggestion()
            {
                Index = cursorPos, CompletionText = x, FullText = toMatch + x
            }).ToList());
        }
        public static async Task <List <Suggestion> > GetCompletionsAsync(string sanitizedText, API.Shell shell, int cursorPos, Task <string[]> commandsInPath)
        {
            // if our cursor position is before a space then we are in command completion mode
            // otherwise we will complete with a filename

            // need to decide if we are going to look for a command, or a file
            var  spacePos       = sanitizedText.IndexOf(' ');
            bool suggestCommand = spacePos == -1 || spacePos >= cursorPos;

            if (suggestCommand)
            {
#pragma warning disable VSTHRD003 // Avoid awaiting foreign Tasks
                var matchedEndings = (await commandsInPath).Where(x => x.StartsWith(sanitizedText)).Select(x => x.Remove(0, sanitizedText.Length)).Distinct().ToList();
#pragma warning restore VSTHRD003 // Avoid awaiting foreign Tasks

                return(matchedEndings
                       .ConvertAll(x => new Suggestion()
                {
                    CompletionText = x, Index = cursorPos, FullText = sanitizedText + x
                })
                       .Union(GetMatchingFilesOrDirectories(sanitizedText, shell, cursorPos))
                       .Distinct()
                       .ToList());
            }
            else
            {
                return(GetMatchingFilesOrDirectories(sanitizedText, shell, cursorPos));
            }
        }
Esempio n. 5
0
        public static List <Suggestion> GetCompletions(string sanitizedText, API.Shell shell, int cursorPos)
        {
            const string CD_MATCH         = "cd";
            var          cdSanitizedInput = sanitizedText.Remove(0, CD_MATCH.Length).TrimStart();

            bool isAbsolutePath = cdSanitizedInput.StartsWith(Path.DirectorySeparatorChar) || RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && cdSanitizedInput.Length >= 3 && cdSanitizedInput[1] == ':';

            if ((isAbsolutePath && Directory.Exists(cdSanitizedInput) && !cdSanitizedInput.EndsWith(Path.DirectorySeparatorChar)) ||
                (Directory.Exists(Path.Combine(shell.WorkingDirectory, cdSanitizedInput)) && !cdSanitizedInput.EndsWith(Path.DirectorySeparatorChar)))
            {
                // Directories must end with a slash
                return(new List <Suggestion>()
                {
                    new Suggestion()
                    {
                        Index = cursorPos, CompletionText = Path.DirectorySeparatorChar.ToString(), FullText = cdSanitizedInput + Path.DirectorySeparatorChar
                    }
                });
            }

            if (string.IsNullOrWhiteSpace(cdSanitizedInput) || (isAbsolutePath && Directory.Exists(cdSanitizedInput)))
            {
                return
                    (TryGetDirectories(isAbsolutePath ? cdSanitizedInput : shell.WorkingDirectory)
                     .Select(x => new Suggestion()
                {
                    Index = cursorPos, CompletionText = Path.GetFileName(x) + Path.DirectorySeparatorChar, FullText = Path.GetFileName(x) + Path.DirectorySeparatorChar
                })
                     .ToList());
            }
            else if (isAbsolutePath) // absolute paths
            {
                return
                    (TryGetDirectories(Path.GetDirectoryName(cdSanitizedInput))
                     .Where(x => x.StartsWith(cdSanitizedInput))
                     .Select(x => x.Remove(0, cdSanitizedInput.Length))
                     .Distinct()
                     .Select(x => new Suggestion()
                {
                    Index = cursorPos, CompletionText = x + Path.DirectorySeparatorChar, FullText = cdSanitizedInput + x + Path.DirectorySeparatorChar
                })
                     .ToList());
            }
            else if (cdSanitizedInput.Contains(Path.DirectorySeparatorChar)) // sub directories based on CWD
            {
                var dirName = Path.GetFileName(cdSanitizedInput);

                return
                    (TryGetDirectories(Path.Combine(shell.WorkingDirectory, Path.GetDirectoryName(cdSanitizedInput)))
                     .Select(x => Path.GetFileName(x))
                     .Where(x => x.StartsWith(dirName))
                     .Select(x => x.Remove(0, dirName.Length))
                     .Distinct()
                     .Select(x => new Suggestion()
                {
                    Index = cursorPos, CompletionText = x + Path.DirectorySeparatorChar, FullText = cdSanitizedInput + x + Path.DirectorySeparatorChar
                })
                     .ToList());
            }
            else // based from working dir
            {
                return(TryGetDirectories(shell.WorkingDirectory)
                       .Select(x => Path.GetFileName(x))
                       .Where(x => x.StartsWith(cdSanitizedInput))
                       .Select(x => x.Remove(0, cdSanitizedInput.Length))
                       .Distinct()
                       .Select(x => new Suggestion()
                {
                    Index = cursorPos, CompletionText = x + Path.DirectorySeparatorChar, FullText = cdSanitizedInput + x + Path.DirectorySeparatorChar
                })
                       .ToList());
            }
        }
Esempio n. 6
0
 public CmdSuggestions(API.Shell shell, Task <string[]> commandsInPath)
 {
     this.shell          = shell;
     this.commandsInPath = commandsInPath;
 }
Esempio n. 7
0
 internal CmdSuggestions(API.Shell shell)
 {
     this.shell          = shell;
     this.commandsInPath = Task.FromResult(Array.Empty <string>());
 }