AutocompleteFilepathContext.cs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System.Text;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.IO.Abstractions;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. namespace Terminal.Gui {
  9. internal class AutocompleteFilepathContext : AutocompleteContext {
  10. public FileDialogState State { get; set; }
  11. public AutocompleteFilepathContext (string currentLine, int cursorPosition, FileDialogState state)
  12. : base (currentLine.EnumerateRunes ().ToList (), cursorPosition)
  13. {
  14. this.State = state;
  15. }
  16. }
  17. internal class FilepathSuggestionGenerator : ISuggestionGenerator {
  18. FileDialogState state;
  19. public IEnumerable<Suggestion> GenerateSuggestions (AutocompleteContext context)
  20. {
  21. if (context is AutocompleteFilepathContext fileState) {
  22. this.state = fileState.State;
  23. }
  24. if (state == null) {
  25. return Enumerable.Empty<Suggestion> ();
  26. }
  27. var path = StringExtensions.ToString (context.CurrentLine);
  28. var last = path.LastIndexOfAny (FileDialog.Separators);
  29. if (string.IsNullOrWhiteSpace (path) || !Path.IsPathRooted (path)) {
  30. return Enumerable.Empty<Suggestion> ();
  31. }
  32. var term = path.Substring (last + 1);
  33. // If path is /tmp/ then don't just list everything in it
  34. if (string.IsNullOrWhiteSpace (term)) {
  35. return Enumerable.Empty<Suggestion> ();
  36. }
  37. if (term.Equals (state?.Directory?.Name)) {
  38. // Clear suggestions
  39. return Enumerable.Empty<Suggestion> ();
  40. }
  41. bool isWindows = RuntimeInformation.IsOSPlatform (OSPlatform.Windows);
  42. var suggestions = state.Children.Where (d => !d.IsParent).Select (
  43. e => e.FileSystemInfo is IDirectoryInfo d
  44. ? d.Name + System.IO.Path.DirectorySeparatorChar
  45. : e.FileSystemInfo.Name)
  46. .ToArray ();
  47. var validSuggestions = suggestions
  48. .Where (s => s.StartsWith (term, isWindows ?
  49. StringComparison.InvariantCultureIgnoreCase :
  50. StringComparison.InvariantCulture))
  51. .OrderBy (m => m.Length)
  52. .ToArray ();
  53. // nothing to suggest
  54. if (validSuggestions.Length == 0 || validSuggestions [0].Length == term.Length) {
  55. return Enumerable.Empty<Suggestion> ();
  56. }
  57. return validSuggestions.Select (
  58. f => new Suggestion (term.Length, f, f)).ToList ();
  59. }
  60. public bool IsWordChar (Rune rune)
  61. {
  62. if (rune.Value == '\n') {
  63. return false;
  64. }
  65. return true;
  66. }
  67. }
  68. }