photogal3.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. (defvar *photogal/photoreel* nil)
  2. (defvar *photogal/tags*
  3. '(
  4. ("e" . (name "spokane" ;; phg will not display
  5. parent ("L" . (name "Location")))) ;; differences in the
  6. ("n" . (name "new-york" ;; names of tag
  7. parent ("L" . (name "Locution")))) ;; parents. they will be
  8. ("e" . (name "emma-chamberlain" ;; considered the same.
  9. parent ("C" . (name "Celebrity"))))
  10. ("x" . (name "lil-nas-x"
  11. parent ("C" . (name "Celebrity"))))
  12. ("a" . (name "art"))
  13. ("c" . (name "cityscape"))
  14. ("f" . (name "family"))
  15. ("g" . (name "good"))
  16. ("h" . (name "screenshot"))
  17. ("l" . (name "politics"))
  18. ("m" . (name "meme"))
  19. ("o" . (name "computer"))
  20. ("p" . (name "portrait"))
  21. ("r" . (name "reaction-photo"))
  22. ("t" . (name "photography"))
  23. ("s" . (name "selfie"))))
  24. (defcustom photogal-default-directory "/Users/jwd/bench/photos/"
  25. "This is where photogal will look for photos.")
  26. (defun photogal-create-photo-roll (photo-dir)
  27. (defun photogalroll--all-photos (directory)
  28. "Give me a list of all the photos in my operating directory."
  29. (directory-files directory
  30. t directory-files-no-dot-files-regexp))
  31. (defun photogalroll--generate (destination-dir)
  32. (mapcar (apply-partially #'photogalroll--make-photo-entry destination-dir)
  33. (photogalroll--all-photos photo-dir)))
  34. (let ((destination-dir (concat photo-dir "-photogal"))
  35. (idx 0))
  36. (mapcar (lambda (photo) (photogal--set-index photo (cl-incf idx)))
  37. (photogalroll--generate destination-dir))))
  38. (defun photogal-current-file (photoreel)
  39. "What is the file currently being operated on?"
  40. (car photoreel))
  41. (defun photogal-advance-file (photoreel)
  42. "Move forward by one photo."
  43. (append (cdr photoreel) (list (car photoreel))))
  44. (defun photogal-rewind-file (photoreel)
  45. "Reverse by one photo."
  46. (append (last photoreel) (butlast photoreel)))
  47. (defun photogal3 (photo-dir)
  48. (interactive (list (read-directory-name
  49. "where are ur photos? " photogal-default-directory)))
  50. (setq *photogal/photoreel* (photogal-create-photo-roll photo-dir))
  51. (photogal-render *photogal/photoreel* *photogal/tags*))
  52. (defun photogal-render (photoreel tags)
  53. (photogal-draw-buffer photoreel "photogal3" tags))
  54. (defun photogal-refresh ()
  55. (photogal-render *photogal/photoreel* *photogal/tags*))
  56. (defun photogal-tag-current-photo (tag)
  57. (photogaltag-toggle tag (photogal-current-file *photogal/photoreel*)))
  58. (defun photogaltag-tags= (tag1 tag2)
  59. ;; tags are equal ONLY when their keys are the same
  60. (string= (photogal-tag-key tag1) (photogal-tag-key tag2)))
  61. (defun photogaltag-tags< (tag1 tag2)
  62. (string< (photogal-tag-key tag1) (photogal-tag-key tag2)))
  63. (defun photogaltag-is-parent (tag)
  64. ;; 91 is '[', right after 'Z' in the ascii table
  65. (< (string-to-char (photogal-tag-key tag))
  66. 91))
  67. (defun photogaltag-is-parent-or-child (mytag)
  68. (or (photogaltag-is-parent mytag)
  69. (photogal-tag-parent mytag)))
  70. (defun photogaltag-add-tag (tag photo)
  71. (let ((tags (photogal--get-tags photo)))
  72. (photogal--set-tags
  73. photo
  74. (seq-sort #'photogaltag-tags<
  75. (seq-uniq (cons tag tags) #'photogaltag-tags=)))))
  76. (defun photogaltag-rm-tag (tag photo)
  77. (photogal--set-tags
  78. photo
  79. (seq-remove (apply-partially #'photogaltag-tags= tag)
  80. (photogal--get-tags photo))))
  81. (defun photogaltag-has-tag-p (tag photo)
  82. (seq-contains-p (photogal--get-tags photo)
  83. tag
  84. #'photogaltag-tags=))
  85. (defun collapse-tag (tag)
  86. (let* ((parent (photogal-tag-parent tag))
  87. (parent-key (photogal-tag-key parent))
  88. (parent-name (photogal-tag-name parent))
  89. (child-name (photogal-tag-name tag))
  90. (child-key (photogal-tag-key tag)))
  91. (list child-key 'name (concat child-name parent-name))))
  92. (defun photogaltag-toggle (tag photo)
  93. "If a photo has the tag, remove it. If it doesn't have it, add it."
  94. (if (photogaltag-has-tag-p tag photo)
  95. (photogaltag-rm-tag tag photo)
  96. (photogaltag-add-tag tag photo)))
  97. ;; // PHOTO DATAOBJECT \\ ;;
  98. (defun photogalroll--make-photo-entry (destination-dir filepath)
  99. `(filepath ,filepath
  100. tags ,nil
  101. name ,nil
  102. folders ,(list destination-dir)
  103. copy-to-dir ,nil
  104. index ,-1
  105. ))
  106. (defun photogal--get-filepath (photo)
  107. (plist-get photo 'filepath))
  108. (defun photogal--get-tags (photo)
  109. "What are all the tags for this file?"
  110. (plist-get photo 'tags))
  111. (defun photogal--set-tags (photo tags)
  112. (plist-put photo 'tags
  113. tags))
  114. (defun photogal--get-folders (photo)
  115. "What are all the folders for this file?"
  116. (plist-get photo 'folders))
  117. (defun photogal--set-folders (photo folders)
  118. (plist-put photo 'folders
  119. folders))
  120. (defun photogal--get-index (photo)
  121. (plist-get photo 'index))
  122. (defun photogal--set-index (photo index)
  123. (plist-put photo 'index
  124. index))
  125. (defun photogal--get-copy-to-dir? (photo)
  126. (plist-get photo 'copy-to-dir))
  127. (defun photogal--set-copy-to-dir? (photo copy-to-dir)
  128. (plist-put photo 'copy-to-dir
  129. copy-to-dir))
  130. ;; \\ // ;;
  131. (defun photogal-engage-keys-for-tags (tags)
  132. (mapcar (lambda (tag)
  133. (let ((key (photogal-tag-key tag)))
  134. (eval `(define-key photogal3-mode-map (kbd ,key)
  135. (lambda () (interactive)
  136. (photogal-tag-current-photo ',tag)
  137. (photogal-refresh))))
  138. ))
  139. tags))
  140. (defun photogal-engage-keys-for-parents (parent-tags)
  141. (mapcar (lambda (tag)
  142. (let ((key (photogal-tag-key tag)))
  143. (eval `(define-key photogal3-mode-map (kbd ,key)
  144. (lambda () (interactive)
  145. (photogal-tag-family ',tag)
  146. ;; (photogal-refresh)
  147. )))
  148. ))
  149. parent-tags))
  150. (defun photogal-tag-family (parent-tag)
  151. (photogal-render
  152. *photogal/photoreel*
  153. (mapcar #'collapse-tag
  154. (photogal-child-tags-belonging-to parent-tag *photogal/tags*))))
  155. ;; //////////////// |||||||||||||||| //////////////// ;;
  156. ;; ^^^^ ^^^^ ^^^^ work zone ^^^^ ^^^^ ^^^^
  157. (defun photogaldraw-activate-key-commands (active-tags)
  158. (photogal-engage-keys-for-tags (photogal-tags-with-no-parents active-tags))
  159. (photogal-engage-keys-for-parents (photogal-all-parents *photogal/tags*))
  160. (mapcar (lambda (key-command)
  161. (let ((key (car key-command))
  162. (function (cadr key-command))
  163. (info-message (caddr key-command))
  164. (display (cadddr key-command)))
  165. (eval
  166. `(define-key photogal3-mode-map (kbd ,key)
  167. (lambda () (interactive)
  168. (message ,info-message)
  169. (funcall #',function))))))
  170. key-commands)
  171. )
  172. (defun photogaldraw-index-tracker (photoreel)
  173. (let* ((current-file (photogal-current-file photoreel))
  174. (current-index (photogal--get-index current-file))
  175. (total-photos (length photoreel)))
  176. (insert " ur lookin at photo ")
  177. (photogal--insert-print-color current-index "red")
  178. (insert " of ")
  179. (photogal--insert-print-color total-photos "red")))
  180. (defun photogaldraw--commit-message (photo)
  181. (if (photogal--get-copy-to-dir? photo)
  182. (progn
  183. (insert "\t\t\t\t will commit?: ")
  184. (photogal--insert-print-color "✓" "SeaGreen3"))
  185. (progn
  186. (insert "\t\t\t\t will commit?: ")
  187. (photogal--insert-print-color "✗" "red"))))
  188. (defun photogaldraw--insert-image (filepath)
  189. (insert " ")
  190. (insert-image
  191. (if resize-image
  192. (create-image filepath 'imagemagick nil
  193. :width (- (window-pixel-width) 75))
  194. (create-image filepath 'imagemagick nil
  195. :height (/ (window-pixel-height) 2)))))
  196. (defun photogaldraw--insert-photo-tags (photo)
  197. (photogaldraw--newline)
  198. (photogaldraw--newline)
  199. (insert "Current tags: ")
  200. (insert (format "%s"
  201. (mapcar #'photogal-tag-name (photogal--get-tags photo))))
  202. (photogaldraw--newline))
  203. (defun photogaldraw--insert-tags (tags photo)
  204. (photogal--insert-print-color "Tag:\n" "red")
  205. (mapcar (lambda (tag)
  206. (let* ((key-command (photogal-tag-key tag))
  207. (tag-name (photogal-tag-name tag))
  208. (activated (photogaltag-has-tag-p tag photo)))
  209. (photogal--pprint-key-command key-command tag-name 16 activated)))
  210. tags))
  211. (defun photogaldraw--insert-commands-to-buffer (commands)
  212. "Pretty print the commands with their invoke key."
  213. (photogaldraw--newline)
  214. (photogaldraw--newline)
  215. (photogal--insert-print-color "Commands:" "red")
  216. (photogaldraw--newline)
  217. (mapcar (lambda (command)
  218. (let ((key-command (car command))
  219. (display-copy (caddr command)))
  220. (when display-copy ;; only show command if it has description
  221. (photogal--pprint-key-command key-command display-copy 16))))
  222. commands))
  223. (defun photogaldraw--newline ()
  224. (insert "\n"))
  225. (defun photogal--pprint-key-command (key-to-type name-of-command padding &optional activated)
  226. "Make the low-level insertions to the buffer to render a key-command."
  227. (let ((length-of-unit (+ (length key-to-type) (length name-of-command) 3)))
  228. (when (> (+ (+ (current-column) length-of-unit)
  229. 10)
  230. (window-width))
  231. (insert "\n"))
  232. (insert "[")
  233. (if activated
  234. (photogal--insert-print-color key-to-type "SeaGreen3")
  235. (photogal--insert-print-color key-to-type "dark gray"))
  236. (insert "] ")
  237. (photogal--insert-print-color name-of-command "blue" (- padding (length key-to-type)))
  238. (insert " ")))
  239. (defun photogal--insert-print-color (string-to-insert-to-buffer color &optional padding)
  240. "Insert some text in this color."
  241. (let ((beg (point))
  242. (padding
  243. (if padding
  244. (format "%s" padding)
  245. "0")))
  246. (insert (format (concat "%-" padding "s") string-to-insert-to-buffer))
  247. (put-text-property beg (point) 'font-lock-face `(:foreground ,color))))
  248. (defun photogal-draw-buffer (photoreel buffer tags)
  249. (let* ((current-photo (photogal-current-file photoreel))
  250. (resize-image nil)
  251. (photo-file-path (photogal--get-filepath current-photo))
  252. (buf (get-buffer-create buffer))
  253. (display-tags (photogal-top-level-tags tags)))
  254. (with-current-buffer buf
  255. (photogal3-mode)
  256. (erase-buffer)
  257. (photogaldraw-index-tracker photoreel)
  258. (photogaldraw--commit-message current-photo)
  259. (photogaldraw--newline)
  260. (photogaldraw--insert-image (photogal--get-filepath current-photo))
  261. (photogaldraw--newline)
  262. (photogaldraw--insert-photo-tags current-photo)
  263. (photogaldraw--newline)
  264. (photogaldraw--insert-tags display-tags current-photo)
  265. (photogaldraw--newline)
  266. (photogaldraw--insert-commands-to-buffer key-commands)
  267. (switch-to-buffer buf)
  268. (photogaldraw-activate-key-commands tags))))
  269. (defvar key-commands
  270. '(
  271. ("RET" photogal-next-file "next")
  272. ("<right>" photogal-next-file nil)
  273. ("SPC" photogal-next-file nil )
  274. ("C-p" photogal-prev-file "prev")
  275. ("<left>" photogal-prev-file nil)
  276. ;; ("C-a" . photogal-add-tag)
  277. ;; ("C-d" . photogal-delete-tag)
  278. ;; ("C-f" . photogal-show-filepath)
  279. ;; ("C-r" . photogal-resize-photo)
  280. ;; ("C-c" . photogal-compile-and-commit)
  281. ;; ("C-n" . photogal-name-the-file)
  282. ;; ("C-o" . photogal-give-a-folder)
  283. ("C-g" photogal-refresh "redraw buffer!")
  284. ))
  285. (defun photogal-next-file ()
  286. "Advance by one photo."
  287. (interactive)
  288. (setq *photogal/photoreel* (photogal-advance-file *photogal/photoreel*))
  289. (photogal-render *photogal/photoreel* *photogal/tags*))
  290. (defun photogal-prev-file ()
  291. "Reverse by one photo."
  292. (interactive)
  293. (setq *photogal/photoreel*
  294. (append (last *photogal/photoreel*) (butlast *photogal/photoreel*)))
  295. (photogal-render *photogal/photoreel* *photogal/tags*))
  296. ;; // tag shit
  297. (defun photogal-all-parents (tags)
  298. (seq-filter (lambda (x) x)
  299. (seq-uniq (mapcar (lambda (tag) (plist-get (cdr tag) 'parent)) tags)
  300. (lambda (a b) (string= (car a) (car b))))))
  301. (defun photogal-child-tags-belonging-to (parent tags)
  302. (seq-filter
  303. (lambda (tag)
  304. (photogaltag-tags= parent (photogal-tag-parent tag)))
  305. tags))
  306. (defun photogal-tags-with-parents (tags)
  307. (seq-filter (lambda (tag) (plist-member (cdr tag) 'parent))
  308. *photogal/tags*))
  309. (defun photogal-tags-with-no-parents (tags)
  310. (seq-remove (lambda (tag) (plist-member (cdr tag) 'parent)) tags))
  311. (defun photogal-top-level-tags (tags)
  312. (append (photogal-all-parents tags)
  313. (photogal-tags-with-no-parents tags)))
  314. (defun photogal-tag-name (tag)
  315. (plist-get (cdr tag) 'name))
  316. (defun photogal-tag-parent (tag)
  317. (plist-get (cdr tag) 'parent))
  318. (defun photogal-tag-key (tag)
  319. (car tag))
  320. (defvar photogal3-mode-map nil "Keymap for `photogal-mode`")
  321. ;; (setq photogal3-mode-map nil)
  322. ;; (setq photogal3-mode-map (make-sparse-keymap))
  323. (define-derived-mode photogal3-mode text-mode "photogal3"
  324. "Major mode for grouping and labeling images.")
  325. ;; (progn
  326. ;; (setq photogal-mode-map (make-sparse-keymap))
  327. ;; (map-do (lambda (key command)
  328. ;; (eval `(define-key photogal-mode-map (kbd ,key) ',command)))
  329. ;; key-commands))