complete.b 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. implement Complete;
  2. # Limbo translation by caerwyn of libcomplete on Plan 9
  3. # Subject to the Lucent Public License 1.02
  4. include "sys.m";
  5. sys: Sys;
  6. include "string.m";
  7. str: String;
  8. include "complete.m";
  9. include "readdir.m";
  10. readdir: Readdir;
  11. init()
  12. {
  13. sys = load Sys Sys->PATH;
  14. str = load String String->PATH;
  15. readdir = load Readdir Readdir->PATH;
  16. }
  17. longestprefixlength(a, b: string, n: int): int
  18. {
  19. for(i := 0; i < n; i++)
  20. if(a[i] != b[i])
  21. break;
  22. return i;
  23. }
  24. complete(dir, s: string): (ref Completion, string)
  25. {
  26. if(str->splitl(s, "/").t1 != nil)
  27. return (nil, "slash character in name argument to complete()");
  28. (da, n) := readdir->init(dir, Readdir->COMPACT);
  29. if(n < 0)
  30. return (nil, sys->sprint("%r"));
  31. if(n == 0)
  32. return (nil, nil);
  33. c := ref Completion(0, 0, nil, 0, nil);
  34. name := array[n] of string;
  35. mode := array[n] of int;
  36. length := len s;
  37. nfile := 0;
  38. minlen := 1000000;
  39. for(i := 0; i < n; i++)
  40. if(str->prefix(s,da[i].name)){
  41. name[nfile] = da[i].name;
  42. mode[nfile] = da[i].mode;
  43. if(minlen > len da[i].name)
  44. minlen = len da[i].name;
  45. nfile++;
  46. }
  47. if(nfile > 0){
  48. # report interesting results
  49. # trim length back to longest common initial string
  50. for(i = 1; i < nfile; i++)
  51. minlen = longestprefixlength(name[0], name[i], minlen);
  52. c.complete = (nfile == 1);
  53. c.advance = c.complete || (minlen > length);
  54. c.str = name[0][length:minlen];
  55. if(c.complete){
  56. if(mode[0]&Sys->DMDIR)
  57. c.str[minlen++ - length] = '/';
  58. else
  59. c.str[minlen++ - length] = ' ';
  60. }
  61. c.nmatch = nfile;
  62. }else{
  63. # no match: return all names
  64. for(i = 0; i < n; i++){
  65. name[i] = da[i].name;
  66. mode[i] = da[i].mode;
  67. }
  68. nfile = n;
  69. c.nmatch = 0;
  70. }
  71. c.filename = name;
  72. for(i = 0; i < nfile; i++)
  73. if(mode[i] & Sys->DMDIR)
  74. c.filename[i] += "/";
  75. return (c, nil);
  76. }