dired.sl 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % DIRED.SL - Directory Editor Subsystem
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 16 July 1982
  8. % Revised: 16 February 1983
  9. %
  10. % This file implements a directory editor subsystem.
  11. %
  12. % 16-Feb-83 Alan Snyder
  13. % Declare -> Declare-Flavor.
  14. % Fix cleanup method to NIL out the buffer variable to allow the buffer object
  15. % to be garbage collected.
  16. % 11-Feb-83 Alan Snyder
  17. % Fix bug in previous change.
  18. % 8-Feb-83 Alan Snyder
  19. % Enlarge width of size field in display.
  20. % 4-Feb-83 Alan Snyder
  21. % Rewritten to use new browser support.
  22. %
  23. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  24. (BothTimes (load extended-char fast-strings))
  25. (load directory stringx)
  26. % External variables:
  27. (fluid '(
  28. nmode-current-buffer
  29. nmode-current-window
  30. nmode-terminal
  31. nmode-command-argument
  32. nmode-command-argument-given
  33. ))
  34. % Internal static variables:
  35. (fluid '(File-Browser-Mode File-Browser-Command-List))
  36. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  37. (setf File-Browser-Mode (nmode-define-mode "File-Browser" '(
  38. (nmode-define-commands File-Browser-Command-List)
  39. (nmode-establish-mode Read-Only-Text-Mode)
  40. )))
  41. (setf File-Browser-Command-List (list
  42. (cons (x-char ?) 'dired-help)
  43. (cons (x-char D) 'browser-delete-command)
  44. (cons (x-char E) 'browser-edit-command)
  45. (cons (x-char I) 'browser-ignore-command)
  46. (cons (x-char K) 'browser-kill-command)
  47. (cons (x-char N) 'browser-undo-filter-command)
  48. (cons (x-char Q) 'dired-exit)
  49. (cons (x-char R) 'dired-reverse-sort)
  50. (cons (x-char S) 'dired-sort)
  51. (cons (x-char U) 'browser-undelete-command)
  52. (cons (x-char V) 'browser-view-command)
  53. (cons (x-char X) 'dired-exit)
  54. (cons (x-char BACKSPACE) 'browser-undelete-backwards-command)
  55. (cons (x-char RUBOUT) 'browser-undelete-backwards-command)
  56. (cons (x-char SPACE) 'move-down-command)
  57. (cons (x-char control D) 'browser-delete-command)
  58. (cons (x-char control K) 'browser-kill-command)
  59. ))
  60. (de dired-command ()
  61. (let ((fn (=> nmode-current-buffer file-name))
  62. directory-name
  63. )
  64. (cond
  65. ((or (not fn) (>= nmode-command-argument 4))
  66. (setf directory-name (prompt-for-string "Edit Directory: " NIL))
  67. )
  68. (nmode-command-argument-given
  69. (setf directory-name (namestring (pathname-without-version fn)))
  70. )
  71. (t
  72. (setf directory-name (directory-namestring fn))
  73. ))
  74. (directory-editor directory-name)
  75. ))
  76. (de edit-directory-command ()
  77. (let* ((fn (=> nmode-current-buffer file-name))
  78. (directory-name
  79. (prompt-for-string
  80. "Edit Directory:"
  81. (and fn (directory-namestring fn))
  82. )))
  83. (directory-editor directory-name)
  84. ))
  85. (de directory-editor (directory-name)
  86. % Put up a directory editor subsystem, containing all files that match the
  87. % specified string. If the string specifies a directory, then all files in
  88. % that directory are used.
  89. (setf directory-name (fixup-directory-name directory-name))
  90. (write-prompt "Reading directory or directories...")
  91. (let ((items (dired-create-items (find-matching-files directory-name t))))
  92. (if (null items)
  93. (write-prompt (BldMsg "No files match: %w" directory-name))
  94. % ELSE
  95. (let* ((b (buffer-create "+FILES" File-Browser-Mode))
  96. (header-text (vector
  97. (string-concat "Directory List of " directory-name)
  98. ""
  99. ))
  100. )
  101. (=> b put 'directory-name directory-name)
  102. (create-browser b NIL header-text items #'dired-filename-sorter)
  103. (browser-enter b)
  104. (dired-help)
  105. ))))
  106. (de dired-create-items (file-list)
  107. % Accepts a list containing one element per file, where each element is
  108. % a list. Returns a list of file-browser-items.
  109. (when file-list
  110. (let* ((display-width (=> nmode-current-window width))
  111. (names (for (in f file-list)
  112. (collect (fixup-file-name (nth f 1)))
  113. ))
  114. (prefix (trim-filename-to-prefix
  115. (strings-largest-common-prefix names)))
  116. (prefix-length (string-length prefix))
  117. )
  118. (for (in f file-list)
  119. (collect
  120. (create-file-browser-item
  121. display-width
  122. (nth f 1) % full-name
  123. (string-rest (fixup-file-name (nth f 1)) prefix-length) % nice-name
  124. (nth f 2) % deleted?
  125. (nth f 3) % size
  126. (nth f 4) % write-date
  127. (nth f 5) % read-date
  128. ))))))
  129. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  130. % DIRED command procedures:
  131. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. (de dired-exit ()
  133. (let ((actions (dired-determine-actions nmode-current-buffer)))
  134. (if (and (null (first actions)) (null (second actions)))
  135. (browser-exit-command)
  136. % else
  137. (let ((command (dired-present-actions actions)))
  138. (cond
  139. ((eq command 'exit)
  140. (browser-exit-command)
  141. )
  142. ((eq command t)
  143. (dired-perform-actions actions)
  144. (browser-exit-command)
  145. )
  146. ))
  147. )))
  148. (de dired-help ()
  149. (write-message
  150. "View Edit Un/Delete Kill-now Ignore uN-ignore Sort Reverse-sort Quit"
  151. ))
  152. (de dired-reverse-sort ()
  153. (nmode-set-immediate-prompt "Reverse Sort by ")
  154. (dired-reverse-sort-dispatch)
  155. )
  156. (de dired-reverse-sort-dispatch ()
  157. (selectq (char-upcase (input-base-character))
  158. (#/F (browser-sort "Reverse Sort by Filename" 'dired-filename-reverser))
  159. (#/S (browser-sort "Reverse Sort by Size" 'dired-size-reverser))
  160. (#/W (browser-sort "Reverse Sort by Write date" 'dired-write-reverser))
  161. (#/R (browser-sort "Reverse Sort by Read date" 'dired-read-reverser))
  162. (#/?
  163. (nmode-set-immediate-prompt
  164. "Reverse Sort by (Filename, Size, Read date, Write date) ")
  165. (dired-reverse-sort-dispatch)
  166. )
  167. (t (write-prompt "") (Ding))
  168. ))
  169. (de dired-sort ()
  170. (nmode-set-immediate-prompt "Sort by ")
  171. (dired-sort-dispatch)
  172. )
  173. (de dired-sort-dispatch ()
  174. (selectq (char-upcase (input-base-character))
  175. (#/F (browser-sort "Sort by Filename" 'dired-filename-sorter))
  176. (#/S (browser-sort "Sort by Size" 'dired-size-sorter))
  177. (#/W (browser-sort "Sort by Write date" 'dired-write-sorter))
  178. (#/R (browser-sort "Sort by Read date" 'dired-read-sorter))
  179. (#/? (nmode-set-immediate-prompt
  180. "Sort by (Filename, Size, Read date, Write date) ")
  181. (dired-sort-dispatch)
  182. )
  183. (t (write-prompt "") (Ding))
  184. ))
  185. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  186. % DIRED Support Functions
  187. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  188. (de dired-determine-actions (b)
  189. % Return a list containing two lists: the first a list of file names to be
  190. % deleted, the second a list of file names to be undeleted.
  191. (let ((items (=> (=> b get 'browser) items))
  192. (delete-list ())
  193. (undelete-list ())
  194. )
  195. (for (in item items)
  196. (do (selectq (=> item action-wanted)
  197. (delete
  198. (setf delete-list (aconc delete-list (=> item full-name))))
  199. (undelete
  200. (setf undelete-list (aconc undelete-list (=> item full-name))))
  201. )))
  202. (list delete-list undelete-list)
  203. ))
  204. (de dired-present-actions (action-list)
  205. (let ((delete-list (first action-list))
  206. (undelete-list (second action-list))
  207. )
  208. (nmode-begin-typeout)
  209. (dired-present-list delete-list "These files to be deleted:")
  210. (dired-present-list undelete-list "These files to be undeleted:")
  211. (while t
  212. (printf "%nDo It (YES, N, X)? ")
  213. (selectq (get-upchar)
  214. (#/Y
  215. (if (= (get-upchar) #/E)
  216. (if (= (get-upchar) #/S)
  217. (exit T)
  218. (Ding) (next))
  219. (Ding) (next))
  220. )
  221. (#/N (exit NIL))
  222. (#/X (exit 'EXIT))
  223. (#/? (printf "%n YES-Do it, N-Return to DIRED, X-Exit from DIRED."))
  224. (t (Ding))
  225. ))))
  226. (de get-upchar ()
  227. % This function is used during "normal PSL" typeout, so we cannot use
  228. % the NMODE input functions, for they will refresh the NMODE windows.
  229. (let ((ch (X-Base (=> nmode-terminal get-character))))
  230. (when (AlphaP ch) (setf ch (char-upcase ch)) (WriteChar ch))
  231. ch))
  232. (de dired-present-list (list prompt)
  233. (when list
  234. (printf "%w%n" prompt)
  235. (for (in item list)
  236. (for count 0 (if (= count 1) 0 (+ count 1)))
  237. (do (printf "%w" (string-pad-right item 38))
  238. (if (= count 1) (printf "%n"))
  239. )
  240. )
  241. (printf "%n")
  242. ))
  243. (de dired-perform-actions (action-list)
  244. (let ((delete-list (first action-list))
  245. (undelete-list (second action-list))
  246. )
  247. (for (in file delete-list)
  248. (do (file-delete file)))
  249. (for (in file undelete-list)
  250. (do (file-undelete file)))
  251. ))
  252. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  253. % Sorting predicates:
  254. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  255. (declare-flavor file-browser-item f1 f2)
  256. (de dired-filename-sorter (f1 f2)
  257. (let ((n1 (=> f1 sort-name))
  258. (n2 (=> f2 sort-name))
  259. )
  260. (if (string= n1 n2)
  261. (<= (=> f1 version-number) (=> f2 version-number))
  262. (string<= n1 n2)
  263. )))
  264. (de dired-filename-reverser (f1 f2)
  265. (not (dired-filename-sorter f1 f2)))
  266. (de dired-size-sorter (f1 f2)
  267. (let ((size1 (=> f1 size))
  268. (size2 (=> f2 size))
  269. )
  270. (or (< size1 size2)
  271. (and (= size1 size2)
  272. (dired-filename-sorter f1 f2))
  273. )))
  274. (de dired-size-reverser (f1 f2)
  275. (let ((size1 (=> f1 size))
  276. (size2 (=> f2 size))
  277. )
  278. (or (> size1 size2)
  279. (and (= size1 size2)
  280. (dired-filename-sorter f1 f2))
  281. )))
  282. (de dired-write-sorter (f1 f2)
  283. (let ((d1 (=> f1 write-date))
  284. (d2 (=> f2 write-date))
  285. )
  286. (or (LessP d1 d2)
  287. (and (EqN d1 d2) (dired-filename-sorter f1 f2))
  288. )))
  289. (de dired-write-reverser (f1 f2)
  290. (let ((d1 (=> f1 write-date))
  291. (d2 (=> f2 write-date))
  292. )
  293. (or (GreaterP d1 d2)
  294. (and (EqN d1 d2) (dired-filename-sorter f1 f2))
  295. )))
  296. (de dired-read-sorter (f1 f2)
  297. (let ((d1 (=> f1 read-date))
  298. (d2 (=> f2 read-date))
  299. )
  300. (or (LessP d1 d2)
  301. (and (EqN d1 d2) (dired-filename-sorter f1 f2))
  302. )))
  303. (de dired-read-reverser (f1 f2)
  304. (let ((d1 (=> f1 read-date))
  305. (d2 (=> f2 read-date))
  306. )
  307. (or (GreaterP d1 d2)
  308. (and (EqN d1 d2) (dired-filename-sorter f1 f2))
  309. )))
  310. (undeclare-flavor f1 f2)
  311. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  312. % The file-browser-item flavor:
  313. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  314. (de create-file-browser-item (width full-name nice-name deleted? size
  315. write-date read-date)
  316. (make-instance 'file-browser-item
  317. 'full-name full-name
  318. 'nice-name nice-name
  319. 'deleted? deleted?
  320. 'size size
  321. 'write-date write-date
  322. 'read-date read-date
  323. 'display-width width
  324. ))
  325. (defflavor file-browser-item
  326. (
  327. display-text
  328. display-width
  329. full-name % full name of file
  330. nice-name % file name as displayed
  331. sort-name % name without version (for sorting purposes)
  332. version-number % version number (or 0) (for sorting purposes)
  333. size % size of file (arbitrary units)
  334. write-date % write date of file (or NIL)
  335. read-date % read date of file (or NIL)
  336. deleted? % file is actually deleted
  337. delete-flag % user wants file deleted
  338. (buffer NIL) % buffer created to view file
  339. )
  340. ()
  341. (gettable-instance-variables display-text full-name nice-name
  342. sort-name version-number
  343. size write-date read-date)
  344. (initable-instance-variables)
  345. )
  346. (defmethod (file-browser-item init) (init-plist)
  347. (let ((pn (pathname full-name)))
  348. (setf sort-name (namestring (pathname-without-version pn)))
  349. (setf version-number (pathname-version pn))
  350. (if (not (fixp version-number)) (setf version-number 0))
  351. )
  352. (setf display-text
  353. (string-concat
  354. (if deleted? "D " " ")
  355. (string-pad-right nice-name (- display-width 48))
  356. (string-pad-left (BldMsg "%d" size) 8)
  357. (string-pad-left (if write-date (file-date-to-string write-date) "") 19)
  358. (string-pad-left (if read-date (file-date-to-string read-date) "") 19)
  359. ))
  360. (setf delete-flag deleted?)
  361. )
  362. (defmethod (file-browser-item delete) ()
  363. (when (not delete-flag)
  364. (setf display-text (copystring display-text))
  365. (string-store display-text 0 #/D)
  366. (setf delete-flag T)
  367. ))
  368. (defmethod (file-browser-item undelete) ()
  369. (when delete-flag
  370. (setf display-text (copystring display-text))
  371. (string-store display-text 0 #\space)
  372. (setf delete-flag NIL)
  373. ))
  374. (defmethod (file-browser-item deleted?) ()
  375. delete-flag
  376. )
  377. (defmethod (file-browser-item kill) ()
  378. (nmode-delete-file full-name)
  379. )
  380. (defmethod (file-browser-item view-buffer) (x)
  381. (or (find-file-in-existing-buffer full-name)
  382. (setf buffer (find-file-in-buffer full-name T))
  383. ))
  384. (defmethod (file-browser-item cleanup) ()
  385. (when (and buffer (not (=> buffer modified?)))
  386. (if (buffer-is-selectable? buffer) (buffer-kill-and-detach buffer))
  387. (setf buffer NIL)
  388. ))
  389. (defmethod (file-browser-item apply-filter) (filter)
  390. (apply filter (list self))
  391. )
  392. (defmethod (file-browser-item action-wanted) ()
  393. % Return 'DELETE, 'UNDELETE, or NIL.
  394. (if (not (eq deleted? delete-flag)) % user wants some action taken
  395. (let ((file-status (file-deleted-status full-name)))
  396. (if file-status % File currently exists (otherwise, forget it)
  397. (let ((actually-deleted? (eq file-status 'deleted)))
  398. (if (not (eq delete-flag actually-deleted?))
  399. (if delete-flag 'DELETE 'UNDELETE)
  400. ))))))