Have been using modus-vivendi theme to which I add a bold font for everything for some time.
I would like to introduce a special customisation for comments, using normal weight, and having a keybinding that changes the contrast ratio between the comment colour and the background.
Had started writing a minor mode, but some have suggested the use of a derived mode, as the appropriate way to customise comments as described. Any examples I can use?
In the elisp manual I found define-derived-mode. As the new customisotion is for comments, I would surmise that a closely related mode to inherit would be prog-mode.
But I have no experience on how to go about successfully making a derived mode.
(defvar richkov-annotation-contrast 2
"Sets the colour contrast (against background) for comments.")
(defvar richkov-annotation-chroma
;; Using two Association Lists, each compased of a Chroma Intensity
;; Key (low, mid, high) associated with an RGB Hex-Code. Emacs
;; Minibuffer Command `M-x list-colors-display' lists colour names
;; and hex-codes.
'( (dark . ((low . "#8300E0") ; indigo (Blu:63% Red:37% Grn:0%)
(mid . "#AA33FF") ; indigo (Blu:54% Red:36% Grn:11%)
(high . "#C370FF"))) ; indigo (Blu:45% Red:35% Grn:20%)
(light . ((low . "#C16BFF") ; indigo (Blu:46% Red:35% Grn:19%)
(mid . "#AA33FF") ; indigo (Blu:54% Red:36% Grn:11%)
(high . "#8000DB"))) ) ; indigo (Blu:63% Red:37% Grn:0%)
"Colour contrast for comments, indigo on dark and light background.")
(defun richkov-annotation-font-weight ()
"Use normal weight typeface for comments."
(set-face-attribute 'font-lock-comment-face nil :weight 'normal))
(princ "Weight: ")
(princ (face-attribute 'default :weight))
(defun richkov-annotation-typeface (chroma)
"Set the foreground colour for comments.
CHROMA Intensity Key used for setting colour of comments ."
(message "richkov-annotation-typeface ")
(let* ( (colors richkov-annotation-chroma)
(levels
(alist-get (frame-parameter nil 'background-mode) colors)) )
;; make comment colour change buffer-local
(face-remap-add-relative 'font-lock-comment-face
`(:foreground ,(alist-get chroma levels)))
(message "richkov-annotation: %s contrast" chroma)) )
(defun richkov-annotation-sweep ()
"Cycles through the colour chroma for comments.
Colours are determined by `richkov-annotation'."
(interactive)
(pcase richkov-annotation-contrast
(1
(richkov-annotation-typeface 'low)
(setq richkov-annotation-contrast 2))
(2
(richkov-annotation-typeface 'mid)
(setq richkov-annotation-contrast 3))
(_
(richkov-annotation-typeface 'high)
(setq richkov-annotation-contrast 1)) ))
(defun richkov-annotation-low-contrast ()
(when richkov-minor-mode
(richkov-annotation-typeface 'low)))
(defun richkov-annotation-keytrigger ()
"Key trigger for rapid execution of richkov commands"
(interactive)
(global-set-key (kbd "H-;") #'richkov-annotation-sweep))
(defun richkov-annotation-tools ()
"Aggregates annotation tools for comments."
(richkov-annotation-font-weight)
(richkov-annotation-low-contrast)
(richkov-annotation-keytrigger))
;;;###autoload
(define-minor-mode richkov-minor-mode
"Colour Brace Marks according to their depth."
:lighter "richkov" ; indicator in mode-line
(font-lock-remove-keywords nil richkov-font-lock)
(set-face-attribute 'font-lock-comment-face nil
:weight (face-attribute 'default :weight))
(when richkov-minor-mode
(font-lock-add-keywords nil richkov-font-lock 'append)
(set (make-local-variable 'jit-lock-contextually) t)
(richkov-annotation-tools))
(when font-lock-mode
(if (fboundp 'font-lock-flush)
(font-lock-flush)
(with-no-warnings (font-lock-fontify-buffer)) )) )
;;;###autoload
(defun richkov-minor-mode-enable ()
"Enable `richkov-minor-mode'."
(richkov-minor-mode 1))
;;;###autoload
(defun richkov-minor-mode-disable ()
"Disable `richkov-minor-mode'."
(richkov-minor-mode 0))
Related
Trying to get the line numbering right aligned with a separator space and the same background color as the line highlighting in Spacemacs was quite complicated. Specialy when it came to do both at the same time in linum and linum-relative.
I don't know if this code is ok, but it manages so far:
(defun dotspacemacs/user-config ()
"Configuration function for user code.
This function is called at the very end of Spacemacs initialization after
layers configuration. You are free to put any user code."
(global-linum-mode t)
(unless window-system
(add-hook 'linum-before-numbering-hook
(lambda ()
(setq-local my-linum-format-fmt
(let ((w (length (number-to-string
(count-lines (point-min) (point-max))))))
(concat "%" (number-to-string w) "d"))))
(set-face-attribute 'linum nil
:background (face-background 'hl-line nil t))))
(defface my-linum-hl
`((t :inherit linum :background ,(face-background 'hl-line nil t)))
"Face for the current line number."
:group 'linum)
(defun my-linum-format-func (line)
(concat
(propertize (format my-linum-format-fmt line) 'face 'my-linum-hl)
(propertize " " 'face 'my-linum-hl)))
(unless window-system
(setq linum-format 'my-linum-format-func))
;; linum-relative
(linum-relative-toggle)
(unless window-system
(setq-local my-linum-relative-format-fmt
(let ((w (length (number-to-string
(count-lines (point-min) (point-max))))))
(concat "%" (number-to-string w) "s "))))
(unless window-system
(setq linum-relative-format my-linum-relative-format-fmt))
)
Problem is: The numbers background color don't change to the correct one when I change the theme while inside Emacs. The color remains the same. How do I make emacs update the linum and linum-relative background color after a color theme change?
The only way I found to change margins in emacs to my liking without things acting funny is this:
(add-hook 'window-configuration-change-hook
(lambda ()
(set-window-margins (car (get-buffer-window-list (current-buffer) nil t)) 24 24)))
I would like for this setting to be invoked only in text-mode and change back when I change to other modes. Somewhat naively I tried this:
(add-hook 'text-mode-hook
(lambda ()
(set-window-margins (car (get-buffer-window-list (current-buffer) nil t)) 24 24)))
But it's not working. What would be the right code to have the margins only change for buffers in text-mode?
Even though you can set the margins using set-window-margins, they are lost as soon as you change the window in any way. A better solution is to set the variables left-margin-width and right-margin-width. For example:
(defun my-set-margins ()
"Set margins in current buffer."
(setq left-margin-width 24)
(setq right-margin-width 24))
(add-hook 'text-mode-hook 'my-set-margins)
How about something like this? Your problem likely stems from the fact that many major modes inherit text-mode. You can either eliminate your window-configuration-change-hook, or you can use your new function major-briggs with it -- personally I'd just use the text-mode-hook with the major-briggs function.
(add-hook 'text-mode-hook (lambda ()
(major-briggs)
;; insert additional stuff if so desired
))
(defun major-briggs ()
(when (eq major-mode 'text-mode)
(set-window-margins
(car (get-buffer-window-list (current-buffer) nil t)) 24 24) ))
Here's some code to center your markdown and text files within 80 characters. This adjusts the margins for all your frames automatically.
;; Add left and right margins, when file is markdown or text.
(defun center-window (window) ""
(let* ((current-extension (file-name-extension (or (buffer-file-name) "foo.unknown")))
(max-text-width 80)
(margin (max 0 (/ (- (window-width window) max-text-width) 2))))
(if (and (not (string= current-extension "md"))
(not (string= current-extension "txt")))
;; Do nothing if this isn't an .md or .txt file.
()
(set-window-margins window margin margin))))
;; Adjust margins of all windows.
(defun center-windows () ""
(walk-windows (lambda (window) (center-window window)) nil 1))
;; Listen to window changes.
(add-hook 'window-configuration-change-hook 'center-windows)
With the following code:
(defvar-local my-text-width nil
"Text area width for current buffer, or nil if no attention needed.")
(put 'my-text-width 'safe-local-variable #'integerp)
(defun my--margin-setup ()
"Handle settings of `my-text-width'."
(walk-windows
(lambda (window)
(with-current-buffer (window-buffer window)
(let ((margin (and my-text-width
(/ (max 0 (- (window-total-width)
my-text-width))
2))))
(when (or (not (equal margin left-margin-width))
(not (equal margin right-margin-width)))
(setq left-margin-width margin)
(setq right-margin-width margin)
(set-window-buffer window (current-buffer))))))))
(add-hook 'window-configuration-change-hook #'my--margin-setup)
You can set my-text-width in a file-local or directory-local variable, and Emacs will automatically set the margins accordingly to get that text width. It works even when you resize the frame or introduce splits.
Currently my buffer with linum mode and white space mode enabled looks like this:
How do I configure the linum region to not render the whitespace symbols?
Observation: There is no need for spaces to the right of the line numbers (as shown in the question), because the fringe width can be used to control separation between the line numbers and the body.
(setq-default left-fringe-width 10)
(setq-default right-fringe-width 0)
(set-face-attribute 'fringe nil :background "black")
Option # 1: However, this is not flush-right.
(setq linum-format "%d")
Option # 2: Use leading zeros -- is flush-right.
(eval-after-load 'linum
'(progn
(defface linum-leading-zero
`((t :inherit 'linum
:foreground ,(face-attribute 'linum :background nil t)))
"Face for displaying leading zeroes for line numbers in display margin."
:group 'linum)
(defun linum-format-func (line)
(let ((w (length
(number-to-string (count-lines (point-min) (point-max))))))
(concat
(propertize (make-string (- w (length (number-to-string line))) ?0)
'face 'linum-leading-zero)
(propertize (number-to-string line) 'face 'linum))))
(setq linum-format 'linum-format-func)))
You could improve #lawlists second solution, but instead of using 0s as a space replacement, you can use some exotic whitespace like the en-space which would be "\u2002". Since we aren't using proportional fonts that will look just like a space, but whitespace won't mess with it.
I'm actually using linum-relative-mode where you can conveniently just advice linum-relative:
(advice-add 'linum-relative :filter-return
(lambda (num)
(if (not (get-text-property 0 'invisible num))
(propertize (replace-regexp-in-string " " "\u2002" num)
'face (get-text-property 0 'face num)))))
I'd like to control the color of the text displayed in Common Lisp.
Something like this pseudo-code:
(print-color (:red "hello") (:blue "world"))
Is there any way this can be done? I use SBCL and my repl is inside emacs.
Thanks!
You can use ANSI escape code to print colorful texts:
(format t "~c[31mabc~c[0m~%" #\ESC #\ESC) ; this prints a red "abc" for most modern terminals
I'm not sure whether this works in slime, although.
To enable ANSI color escape sequences, load the http://melpa.org/#/slime-repl-ansi-color package — but due to a bug, you may have to M-x slime-repl-ansi-color-mode RET in the REPL buffer. Distilled from various abandoned buggy versions, find the best and latest version at https://gitlab.com/augfab/slime-repl-ansi-color
slime-repl-ansi-color.el
(require 'ansi-color)
(require 'slime)
(define-minor-mode slime-repl-ansi-color-mode
"Process ANSI colors in Lisp output."
nil
:lighter " SlimeANSI")
(define-slime-contrib slime-repl-ansi-color
"Turn on ANSI colors in REPL output"
(:authors "Max Mikhanosha")
(:license "GPL")
(:slime-dependencies slime-repl)
(:on-load
(add-hook 'slime-repl-mode-hook 'slime-repl-ansi-color-mode)))
(defadvice slime-repl-emit (around slime-repl-ansi-colorize activate compile)
"Process ANSI colors in the Lisp output."
(with-current-buffer (slime-output-buffer)
(let ((start slime-output-start))
(setq ad-return-value ad-do-it)
(when slime-repl-ansi-color-mode
(ansi-color-apply-on-region start slime-output-end)))))
(provide 'slime-repl-ansi-color)
In your .emacs init file, something like
(add-to-list 'slime-contribs 'slime-repl-ansi-color)
should enable the slime repl expression
(format t "~c[31mRed~:*~c[32mGreen~:*~c[34mBlue~:*~c[mPlain~%" (code-char 27))
to produce varicolored output. Try
(ql:quickload :cl-ansi-text)
(cl-ansi-text:with-color (:green :style :background)
(cl-ansi-text:with-color (:yellow :effect :bright)
(princ " Yellow on Green ")))
(princ (cl-ansi-text:green
(cl-ansi-text:yellow " Yellow on Green " :effect :bright)
:style :background))
(defun color-text (string color); ANSI escape code
(let((color
(cond
((string= color "red") "31")
((string= color "green") "32")
((string= color "yellow") "33")
((string= color "white") "37")
((string= color "bright blue") "94")
((string= color "bright yellow") "93")
((string= color "bright cyan") "96")
((string= color "bright magneta") "95")
(t "90")
)))
(format t (concatenate 'string "~c[" color "m" ) #\ESC )
(eval(read-from-string string))
(format t (concatenate 'string "~c[" color "m~c[0m" ) #\ESC #\ESC))
); (color-text "(format t \"~a\" \"ADASDASDASDA dsfsdf\")" "red")
I am developing an emacs major mode for a language (aka mydsl). However, using the techniques on xahlee's site doesn't seem to be working for some reason (possibly older emacs dialect..)
The key issues I am fighting with are (1) highlighting comments is not working and (2), the use of regexp-opt lines is not working.
I've reviewed the GNU manual and looked over cc-mode and elisp mode... those are significantly more complicated than I need.
;;;Standard # to newline comment
;;;Eventually should also have %% to %% multiline block comments
(defun mydsl-comment-dwim (arg)
"comment or uncomment"
(interactive "*P")
(require 'newcomment)
(let
((deactivate-mark nil)
(comment-start "#")
(comment-end "")
comment-dwim arg)))
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;;Highlight various elements
(setq mydsl-hilite
'(
; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
))
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
(define-derived-mode mydsl-mode fundamental-mode
"MYDSL mode is a major mode for editing MYDSL files"
;Recommended by manual
(kill-all-local-variables)
(setq mode-name "MYDSL script")
(setq font-lock-defaults '((mydsl-hilite)))
(if (null mydsl-tab-width)
(setq tab-width mydsl-tab-width)
(setq tab-width default-tab-width)
)
;Comment definitions
(define-key mydsl-mode-map [remap comment-dwim] 'mydsl-comment-dwim)
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)
You have a couple of syntactic problems in your code, but you got it nearly correct. Here's my edited version which appears to do the right thing for a buffer in mydsl-mode:
; No changes to the simple vars
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;; I'd probably put in a default that you want, as opposed to nil
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
;; Two small edits.
;; First is to put an extra set of parens () around the list
;; which is the format that font-lock-defaults wants
;; Second, you used ' (quote) at the outermost level where you wanted ` (backquote)
;; you were very close
(defvar mydsl-font-lock-defaults
`((
;; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
;; ; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
)))
(define-derived-mode mydsl-mode fundamental-mode "MYDSL script"
"MYDSL mode is a major mode for editing MYDSL files"
;; fundamental-mode kills all local variables, no need to do it again
(setq mode-name "MYDSL script")
;; you again used quote when you had '((mydsl-hilite))
;; I just updated the variable to have the proper nesting (as noted above)
;; and use the value directly here
(setq font-lock-defaults mydsl-font-lock-defaults)
;; when there's an override, use it
;; otherwise it gets the default value
(when mydsl-tab-width
(setq tab-width mydsl-tab-width))
;; for comments
;; overriding these vars gets you what (I think) you want
;; they're made buffer local when you set them
(setq comment-start "#")
(setq comment-end "")
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)