dired.sl 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. %
  2. % DIRED.SL - Directory Editor Subsystem for EMODE
  3. %
  4. % Author: Alan Snyder
  5. % Hewlett-Packard/CRC
  6. % Date: 16 July 1982
  7. %
  8. % This file implements a directory editor subsystem.
  9. %
  10. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  11. (BothTimes (load common strings directory gsort))
  12. (fluid '(CurrentLineIndex point WindowsBufferName BufferPreviousBuffer
  13. BufferAuxiliaryInfo CurrentBufferName DefaultMode buffers_file))
  14. (fluid '(DiredMode))
  15. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  16. % Macros
  17. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  18. (defmacro fi-full-name (fi) `(nth ,fi 1)) % string for file primitives
  19. (defmacro fi-deleted? (fi) `(nth ,fi 2)) % is file marked 'deleted'?
  20. (defmacro fi-size (fi) `(nth ,fi 3)) % "size" of file
  21. (defmacro fi-write-date (fi) `(nth ,fi 4)) % date/time file last written
  22. (defmacro fi-read-date (fi) `(nth ,fi 5)) % date/time file last read
  23. (defmacro fi-nice-name (fi) `(nth ,fi 6)) % string to show user
  24. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  25. (setf DiredMode
  26. '((SetKeys DiredDispatchList)
  27. (SetKeys ReadOnlyTextDispatchList)
  28. (SetKeys RlispDispatchList)
  29. (SetKeys BasicDispatchList)))
  30. (setf DiredDispatchList (list
  31. % These are the DIRED-specific commands.
  32. (cons (char ?) 'dired-help)
  33. (cons (char C) 'dired-srccom-file)
  34. (cons (char D) 'dired-delete-file)
  35. (cons (char E) 'dired-edit-file)
  36. (cons (char H) 'dired-automatic-delete)
  37. (cons (char K) 'dired-delete-file)
  38. (cons (char N) 'dired-next-hog)
  39. (cons (char Q) 'dired-exit)
  40. (cons (char R) 'dired-reverse-sort)
  41. (cons (char S) 'dired-sort)
  42. (cons (char U) 'dired-undelete)
  43. (cons (char X) 'dired-exit)
  44. (cons (char rubout) 'dired-reverse-undelete)
  45. (cons (char space) '$ForwardLine)
  46. (cons (char (cntrl D)) 'dired-delete-file)
  47. (cons (char (cntrl K)) 'dired-delete-file)
  48. ))
  49. (de dired-command ()
  50. (write-prompt "")
  51. (let* ((directory-name (prompt_for_string "Directory to edit: " buffers_file))
  52. file-list
  53. )
  54. (write-prompt "Reading directory(ies)...")
  55. (setf file-list (find-matching-files directory-name t))
  56. (if (null file-list)
  57. (write-prompt (BldMsg "No files match: %w" directory-name))
  58. % ELSE
  59. (dired-fixup-file-list file-list)
  60. (SelectBuffer (buffer-create '*Dired DiredMode))
  61. (setf BufferPreviousBuffer WindowsBufferName)
  62. (setf BufferAuxiliaryInfo file-list)
  63. (setf buffers_file directory-name)
  64. (load-dired-buffer BufferAuxiliaryInfo)
  65. (setf WindowsBufferName CurrentBufferName)
  66. (EstablishCurrentMode)
  67. (write-prompt "")
  68. )
  69. )
  70. )
  71. (de dired-fixup-file-list (file-list)
  72. % Adds to each element:
  73. % A cleaned-up file name for display and sorting purposes.
  74. (for (in file-info file-list)
  75. (do
  76. (aconc file-info (fixup-file-name (fi-full-name file-info)))
  77. ))
  78. (let ((prefix (if file-list (fi-nice-name (first file-list)) ""))
  79. prefix-length
  80. name)
  81. (for (in file-info file-list)
  82. (do (setf prefix
  83. (string-largest-common-prefix prefix (fi-nice-name file-info))
  84. ))
  85. )
  86. (setf prefix (trim-filename-to-prefix prefix))
  87. (setf prefix-length (+ 1 (size prefix)))
  88. (for (in file-info file-list)
  89. (do (setf name (fi-nice-name file-info))
  90. (setf (fi-nice-name file-info)
  91. (sub name
  92. prefix-length
  93. (- (size name) prefix-length))))
  94. ))
  95. )
  96. (de load-dired-buffer (file-list)
  97. ($DeleteBuffer)
  98. (for* (in file-info file-list)
  99. (do (insert_string (file-info-to-string file-info))
  100. ($CRLF))
  101. )
  102. (setf point 0)
  103. (SelectLine 0)
  104. )
  105. (de file-info-to-string (file-info)
  106. (let ((first-part (if (fi-deleted? file-info) "D " " "))
  107. (file-name (string-pad-right (fi-nice-name file-info) 34))
  108. (file-size (string-pad-left (BldMsg "%d" (fi-size file-info)) 4))
  109. (write-date (file-date-to-string (fi-write-date file-info)))
  110. (read-date (file-date-to-string (fi-read-date file-info))))
  111. (string-concat first-part file-name file-size " " write-date " " read-date)
  112. ))
  113. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  114. % DIRED command procedures:
  115. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  116. (de dired-exit ()
  117. (let* ((actions (dired-determine-actions BufferAuxiliaryInfo))
  118. command
  119. )
  120. (if (and (null (first actions)) (null (second actions)))
  121. (window-kill-buffer)
  122. % else
  123. (setf command (dired-present-actions actions))
  124. (cond
  125. ((eq command 'exit) (window-kill-buffer))
  126. ((eq command t) (dired-perform-actions actions) (window-kill-buffer))
  127. )
  128. )))
  129. (de dired-delete-file ()
  130. % Mark the current file as deleted.
  131. (cond ((current-line-empty) (Ding))
  132. (t
  133. (if (= (current-line-fetch 0) (char space))
  134. (current-line-store 0 (char D)))
  135. (move-to-next-line)
  136. )))
  137. (de dired-undelete ()
  138. % Unmark the current file.
  139. (cond ((current-line-empty) (Ding))
  140. (t
  141. (if (= (current-line-fetch 0) (char D))
  142. (current-line-store 0 (char space)))
  143. (move-to-next-line)
  144. )))
  145. (de dired-reverse-undelete ()
  146. % Unmark the previous file.
  147. (cond ((= CurrentLineIndex 0) (Ding))
  148. (t
  149. (move-to-previous-line)
  150. (if (= (current-line-fetch 0) (char D))
  151. (current-line-store 0 (char space)))
  152. )))
  153. (de dired-help ()
  154. (write-prompt
  155. "DIRED: D-delete, U-undelete, E-edit file, S-sort, R-reverse sort, Q-exit")
  156. )
  157. (de dired-next-hog ()
  158. (write-prompt "The DIRED NEXT HOG command is unimplemented.") (Ding)
  159. )
  160. (de dired-automatic-delete ()
  161. (write-prompt "The DIRED AUTOMATIC DELETE command is unimplemented.") (Ding)
  162. )
  163. (de dired-edit-file ()
  164. (write-prompt "")
  165. (if (not (dired-valid-line)) (Ding)
  166. (let* ((file-info (nth BufferAuxiliaryInfo (+ CurrentLineIndex 1)))
  167. (file-name (fi-full-name file-info))
  168. (old-buffer CurrentBufferName)
  169. )
  170. (find-file file-name)
  171. (setf BufferPreviousBuffer old-buffer)
  172. (write-prompt "C-M-L returns to DIRED; C-X K kills buffer and returns.")
  173. )
  174. )
  175. )
  176. (de dired-reverse-sort ()
  177. (write-prompt "Reverse Sort by ")
  178. (while t
  179. (let ((ch (RaiseChar (GetNextCommandCharacter))))
  180. (cond
  181. ((= ch (char F))
  182. (dired-perform-sort "Reverse Sort by Filename" 'dired-filename-reverser)
  183. (exit))
  184. ((= ch (char S))
  185. (dired-perform-sort "Reverse Sort by Size" 'dired-size-reverser)
  186. (exit))
  187. ((= ch (char W))
  188. (dired-perform-sort "Reverse Sort by Write date" 'dired-write-reverser)
  189. (exit))
  190. ((= ch (char R))
  191. (dired-perform-sort "Reverse Sort by Read date" 'dired-read-reverser)
  192. (exit))
  193. ((= ch (char ?))
  194. (write-prompt "Reverse Sort by (Filename, Size, Read date, Write date) ")
  195. (next))
  196. (t (write-prompt "") (Ding) (exit))
  197. ))))
  198. (de dired-sort ()
  199. (write-prompt "Sort by ")
  200. (while t
  201. (let ((ch (RaiseChar (GetNextCommandCharacter))))
  202. (cond
  203. ((= ch (char F))
  204. (dired-perform-sort "Sort by Filename" 'dired-filename-sorter)
  205. (exit))
  206. ((= ch (char S))
  207. (dired-perform-sort "Sort by Size" 'dired-size-sorter)
  208. (exit))
  209. ((= ch (char W))
  210. (dired-perform-sort "Sort by Write date" 'dired-write-sorter)
  211. (exit))
  212. ((= ch (char R))
  213. (dired-perform-sort "Sort by Read date" 'dired-read-sorter)
  214. (exit))
  215. ((= ch (char ?))
  216. (write-prompt "Sort by (Filename, Size, Read date, Write date) ")
  217. (next))
  218. (t (write-prompt "") (Ding) (exit))
  219. ))))
  220. (de dired-srccom-file ()
  221. (write-prompt "The DIRED SRCCOM command is unimplemented.") (Ding)
  222. )
  223. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  224. % DIRED Support Functions
  225. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  226. (de dired-valid-line ()
  227. (and
  228. (>= CurrentLineIndex 0)
  229. (> (current-line-length) 60)
  230. (= (current-line-fetch 1) (char space))))
  231. (de dired-determine-actions (file-list)
  232. % Return a list containing two lists: the first a list of
  233. % file names to be deleted, the second a list of file names
  234. % to be undeleted.
  235. (let ((old-line CurrentLineIndex))
  236. (SelectLine 0)
  237. (prog1
  238. (for*
  239. (in file-info file-list)
  240. (with delete-list undelete-list file-name file-status desired-status)
  241. (do
  242. (setf file-name (fi-full-name file-info))
  243. (setf file-status (file-deleted-status file-name))
  244. (setf desired-status (current-line-fetch 0))
  245. (move-to-next-line)
  246. (if file-status
  247. (cond
  248. ((and (eq file-status 'deleted) (= desired-status (char space)))
  249. (setf undelete-list (append undelete-list (list file-name))))
  250. ((and (neq file-status 'deleted) (= desired-status (char D)))
  251. (setf delete-list (append delete-list (list file-name))))
  252. )))
  253. (returns (list delete-list undelete-list))
  254. )
  255. (SelectLine old-line))))
  256. (de dired-present-actions (action-list)
  257. (let ((delete-list (first action-list))
  258. (undelete-list (second action-list))
  259. ch)
  260. % This is a terrible way of outputting information, but it is
  261. % the way EMODE already does it.
  262. (SelectOldChannels)
  263. (ClearScreen)
  264. (dired-present-list delete-list "These files to be deleted:")
  265. (dired-present-list undelete-list "These files to be undeleted:")
  266. (prog1
  267. (while t
  268. (printf "%nDo It (YES, N, X)? ")
  269. (setf ch (get-upchar))
  270. (cond
  271. ((= ch (char Y))
  272. (if (= (get-upchar) (char E))
  273. (if (= (get-upchar) (char S))
  274. (exit T)
  275. (Ding) (next))
  276. (Ding) (next))
  277. )
  278. ((= ch (char N)) (exit NIL))
  279. ((= ch (char X)) (exit 'EXIT))
  280. ((= ch (char ?))
  281. (printf "%n YES-Do it, N-Return to DIRED, X-Exit from DIRED.")
  282. )
  283. (t (Ding))
  284. ))
  285. (ClearScreen)
  286. )
  287. ))
  288. (de get-upchar ()
  289. (let ((ch (GetNextCommandCharacter)))
  290. (cond ((AlphaP ch) (setf ch (char-upcase ch)) (WriteChar ch) ch)
  291. (t ch))))
  292. (de dired-present-list (list prompt)
  293. (if list (progn
  294. (printf "%w%n" prompt)
  295. (for (in item list)
  296. (for count 0 (if (= count 1) 0 (+ count 1)))
  297. (do (printf "%w" (string-pad-right item 38))
  298. (if (= count 1) (printf "%n"))
  299. )
  300. )
  301. (printf "%n")
  302. )))
  303. (de dired-perform-actions (action-list)
  304. (let ((delete-list (first action-list))
  305. (undelete-list (second action-list))
  306. )
  307. (for (in file delete-list)
  308. (do (file-delete file)))
  309. (for (in file undelete-list)
  310. (do (file-undelete file)))
  311. ))
  312. (de dired-perform-sort (prompt sorter)
  313. (write-prompt prompt)
  314. (setf BufferAuxiliaryInfo (GSort BufferAuxiliaryInfo sorter))
  315. (load-dired-buffer BufferAuxiliaryInfo)
  316. )
  317. (de dired-filename-sorter (f1 f2)
  318. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  319. (de dired-filename-reverser (f1 f2)
  320. (StringSortFn (fi-nice-name f2) (fi-nice-name f1)))
  321. (de dired-size-sorter (f1 f2)
  322. (or (< (fi-size f1) (fi-size f2))
  323. (and (= (fi-size f1) (fi-size f2))
  324. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  325. ))
  326. (de dired-size-reverser (f1 f2)
  327. (or (> (fi-size f1) (fi-size f2))
  328. (and (= (fi-size f1) (fi-size f2))
  329. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  330. ))
  331. (de dired-write-sorter (f1 f2)
  332. (or (< (fi-write-date f1) (fi-write-date f2))
  333. (and (= (fi-write-date f1) (fi-write-date f2))
  334. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  335. ))
  336. (de dired-write-reverser (f1 f2)
  337. (or (> (fi-write-date f1) (fi-write-date f2))
  338. (and (= (fi-write-date f1) (fi-write-date f2))
  339. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  340. ))
  341. (de dired-read-sorter (f1 f2)
  342. (or (< (fi-read-date f1) (fi-read-date f2))
  343. (and (= (fi-read-date f1) (fi-read-date f2))
  344. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  345. ))
  346. (de dired-read-reverser (f1 f2)
  347. (or (> (fi-read-date f1) (fi-read-date f2))
  348. (and (= (fi-read-date f1) (fi-read-date f2))
  349. (StringSortFn (fi-nice-name f1) (fi-nice-name f2)))
  350. ))
  351. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  352. % Useful String Functions
  353. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  354. (de string-pad-right (s desired-length)
  355. (let ((len (string-length s)))
  356. (if (< len desired-length)
  357. (string-concat s (make-string (- desired-length len) (char space)))
  358. s)))
  359. (de string-pad-left (s desired-length)
  360. (let ((len (string-length s)))
  361. (if (< len desired-length)
  362. (string-concat (make-string (- desired-length len) (char space)) s)
  363. s)))
  364. (de string-largest-common-prefix (s1 s2)
  365. (for (from i 0 (min (size s1) (size s2)) 1)
  366. (while (= (indx s1 i) (indx s2 i)))
  367. (returns (sub s1 0 (- i 1)))
  368. ))