Update of /project/beirc/cvsroot/beirc In directory clnet:/tmp/cvs-serv9934
Modified Files: beirc.asd message-display.lisp variables.lisp Log Message: Add Thomas Persson's color code interpretation patch. Also, add *filter-colors*
--- /project/beirc/cvsroot/beirc/beirc.asd 2006/03/24 21:19:43 1.8 +++ /project/beirc/cvsroot/beirc/beirc.asd 2006/03/27 21:42:41 1.9 @@ -6,7 +6,7 @@ (cl:in-package :beirc.system)
(defsystem :beirc - :depends-on (:mcclim :cl-irc :split-sequence :tab-layout) + :depends-on (:mcclim :cl-irc :split-sequence :tab-layout :cl-ppcre) :components ((:file "package") (:file "variables" :depends-on ("package")) (:file "events" :depends-on ("package")) --- /project/beirc/cvsroot/beirc/message-display.lisp 2006/03/27 13:46:47 1.41 +++ /project/beirc/cvsroot/beirc/message-display.lisp 2006/03/27 21:42:41 1.42 @@ -7,6 +7,29 @@
(defvar *current-message*)
+(defparameter *colors* `((0 . (:ink ,+white+)) + (1 . (:ink ,+black+)) + (2 . (:ink ,+blue+)) + (3 . (:ink ,+green+)) + (4 . (:ink ,+red+)) + (5 . (:ink ,+brown+)) + (6 . (:ink ,+purple+)) + (7 . (:ink ,+orange+)) + (8 . (:ink ,+yellow+)) + (9 . (:ink ,+light-green+)) + (10 . (:ink ,+dark-cyan+)) + (11 . (:ink ,+cyan+)) + (12 . (:ink ,+royal-blue+)) + (13 . (:ink ,+pink+)) + (14 . (:ink ,+grey+)) + (15 . (:ink ,+light-grey+)) + ("" . (normal)) + ("" . (underline)) + ("" . (inverse)) + ("" . (bold)))) + +(defparameter *color-scanner* (cl-ppcre:create-scanner "[0-9]{1,2}(,[0-9]{1,2}){0,1}||||")) + (define-presentation-type url () :inherit-from 'string)
@@ -124,32 +147,138 @@ (string first-char))) (otherwise (values word ""))))))
+(defun extract-color (string) + (multiple-value-bind (start end) + (cl-ppcre:scan *color-scanner* + string) + (if start + (let* ((message (subseq string end)) + (color-code (subseq string start end)) + (color-code (or (cl-ppcre:all-matches-as-strings "[0-9]{1,2}" + color-code) + (list (cl-ppcre:scan-to-strings "|||" + color-code)))) + (foreground (or (parse-integer (car color-code) + :junk-allowed t) + (car color-code))) + (background (when (cadr color-code) + (parse-integer (cadr color-code) + :junk-allowed t))) + (foreground (cdr (assoc foreground + *colors* + :test #'equal))) + (background (cdr (assoc background + *colors* + :test #'equal)))) + (values message + foreground + background + )) + string))) + +(defun split-before (delimiter string) + (let ((matches (cl-ppcre:all-matches delimiter string))) + (if matches + (loop for (a b c) on matches by #'cddr + collecting (subseq string a c) into strings + finally (return (if (zerop (car matches)) + strings + (cons (subseq string + 0 + (car matches)) + strings)))) + (list string)))) + +(defmacro do-colored-string ((string-var str) &body body) + `(dolist (part (split-before *color-scanner* ,str)) + (multiple-value-bind (message foreground background) + (extract-color part) + (cond (*filter-colors* nil) + ((equal (car foreground) + 'normal) + (setf foreground-color +black+ + background-color +white+)) + ((equal (car foreground) + :ink) + (setf foreground-color + (cadr foreground)) + (when background + (setf background-color (cadr background)))) + ((equal (car foreground) + 'bold) + (setf bold (if bold nil :bold))) + ((equal (car foreground) + 'underline) + (setf underline (not underline))) + ((equal (car foreground) + 'inverse) + (setf inverse (not inverse)))) + (with-drawing-options (t :text-face bold) + (let ((,string-var message)) + (if inverse + (with-irc-colors (background-color foreground-color underline) + ,@body) + (with-irc-colors (foreground-color background-color underline) + ,@body))))))) + +(defmacro with-irc-colors ((foreground background underlinep) &body body) + `(with-sheet-medium (medium *standard-output*) + (let ((record (with-new-output-record (t) + (with-drawing-options (t :ink ,foreground) + ,@body)))) + (with-bounding-rectangle* (left top right bottom) + record + (unless (equal left right) + (unless (equal ,background +white+) + (with-identity-transformation (medium) + (draw-rectangle* *standard-output* + left + top + right + bottom + :filled t + :ink ,background) + (replay-output-record record *standard-output*) + (setf (stream-cursor-position *standard-output*) + (values right top)))) + (when ,underlinep + (draw-line* *standard-output* left (- bottom 1) + (- right 1) (- bottom 1) + :ink ,foreground))) + record)))) + (defun format-message* (mumble &key (limit *default-fill-column*) (start-length 0)) - (loop for (word . rest) on (split-sequence:split-sequence #\Space mumble) - with column = start-length - do (incf column (length word)) - when (> column limit) - do (setf column (length word)) - (terpri) - do (multiple-value-bind (%word stripped-preceding-punctuation) (strip-preceding-punctuation word) - (multiple-value-bind (word% stripped-punctuation) (strip-punctuation %word) - (write-string stripped-preceding-punctuation) - (cond - ((or (search "http://" word%) (search "https://" word%)) - (present-url word%)) - ((or - (nick-equals-my-nick-p word% (irc:connection *current-message*)) - (and (current-connection *application-frame*) - (irc:find-user (current-connection *application-frame*) word%))) - (present word% 'nickname)) - ((channelp word%) (present word% 'channel)) - (t (write-string word%))) - (write-string stripped-punctuation))) - ;; TODO: more highlighting - unless (or (null rest) (>= column limit)) - do (write-char #\Space) - (incf column)) - (terpri)) + (let ((foreground-color (medium-foreground *standard-output*)) + (background-color (medium-background *standard-output*)) + (bold nil) + (underline nil) + (inverse nil)) + (let ((column start-length)) + (loop for (word . rest) on (split-sequence:split-sequence #\Space mumble) + do (do-colored-string (word word) + (incf column (length word)) + (when (> column limit) + (setf column (length word)) + (terpri)) + (multiple-value-bind (%word stripped-preceding-punctuation) (strip-preceding-punctuation word) + (multiple-value-bind (word% stripped-punctuation) (strip-punctuation %word) + (write-string stripped-preceding-punctuation) + (cond + ((or (search "http://" word%) (search "https://" word%)) + (present-url word%)) + ((or + (nick-equals-my-nick-p word% (irc:connection *current-message*)) + (and (current-connection *application-frame*) + (irc:find-user (current-connection *application-frame*) word%))) + (present word% 'nickname)) + ((channelp word%) (present word% 'channel)) + (t (write-string word%))) + (write-string stripped-punctuation)))) + do (unless (or (null rest) (>= column limit)) + (do-colored-string (s " ") + (write-string s) + (incf column)))) + (terpri))))
;;; privmsg-like messages
--- /project/beirc/cvsroot/beirc/variables.lisp 2006/03/27 13:46:47 1.13 +++ /project/beirc/cvsroot/beirc/variables.lisp 2006/03/27 21:42:41 1.14 @@ -49,4 +49,8 @@ *auto-close-inactive-query-windows-p*).")
(defvar *meme-log-bot-nick* "cmeme" - "The name of the meme channel log bot") \ No newline at end of file + "The name of the meme channel log bot") + +(defvar *filter-colors* nil + "If set to non-NIL, filter color, bold, inverse and underline +codes from IRC messages.") \ No newline at end of file