reddit / emacs
Comics Builder in GNU Emacs
atamariya · 2022-08-14 05:41
​
https://preview.redd.it/zdr0qd9u8mh91.png?width=888&format=png&auto=webp&s=647881c725c5de0e53bc61278d2b522f5e22e967
Generate comics strip from a script in GNU Emacs. https://lifeofpenguin.blogspot.com/2022/08/comics-builder-in-gnu-emacs.html
internerdt · 2022-08-14 07:38
What *can't* Emacs do at this point?
Schievel1 · 2022-08-14 09:33
Properly scroll smoothly :D
Schievel1 · 2022-08-14 09:34
I love you guys for such things :D
uneven-shiver · 2022-08-14 09:52
Then check out Emacs 29.0.50, there's (pixel-scroll-precision-mode), at least if you built your Emacs with xinput2
Schievel1 · 2022-08-14 10:08
How is that different to the usual pixel scroll mode?
Because when I do switch that on and scroll, my emacs freezes
bdunbar · 2022-08-14 10:14
Well … actually being funny is something it can’t do.
Yet.
pinacoelho · 2022-08-14 10:47
M-x psychoalalyze-pinhead
jaw0 · 2022-08-14 13:43
if you are on mac, this does:
https://bitbucket.org/mituharu/emacs-mac
MartinTheWildPig · 2022-08-14 14:54
wtf
SnooPets20 · 2022-08-15 18:46
It's still kinda iffy. If you scroll normally it skips and jumps, it doesn't behave like you would expect. By contrast, try scrolling quickly in a browser. Now THAT'S smooth.
bitwize · 2022-08-15 20:23
Anybody remember JerkCity, the webcomic created with Microsoft Comic Chat?
This reminds me of that.
GahonMelon · 2022-08-17 11:58
I tried to use this code but I get "Wrong type argument: listp, "A statement is rendered as a Narration balloon""
atamariya · 2022-08-18 04:11
Can you provide the stacktrace?
GahonMelon · 2022-08-18 04:48
You mean the procedure I used?
I copied those three el files into a searchable folder within Emacs.
I added my image files as told and changed the paths in the comics.el file.
I used the same script in your example (with .txt extention) which I used in Emacs.
Then I did M-x comics, and got that error.
​
I use Emacs 27.2.
atamariya · 2022-08-18 06:22
Go to menu bar Options-> Enter Debugger on Error. Then run the command M-x comics. If there's an error, it'll open up a new window with the stacktrace.
GahonMelon · 2022-08-18 06:54
Thanks! Here it is:
​
Debugger entered--Lisp error: (wrong-type-argument listp "A statement is rendered as a Narration balloon")
dom-tag("A statement is rendered as a Narration balloon")
(let\* ((val (dom-tag node))) (cond ((memq val '(th tr td table strong sub sup pre code span b i li ol ul a p h3 h2 h1 div body)) (setq g (svg-group nil nil :id (number-to-string (+ i 1)) :data-id (cdr (assq 'id (dom-attributes node))) :data-class (cdr (assq 'class (dom-attributes node))) :class (dom-tag node)) box (svg-rectangle g x y width height :id (number-to-string (+ i 2)) :fill "none" :stroke "black" :class (cdr (assq 'class (dom-attributes node))))) (setq i (+ i 2))) ((eq val '\\#text) (if (not (string-empty-p (setq node (string-trim node)))) (progn (setq g (svg-group svg nil :id (number-to-string ...)) added t) (let\* ((h ...) (n ...) (size ...) start str) (let (...) (save-current-buffer ... ...)))))) (t nil)))
(let\* ((i canvas--id) (padding (or padding 0)) (margin (or margin 0)) (border (or border 0)) (w 0) (h 0) (left x) (right (+ x width)) (top y) (width-max 0) (height-max 0) g box bbox added break (added1 nil)) (let\* ((val (dom-tag node))) (cond ((memq val '(th tr td table strong sub sup pre code span b i li ol ul a p h3 h2 h1 div body)) (setq g (svg-group nil nil :id (number-to-string (+ i 1)) :data-id (cdr (assq ... ...)) :data-class (cdr (assq ... ...)) :class (dom-tag node)) box (svg-rectangle g x y width height :id (number-to-string (+ i 2)) :fill "none" :stroke "black" :class (cdr (assq ... ...)))) (setq i (+ i 2))) ((eq val '\\#text) (if (not (string-empty-p (setq node ...))) (progn (setq g (svg-group svg nil :id ...) added t) (let\* (... ... ... start str) (let ... ...))))) (t nil))) (if (memq (dom-tag node) '(\\#text head script noscript style comment form map)) nil (mapc #'(lambda (a) (setq break (or (memq ... ...))) (if (setq added1 (svg-render-tag g a 0 0 ... ... padding margin border)) (progn (setq bbox ... w ... h ... w ... h ... added t i ...) (if ... ...) (dom-set-attribute ... ... ...) (setq x ... height-max ...)))) (dom-children node)) (if (and added box) (progn (dom-append-child svg g) (setq width-max (max width-max (+ (- x left))) height-max (+ (max height-max h) (- y top))) (dom-set-attribute box 'width (if width (min width width-max) width-max)) (dom-set-attribute box 'height (if height (min height height-max) height-max))))) (setq canvas--id (+ i 1)) added)
svg-render-tag((g nil) "A statement is rendered as a Narration balloon" 0 0 240 15)
(let\* ((i canvas--id) (type (or type 'speak)) (padding 15) (font-size comics-font-size) (node (dom-node 'g)) (text-node (dom-node 'g)) x y w1 h1 dx bbox) (svg-render-tag text-node txt 0 0 (- (\* 18 font-size) (\* 2 padding)) font-size) (setq i canvas--id) (setq bbox (svg-bbox (last text-node)) w1 (+ (\* 2 padding) (- (nth 2 bbox) (nth 0 bbox))) h1 (+ (\* 2 padding) (- (nth 3 bbox) (nth 1 bbox)))) (setq x (+ (/ w1 5)) x2 (or x2 (/ w1 3)) dx (min 10 (/ h1 2)) y (+ (\* h1 1.1))) (svg-rectangle node 0 0 w1 y :id (+ i 1) :rx (if (eq type 'narrate) nil padding) :fill "white") (if (eq type 'narrate) nil (if right (setq x (- w1 x) x2 (or x2 (- w1 x2)) dx (- dx))) (svg-polyline node (list (cons x y) (cons x2 (+ y size)) (cons (+ x dx) y)) :fill "white" :id (+ i 2)) (svg-line node x y (+ x dx) y :stroke-color "white" :stroke-width 2 :id (+ i 3))) (dom-set-attribute node 'transform (format "translate(%d,%d)" x1 y1)) (dom-set-attribute text-node 'transform (format "translate(%d,%d)" padding padding)) (dom-append-child node text-node) (dom-append-child svg node) (setq canvas--id (+ i 4)) (cons w1 y))
comics--create-balloon((g nil) 0 0 "A statement is rendered as a Narration balloon" narrate)
(setq size1 (comics--create-balloon g-panel x y narration 'narrate) y (+ y (cdr size1)))
(progn (setq size1 (comics--create-balloon g-panel x y narration 'narrate) y (+ y (cdr size1))))
(if narration (progn (setq size1 (comics--create-balloon g-panel x y narration 'narrate) y (+ y (cdr size1)))))
(let\* ((defs (car (dom-by-tag svg 'defs))) (g-actors (dom-node 'g)) (g-balloons (dom-node 'g)) (g-stage (dom-node 'g)) (g-panel (dom-node 'g)) (i 0) (padding 15) (text "some long text here are some of those") (tail-height (/ h 20)) (xpos (make-list n nil)) file x y w1 h1 dx bbox size1 size2 actor action repeat) (setq x 0 y 0) (comics--create-background svg defs background x1 y1 w h) (if narration (progn (setq size1 (comics--create-balloon g-panel x y narration 'narrate) y (+ y (cdr size1))))) (setq y (+ y padding)) (let ((--dotimes-limit-- (length dialog)) (i 0)) (while (< i --dotimes-limit--) (setq repeat (nth (car (nth i dialog)) xpos) size1 '(0 . 0) size2 '(0 . 0)) (if repeat nil (setq size1 (comics--create-actor g-actors (car (nth i dialog)) x (nth 2 (nth i dialog)) (> i 0))) (let\* ((c (nthcdr ... xpos))) (setcar c (cons x (car size1))))) (setq size2 (comics--create-balloon g-balloons (or (car repeat) x) y (nth 1 (nth i dialog)) nil (or (> i (/ i 2))) (\* (- 3 i) tail-height) (+ (/ (or ... ...) 2))) x (+ x (car size1)) y (+ y (cdr size2))) (setq i (1+ i)))) (dom-set-attribute g-actors 'transform (format "translate(0,%d)" (+ y tail-height))) (dom-append-child g-stage g-actors) (dom-append-child g-stage g-balloons) (dom-set-attribute g-stage 'transform (format "translate(%d,0)" (/ (- w x) 2))) (dom-set-attribute g-stage 'clip-path (format "url(#%s)" "clip")) (dom-append-child g-panel g-stage) (dom-set-attribute g-panel 'transform (format "translate(%d,%d)" x1 y1)) (dom-append-child svg g-panel))
GahonMelon · 2022-08-18 06:54
\--->
comics--create-panel((svg ((width . 705) (height . 762) (version . "1.1") (xmlns . "http://www.w3.org/2000/svg") (xmlns:xlink . "http://www.w3.org/1999/xlink") (font-family . "DejaVu Sans") (stroke . "black")) (defs nil (clipPath ((id . "clip")) (rect ((width . 337) (height . 742) (x . 0) (y . 0) (fill . "none") (id . 3)))) (image ((xlink:href . "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD...") (height . 742) (width . 1016.2636103151862) (clip-path . "url(#clip)") (id . "background")))) (use ((href . "#background") (y . 10) (x . 10) (id . 0))) (rect ((width . 337) (height . 742) (x . 10) (y . 10) (fill . "none") (id . 1)))) 10 10 337 742 ((0 " Hi" nil) (1 " Hello" nil)) 2 "A statement is rendered as a Narration balloon" "park1")
(while (< i --dotimes-limit--) (setq panel (nth i panels) dialog (nth 1 panel) narration (nth 0 panel) background (nth 2 panel)) (comics--create-panel svg (+ padding (\* i (+ w1 padding))) (+ padding (\* j (+ h1 padding))) w1 h1 dialog (length actors) narration background) (setq i (1+ i)))
(let ((--dotimes-limit-- (length panels)) (i 0)) (while (< i --dotimes-limit--) (setq panel (nth i panels) dialog (nth 1 panel) narration (nth 0 panel) background (nth 2 panel)) (comics--create-panel svg (+ padding (\* i (+ w1 padding))) (+ padding (\* j (+ h1 padding))) w1 h1 dialog (length actors) narration background) (setq i (1+ i))))
(let\* ((padding 10) (m 0) (j 0) (n comics-col-max) (canvas--id 0) (w1 (/ (- w (\* (1+ n) padding)) n)) start end line tok actor emotion txt h1 actors dialog narration background panel panels) (goto-char (point-min)) (while (re-search-forward "\\n\\n" nil t) (setq m (1+ m))) (setq m (ceiling (/ m n 1.0)) h1 (/ (- h (\* (1+ m) padding)) m)) (goto-char (point-min)) (while (not (eobp)) (setq start (point) end (line-end-position)) (setq line (string-trim (buffer-substring-no-properties start end)) tok (split-string line ":")) (if (looking-at "\[\[\]") (progn (setq background (string-trim (substring line 1 (1- ...)))))) (if (string-empty-p line) (progn (if (and (or narration dialog) (/= (length panels) comics-col-max)) (progn (setq panels (cons ... panels)))) (if (= (length panels) comics-col-max) (progn (setq panels (reverse panels)) (let (... ...) (while ... ... ... ...)) (setq panels nil j (1+ j)))) (setq narration nil dialog nil))) (if (string-empty-p line) nil (if (= (length tok) 1) (setq narration (car tok)) (setq actor (car tok) emotion nil txt (car (cdr tok))) (if (string-match "\\\\(.\*\\\\)(\\\\(.\*\\\\))" txt) (setq emotion (match-string 2 txt) txt (match-string 1 txt))) (if (member actor actors) nil (setq actors (cons actor actors))) (setq dialog (cons (list (1- ...) txt emotion) dialog)))) (forward-line)) (if dialog (progn (setq panels (cons (list narration (nreverse dialog) background) panels)))) (setq panels (reverse panels)) (let ((--dotimes-limit-- (length panels)) (i 0)) (while (< i --dotimes-limit--) (setq panel (nth i panels) dialog (nth 1 panel) narration (nth 0 panel) background (nth 2 panel)) (comics--create-panel svg (+ padding (\* i (+ w1 padding))) (+ padding (\* j (+ h1 padding))) w1 h1 dialog (length actors) narration background) (setq i (1+ i)))))
comics--create((svg ((width . 705) (height . 762) (version . "1.1") (xmlns . "http://www.w3.org/2000/svg") (xmlns:xlink . "http://www.w3.org/1999/xlink") (font-family . "DejaVu Sans") (stroke . "black")) (defs nil (clipPath ((id . "clip")) (rect ((width . 337) (height . 742) (x . 0) (y . 0) (fill . "none") (id . 3)))) (image ((xlink:href . "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD...") (height . 742) (width . 1016.2636103151862) (clip-path . "url(#clip)") (id . "background")))) (use ((href . "#background") (y . 10) (x . 10) (id . 0))) (rect ((width . 337) (height . 742) (x . 10) (y . 10) (fill . "none") (id . 1)))) 705 762)
(let\* ((buf (get-buffer-create "\*Comics\*")) (bbox (window-body-pixel-edges)) (w (- (nth 2 bbox) (nth 0 bbox))) (h (- (nth 3 bbox) (nth 1 bbox))) (svg (svg-create w h :stroke-color "black" :font-family "DejaVu Sans"))) (comics--create svg w h) (pop-to-buffer buf) (save-current-buffer (set-buffer buf) (setq inhibit-read-only t) (erase-buffer) (svg-print svg) (image-mode)))
comics(nil)
funcall-interactively(comics nil)
call-interactively(comics record nil)
command-execute(comics record)
helm-M-x-execute-command(comics)
helm-execute-selection-action-1()
helm-execute-selection-action()
atamariya · 2022-08-18 07:26
This indicates a collision in definition of dom-tag. I guess you'd need dom.el from my repo too. The new definition allows string to be identified as a text node.
[https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/dom.el](https://gitlab.com/atamariya/emacs/-/blob/dev/lisp/dom.el)
Thanks for reporting.
[deleted] · 2022-08-18 07:54
[removed]