Hot answers tagged

33

The standard Emacs Lisp approach is regular expression matching: (string-match-p (regexp-quote needle) haystack)


20

A lot of things in Emacs operate on the current buffer. You need to change the current buffer and restore it when you're done. Use with-current-buffer for simple cases where you just need to do something in another buffer, and save-current-buffer for more complex cases where you need to navigate between several buffers. (defun buffer-string* (buffer) (...


16

Re-writing this answer gives another solution: (format-spec "%a %a %a %b %b %b" (format-spec-make ?a "a" ?b "b")) Edit: Another format-spec solution As Malabarba gives another solution in comments: (format-spec "%a %a %a %b %b %b" '((?a . "a") (?b . "b"))) Edit 2: Evaluation before substitution: Here are examples with evaluation before substitution: (...


15

[Your propertized string looks wrong - perhaps you copied it wrong. foo has only 3 characters, so it is impossible for it to be fontified on chars 0 to 4 (i.e., chars 0, 1, 2, and 3 - that's 4 chars). I use 3 instead of 4 in the example here.] (let* ((foo #("foo" 0 3 (fontified t face font-lock-function-name-face))) (start 0) (end (...


14

You're looking for prin1-to-string. Also, set print-escape-newlines to a true value to get the "\n" behavior you specified. I.e.: (let ((print-escape-newlines t)) (prin1-to-string "foo\nbar")) => "\"foo\\nbar\""


13

Magnar Sveen's string manipulation library s.el provides a variety of ways to do this. For example: (require 's) (s-format "${name} ${name} ${name}" 'aget '(("name" . "test"))) ;; ==> "test test test" Note that s-format can take any replacer function, but provides special handling for aget, elt, and gethash. So you could use a list of tokens and ...


12

Emacs 25 or newer You want C-M-u which runs the command backward-up-list. Move backward out of one level of parentheses. This command will also work on other parentheses-like expressions defined by the current language mode. If ESCAPE-STRINGS is non-nil (as it is interactively), move out of enclosing strings as well.


12

cl-search can do that (and also returns the index of the substring, if found): ELISP> (cl-search "f t" "df tj") 1 (#o1, #x1, ?\C-a) ELISP> (cl-search "ft" "df tj") nil


9

You may be misinterpreting what's going on. The insert function inserts its argument verbatim. The problem is that the string you've included in your program is not \documentclass but ␡ocumentclass where ␡ is ASCII character number 127 (which is unprintable). The string literal "\documentclass" represents the string ␡ocumentclass. Notice how two things ...


9

What's the idiomatic (or best) way to trim surrounding whitespace from a string? The built-in library subr-x.el has included the inline functions string-trim-left, string-trim-right, and string-trim since Emacs 24.4: (eval-when-compile (require 'subr-x)) (string-trim "\n\r\s\tfoo\n\r\s\t") ; => "foo" Since Emacs 26.1 these inline functions also accept ...


7

In Emacs Lisp, backslashes inside strings start escape sequences. For example, \n means a newline, and \a means a bell character. If a string contains an unknown escape sequence, an error is signalled. \A is an unknown escape sequence, and it seems like this leads to the rest of the init file not being loaded. You can either specify the path with forward ...


7

Yes, you can use a literal string that does not include the newline, so that the newline shows only for your code. Use \ to escape the newline, so that it is not included in the string: (setq foo "hello \ world") C-h v foo "hello world" One place where this is often used is in a doc string, where the literal string uses \\<...> or \\[...] ...


7

There is the string manipulation library s.el where trimming whitespace and newlines at the beginning and the end of a string is implemented as function s-trim. I cite that function here with its dependencies: (defun s-trim-left (s) "Remove whitespace at the beginning of S." (declare (pure t) (side-effect-free t)) (save-match-data (if (string-...


6

Ordinary Emacs Lisp strings are multi-line-capable. You can simply put newlines in them. Glancing at cl-heredoc, it sounds like what you are looking for is "raw" strings. There was a proposal to add these to elisp a while back, but unfortunately it was rejected. (I hope rather than expect it could be resurrected.) Nor does elisp have the reader ...


6

This is not exactly the purpose it was invented for, but seems to be useful: (require 'json) (json-encode-string "a neat\nstring\" with tab\t and feed \f, also vertical tab \v") "\"a neat\\nstring\\\" with tab\\t and feed \\f, also vertical tab \\u000b\""


6

Depending on your application, concat might be of use: (concat "live long " nil "and prosper") ;; => "live long and prosper" This works because concat acts on sequences, and nil is an empty list.


6

The easiest way is to use the Common Lisp compatibility layer: (require 'cl-seq) (cl-member "ap" '("foo" "apa" "bar") :test #'string-match) ==> ("apa" "bar") PS. This is not directly relevant to your question, but if you have a few minutes to kill, keep reading. ;-) Note that Emacs maintainers have traditionally eschewed CL (starting with the original ...


6

For occasional use, you can do with query-replace-regexp (C-M-%). Replace .\{32\} with \&^J. This means, replace all chunks of 32 characters, with the same thing followed by a newline. To type the newline into the replacemnt, use C-q C-j. If you want to apply this only to binary strings, use [01]\{32\} for matching. This will protect other text from ...


5

You need to double the backslash in a Lisp string: (replace-regexp-in-string ": \\w" #'upcase ": really") See the Elisp manual, node Syntax for Strings. And a char class has chars inside [], so put [:alpha:] inside []. (replace-regexp-in-string ": [[:alpha:]]" #'upcase ": really") See the Elisp manual, node Regexp Special.


5

Use (type-of EXPRESSION) to determine the type of an expression. In your case you are confusing the value being inserted into a buffer by a function with its return value. shell-command inserts the textual output of the command, but it returns the exit status of the command (which, of course, is an integer). The simplest solution to your problem is ...


4

A slightly less verbose version of the one suggested by kaushalmodi: (replace-regexp-in-string "..$" ":\\&" (format-time-string "%z"))


4

If you like to use elisp regexp, you can do the below. For example, it returns "-05:00" if (format-time-string "%z") returns "-0500". (replace-regexp-in-string "\\([-+][0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)" "\\1:\\2" (format-time-string "%z"))


4

I'm afraid Emacs is rubbish at string manipulation, which is pretty amazing since Emacs is a text editor. It may not be awesome, but personally feel this reads better than using with-temp-buffer. (let ((time (format-time-string "%z"))) (concat (substring time 0 3) ":" (substring time 3)))


4

The special form or is useful here. This macro returns the value of the first argument, unless it's nil in which case it returns the second. So, assuming the variable you want to check is foo, the following will do what you want: (format "%s.el" (or foo "")) In some ways it's better than a magic tag since it makes it clear what value should be returned if ...


4

Perhaps a shorter example, using cl library: (defun chop (string separator) (cl-loop with seplen = (length separator) with len = (length string) with start = 0 with next = seplen for end = (or (cl-search separator string :start2 next) len) for chunk = (substring string start end) collect ...


4

Here's some code for you. This is a slightly modified split-string. I've removed trim option for simplicity and added keep-sep option. The diff is basically 2 lines, so you could say that this code is idiomatic: (defun split-string (string &optional separators omit-nulls keep-sep) "Split STRING into substrings bounded by matches for SEPARATORS." (...


4

This might not be quite the answer you want, but use printenv -0 instead. This puts a NUL between each "line" of output, which in this case will be between each var=value pair: TMUX_PANE=%0^@test=foo bar baz ^@SHLVL=2 Parsing that will be much easier. Code: (split-string (shell-command-to-string "printenv -0") "\0" t)


4

The change is not in concat, but in yas-snippet-dirs. In earlier versions, yas-snippet-dirs could be either a single directory (a string) or a list of directories. The line (setq yas-snippet-dirs (concat user-emacs-directory "snippets")) is working, it's setting yas-snippet-dirs to the string "~/Dropbox/emacs/snippets". The error message byte-code: Wrong ...


4

This could be done with the next function (with or without narrowing): (defun get-nth-line (number) "Get line with NUMBER" (save-restriction (widen) (save-excursion (goto-line number) (buffer-substring-no-properties (line-beginning-position) (line-end-position))))) To get the first line execute ...


4

The function that comes to my mind at least would be cl-member using a string-match-p test. Here's a short example that shows how to use it: ELISP> (setq testing '("an apple" "a pear" "a grape")) ("an apple" "a pear" "a grape") ELISP> (cl-member "apple" testing) nil ELISP> (cl-member "an apple" testing) nil ELISP> (cl-member "an apple" testing ...


Only top voted, non community-wiki answers of a minimum length are eligible