How to not highlight values in comments in Emacs? - regex

I want to highlight true and false values in some configuration files. I've
done it this way:
(defun my/highlight-in-properties-files ()
"Highlight regexps in PROPERTIES files."
(when (string-match-p ".properties" (file-name-nondirectory buffer-file-name))
(highlight-regexp "true" 'hi-green)
(highlight-regexp "false" 'hi-pink)))
But it also highlight those values in comments:
Is there a way to exclude those highlightings?
UPDATE -- highlight-regexp is an alias for ‘hi-lock-face-buffer’ in ‘hi-lock.el’. And string-match-p is a compiled Lisp function in ‘subr.el’.

You can just add the regexps via font-lock-add-keywords, which will already account for the comment syntax in the buffer, eg.
(defun my-font-lock-additions ()
(require 'hi-lock) ; fonts
(font-lock-add-keywords
nil
'(("\\btrue\\b" . 'hi-green)
("\\bfalse\\b" . 'hi-pink)))
(font-lock-flush))
And call (font-lock-refresh-defaults) to revert back to OG settings.
Sticking to a purely regexp solution with highlight-regexp will undoubtebly produce some mistakes in odd cases, but, I think just customizing your regex to check for a comment prefix would probably work well enough as well,
(defun my/highlight-in-properties-files ()
"Highlight regexps in PROPERTIES files."
(when (string-match-p ".properties" (file-name-nondirectory buffer-file-name))
(comment-normalize-vars) ; ensure comment variables are setup
(let ((cmt-re (format "^[^%s]*" (regexp-quote (string-trim comment-start)))))
(highlight-regexp (format "%s\\(\\_<true\\_>\\)" cmt-re) 'hi-green 1)
(highlight-regexp (format "%s\\(\\_<false\\_>\\)" cmt-re) 'hi-pink 1))))

A way would be to simply add a $ at the end of your regex to not match the comments, as the true/false are always at the end, while those in comments are always situated in the middle of a sentence
(defun my/highlight-in-properties-files ()
"Highlight regexps in PROPERTIES files."
(when (string-match-p ".properties" (file-name-nondirectory buffer-file-name))
(highlight-regexp "true$" 'hi-green)
(highlight-regexp "false$" 'hi-pink)))

Related

How this code translates a number to English?

I'm new to Clojure and found there's a piece of code like following
user=> (def to-english (partial clojure.pprint/cl-format nil
"~#(~#[~R~]~^ ~A.~)"))
#'user/to-english
user=> (to-english 1234567890)
"One billion, two hundred thirty-four million, five hundred sixty-seven
thousand, eight hundred ninety"
at https://clojuredocs.org/clojure.core/partial#example-542692cdc026201cdc326ceb. I know what partial does and I checked clojure.pprint/cl-format doc but still don't understand how it translates an integer to English words. Guess secret is hidden behind "~#(~#[~R~]~^ ~A.~)" but I didn't find a clue to read it.
Any help will be appreciated!
The doc mentions it, but one good resource is A Few FORMAT Recipes from Seibel's Practical Common Lisp.
Also, check §22.3 Formatted Output from the HyperSpec.
In Common Lisp:
CL-USER> (format t "~R" 10)
ten
~#(...~^...) is case conversion, where the # prefix means to capitalize (upcase only the first word). It contains an escape upward operation ~^, which in this context marks the end of what is case-converted. It also exits the current context when there are no more argument available.
~#[...] is conditional format: the inner format is applied on a value only if it is non nil.
The final ~A means that the function should be able to accept one more argument and print it.
In fact, your example looks like the one in §22.3.9.2:
If ~^ appears within a ~[ or ~( construct, then all the commands up to
the ~^ are properly selected or case-converted, the ~[ or ~(
processing is terminated, and the outward search continues for a ~{ or
~< construct to be terminated. For example:
(setq tellstr "~#(~#[~R~]~^ ~A!~)")
=> "~#(~#[~R~]~^ ~A!~)"
(format nil tellstr 23) => "Twenty-three!"
(format nil tellstr nil "losers") => " Losers!"
(format nil tellstr 23 "losers") => "Twenty-three losers!"

How to get to end of line but before start of comment in emacs C++ mode?

In practice I usually encounter below situation:
statement_line /*..some comments..*/
Sometimes I need to jump to just pass the end of the statement_line to: add some code, or delete the entire comment region.
Is there a keyboard shortcut to do it? (I know C-s ; Ret works for statement_line ending with a ";" but this is not all the case. e.g. if(...) /*...comments...*/)
Thanks in advance.
Try this code:
(defun end-of-statement ()
(interactive)
(beginning-of-line)
(if (comment-search-forward (line-end-position) t)
(re-search-backward "//\\|/\\*")
(end-of-line))
(skip-chars-backward " \t"))
I just wrote it, so it might require some tweaks, but it looks
fine at the moment.
Not a full answer to your question, but for the case where you want to remove the comment, you can use C-u M-; (aka comment-kill).
I have a command to bounce between the end of line and end of code. It works in most programming modes.
(defun end-of-line-code ()
(interactive "^")
(require 'newcomment)
(if comment-start-skip
(save-match-data
(let* ((bolpos (line-beginning-position)))
(end-of-line)
(if (comment-search-backward bolpos 'noerror)
(search-backward-regexp comment-start-skip bolpos 'noerror))
(skip-syntax-backward " " bolpos)))
(end-of-line)))
(defun end-of-line-or-code ()
"Move to EOL, or if already there, to EOL sans comments."
(interactive "^")
(if (eolp) ;; test me here
(end-of-line-code)
(end-of-line)))
(put 'end-of-line-or-code 'CUA 'move)
(defun jpk/prog-mode-hook ()
...
(local-set-key (kbd "C-e") 'end-of-line-or-code)
...
)
(add-hook 'prog-mode-hook 'jpk/prog-mode-hook)
I have a similar command that bounces between the beginning of line and beginning of text, which I can post if you're interested.

google-style file for C++ for emacs

I use the google-style file for emacs. It also looks like a good one to start learning some emacs lisp, not that long. However there is sth I am trying configure in that file, maybe some already did that before, for coding a class, I wrote,
namespace A
{
class A_A
{
public:
A_A();
private:
int a;
};
}
however public/private keywords are not at the right places, I did not understand why it places them like this out of the box, how can fix this? I am not good at emacs lisp yet unfortunately.
EDIT: I wanted to have sth like
namespace A
{
class A_A
{
public:
A_A();
private:
int a;
};
}
To get indent you like use such debug techniques:
(setq c-echo-syntactic-information-p t)
When you press TAB for indenting you will see something like:
syntax: ((inclass 33) (access-label 33))
As you can see access-label identify how indent priv/pub modifiers.
So change to what you want:
(defconst my-c-style
'(
(c-tab-always-indent . t)
(c-offsets-alist
. (
(access-label . /) ; XXXXXX LOOK HERE!!!!!!!
))
)
"My C Programming Style")
(defun my-c-mode-style-hook ()
(c-add-style "my" my-c-style t)
;; If set 'c-default-style' before 'c-add-style'
;; "Undefined style: my" error occured from 'c-get-style-variables'.
(setq c-default-style
'(
(java-mode . "my") (c-mode . "my") (csharp-mode . "my") (c++-mode . "my")
(other . "my")
))
)
(add-hook 'c-mode-common-hook 'my-c-mode-style-hook)
In example I remove half-level indent as inclass add one full indent (to get 1/2 of indent. For offset syntax read C-h v c-offsets-alist RET. For example:
If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/'
then a positive or negative multiple of `c-basic-offset' is added to
the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively.
Probably nowadays a good solution is given by the config file provided in Github by Google.
In the repository styleguide
there is the config file google-c-style.el
that, as described in the file,
;; Provides the google C/C++ coding style. You may wish to add
;; `google-set-c-style' to your `c-mode-common-hook' after requiring this
;; file. For example:
;;
;; (add-hook 'c-mode-common-hook 'google-set-c-style)
;;
;; If you want the RETURN key to go to the next line and space over
;; to the right place, add this to your .emacs right after the load-file:
;;
;; (add-hook 'c-mode-common-hook 'google-make-newline-indent)
The file is also distributed via MELT package system as google-c-style.el.

Regex Searching in Emacs

I'm trying to write some Elisp code to format a bunch of legacy files.
The idea is that if a file contains a section like "<meta name=\"keywords\" content=\"\\(.*?\\)\" />", then I want to insert a section that contains existing keywords. If that section is not found, I want to insert my own default keywords into the same section.
I've got the following function:
(defun get-keywords ()
(re-search-forward "<meta name=\"keywords\" content=\"\\(.*?\\)\" />")
(goto-char 0) ;The section I'm inserting will be at the beginning of the file
(or (march-string 1)
"Rubber duckies and cute ponies")) ;;or whatever the default keywords are
When the function fails to find its target, it returns Search failed: "[regex here]" and prevents the rest of evaluation. Is there a way to have it return the default string, and ignore the error?
Use the extra options for re-search-forward and structure it more like
(if (re-search-forward "<meta name=\"keywords\" content=\"\\(.*?\\)\" />" nil t)
(match-string 1)
"Rubber duckies and cute ponies")
Also, consider using the nifty "rx" macro to write your regex; it'll be more readable.
(rx "<meta name=\"keywords\" content=\""
(group (minimal-match (zero-or-more nonl)))
"\" />")

Emacs - override indentation

I have a multiply nested namespace:
namespace first {namespace second {namespace third {
// emacs indents three times
// I want to intend here
} } }
so emacs indents to the third position. However I just want a single indentation.
Is it possible to accomplish this effect simply?
Use an an absolute indentation column inside namespace:
(defconst my-cc-style
'("gnu"
(c-offsets-alist . ((innamespace . [4])))))
(c-add-style "my-cc-style" my-cc-style)
Then use c-set-style to use your own style.
Note that this only works in c++-mode, c-mode doesn't know 'innamespace'.
With c++-mode in Emacs 23, I had to do like this:
(defun my-c-setup ()
(c-set-offset 'innamespace [4]))
(add-hook 'c++-mode-hook 'my-c-setup)
To disable the indentation in namespaces altogether, change [4] to 0.
OK so this seems to work in both emacs 21 and 22 at least:
(defun followed-by (cases)
(cond ((null cases) nil)
((assq (car cases)
(cdr (memq c-syntactic-element c-syntactic-context))) t)
(t (followed-by (cdr cases)))))
(c-add-style "foo"
`(( other . personalizations )
(c-offsets-alist
( more . stuff )
(innamespace
. (lambda (x)
(if (followed-by
'(innamespace namespace-close)) 0 '+))))))
(The first solution doesn't support constructs like
namespace X { namespace Y {
class A;
namespace Z {
class B;
}
}}
)
If you simply want to input a literal tab, rather than changing emacs' indentation scheme, C-q TAB should work.
Unfortunately, I don't think emacs has a separate style for a namespace inside another namespace. If you go to the inner line and do C-c, C-o, you can change the topmost-intro style, and if you run customize-variable c-offsets-alist you can edit all the different indentation options emacs has, but one doesn't exist for your specific use case. You would need to write it manually in elisp
This works for me, inherit from cc-mode and replace the name space indenting to 0, aka, disable it's indent.
(defconst my-cc-style
'("cc-mode"
(c-offsets-alist . ((innamespace . [0])))))
(c-add-style "my-cc-mode" my-cc-style)