Yu-Gi-Oh! Deck Building and Card Inventory Management web interface written in Common Lisp, utilizing HTMX.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 line
5.4KB

  1. #|
  2. src/toolkit/paths.lisp
  3. Utilities For Working With Directories, Files, Paths, etc.
  4. |#
  5. (in-package #:cl-deck-builder2.toolkit.paths)
  6. ;;;; Code for munging paths and finding files at paths and renaming
  7. ;;;; files and that sort of thing.
  8. (defvar +ygoprodeck-images-root+
  9. (merge-pathnames #P"ygoprodeck/" *public-directory*)
  10. "The path to where the web server can display YGOProDeck images.")
  11. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  12. (defun probe-file-list (seq defaults)
  13. "PROBE-FILE-LIST wille apply PROBE-FILE to every file in SEQ.
  14. It appears we also do some MERGE-PATHNAMES trickery."
  15. (mapcar (lambda (filename)
  16. (probe-file
  17. (merge-pathnames filename defaults)))
  18. seq))
  19. (defun relative-file-list (seq &key (type "jpg"))
  20. "RELATIVE-FILE-LIST takes a LIST of files and transforms them into data that can be presented on the web interface, e.g. for A HREF URLs.
  21. RELATIVE is in the title because we use PATHNAME-NAME to strip out any directory components on elements of SEQ.
  22. ARGUMENTS:
  23. SEQ A LIST of files.
  24. DEFAULTS This is passed as the defaults argument to MERGE-PATHNAMES.
  25. SEE STATIC-RELATIVE-FILE-LIST
  26. SEE YGO-RELATIVE-FILE-LIST"
  27. (mapcar (lambda (file)
  28. (make-pathname :name file :type type))
  29. (mapcar #'pathname-name seq)))
  30. (defun static-probe-file-list (seq)
  31. "STATIC-PROBE-FILE-LIST takes a LIST of Yu-Gi-Oh! passcodes and transforms them into data that can be presented on the web interface,e.g. for A HREF URLs.
  32. STATIC-PROBE-FILE-LIST takes a LIST of files and transforms them into data that can be presented on the web interface, e.g. for A HREF URLs. We use *PUBLIC-DIRECTORY* as the root directory for the output.
  33. ARGUMENTS:
  34. SEQ A LIST of files.
  35. SEE RELATIVE-FILE-LIST"
  36. (probe-file-list seq
  37. (relative-pathname *public-directory*)))
  38. (defun ygo-probe-file-list (seq)
  39. "YGO-RELATIVE-FILE-LIST takes a LIST of Yu-Gi-Oh! passcodes and transforms them into data that can be presented on the web interface,e.g. for A HREF URLs.
  40. ARGUMENTS:
  41. SEQ A LIST of files.
  42. SEE RELATIVE-FILE-LIST"
  43. (probe-file-list
  44. (relative-file-list (mapcar #'princ-to-string seq) :type "jpg")
  45. (relative-pathname +ygoprodeck-images-root+)))
  46. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  47. (defun make-static-filename-kind (pathname-name maybe-list &key (type "jpg"))
  48. "We use UIOP:ENSURE-LIST so this may be called with one LIST argument.
  49. TODO That seems kinda hacky to me."
  50. (merge-pathnames
  51. (make-pathname :name (format nil "~A-~{~A~^-~}"
  52. pathname-name
  53. (uiop:ensure-list maybe-list))
  54. :type type)
  55. *public-directory*))
  56. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  57. ;; Get the files from the file system .. so sloppy ...
  58. (defun image-files-list (name)
  59. (mapcar
  60. (lambda (kind)
  61. (make-static-filename-kind name kind))
  62. '("MAIN" "EXTRA" "SIDE" "MAIN-EXTRA" "MAIN-SIDE" "FINAL")))
  63. (defun probe-image-files-list (name &optional (strip t))
  64. (let* ((pathname *public-directory*)
  65. (len (length (namestring pathname))))
  66. (remove
  67. NIL
  68. (mapcar
  69. (lambda (path)
  70. (if (probe-file path)
  71. (if strip
  72. (subseq (namestring path) len)
  73. path)))
  74. (image-files-list name)))))
  75. ;; TODO UIOP:ENOUGH-PATHNAME
  76. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  77. ;; This had to be here, in WEB package probably, because YDK depends
  78. ;; on TOOLKIT so it can't go in TOOLKIT because it depends on YDK: it
  79. ;; uses YDK-NAME-OF. Perhaps I could pass just a name into this and
  80. ;; make it deck agnostic.
  81. ;;
  82. ;; Okay I've done exactly that.
  83. (defun ydk-rename-files (old-name new-name)
  84. "Rename the files from DECK if there are any files according to PROBE-IMAGE-FILES-LIST.
  85. If there are images, NEW-NAME will replace the PATHNAME-NAME of the old images."
  86. (let* ((old-files (probe-image-files-list old-name nil))
  87. (new-files
  88. (mapcar (lambda (path)
  89. (merge-pathnames
  90. (make-pathname :name path :type "jpg") *public-directory*))
  91. (mapcar (lambda (old-path)
  92. (cl-ppcre:regex-replace-all old-name (pathname-name old-path) new-name))
  93. old-files))))
  94. ;; (format t "<pre>~a</pre>" (mapcar #'list old-files new-files))))
  95. (mapcar (lambda (pair)
  96. (when (probe-file (car pair))
  97. (rename-file (car pair) (cadr pair))))
  98. (mapcar #'list old-files new-files))))
  99. (defun relative-pathname (name)
  100. (asdf:system-relative-pathname :cl-deck-builder2 name))
  101. (defun public-pathname (name)
  102. (merge-pathnames name *public-directory*))
  103. (defun static-pathname (name)
  104. (merge-pathnames name *static-directory*))
  105. (defun ygo-pathname (name)
  106. (merge-pathnames name +ygoprodeck-images-root+))
  107. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  108. ;; Was originally from files.lisp
  109. (defun digest-file-string (digest-spec pathspec &rest args)
  110. (format nil "~{~x~}"
  111. (coerce (apply #'ironclad:digest-file digest-spec pathspec args)
  112. 'list)))
  113. ;; (random-filename (pathname-type pathspec)) => uuid.type
  114. (defun random-pathname-name (&key type)
  115. (let ((uuid (uuid:print-bytes nil (uuid:make-v4-uuid))))
  116. (format nil "~a~@[.~a~]" uuid type)))