18

I just want to check if the current line is empty or not (if it contains only whitespace, then I still consider it empty).

Here is my initial version:

(defun strip-text-properties(txt)
  (set-text-properties 0 (length txt) nil txt)
  txt)

(defun is-current-line-empty ()
  (interactive)
  (setq c-line (thing-at-point 'line))
  (string-match "^\s*$" (strip-text-properties c-line)))

What is the easiest way to check if current line is empty?

3
  • 3
    In a lisp string, writing \s is equivalent to writing s. Perhaps you meant "^\\s*$".
    – YoungFrog
    Commented Sep 21, 2015 at 15:23
  • 3
    As a general comment, elisp will make more sense once you start thinking in terms of actions on buffers, as opposed to (as one tends to do in other languages) doing things with strings. Isolating and extracting a string in order to perform some test is likely to (a) be inefficient, and (b) dramatically reduce the number of tools at your disposal. Elisp is really good at doing things directly on the contents of buffers.
    – phils
    Commented Sep 22, 2015 at 0:10
  • 1
    @YoungFrog, also it should be \\s- instead of \\s. That hyphen is required in elisp regexp. Commented Jul 26, 2016 at 10:49

7 Answers 7

27

Would something like this be "easier"?

(defun current-line-empty-p ()
  (save-excursion
    (beginning-of-line)
    (looking-at-p "[[:blank:]]*$")))
3
  • Shouldn't space be blank? (to account for tabs)
    – ideasman42
    Commented Nov 15, 2020 at 10:04
  • @ideasman42 space accounts for all whitespace, not just space characters. That said, blank might be better here because it only accounts for horizontal whitespace rather than all whitespace. Reference: gnu.org/software/emacs/manual/html_node/elisp/…
    – eeowaa
    Commented Nov 17, 2020 at 20:06
  • :space: uses the syntax table, where :blank: is simply space or tab, which seems more accurate.
    – ideasman42
    Commented Nov 17, 2020 at 23:04
12

A simple method, close to what you have:

(defun current-line-empty-p ()
  (string-match-p "\\`\\s-*$" (thing-at-point 'line)))
6
  • I like this solution because it does not modify match-data.
    – nispio
    Commented Apr 25, 2016 at 16:08
  • 1
    You need to have \\s- instead of \s. Have you tried that solution? Commented Jul 26, 2016 at 10:51
  • 1
    still missing the hyphen? :) Commented Jul 26, 2016 at 13:53
  • 1
    It was early, and I hadn't completely woken up yet.
    – PythonNut
    Commented Jul 27, 2016 at 17:57
  • 1
    (thing-at-point 'line) seems to return nil in an empty buffer (or only whitespace in buffer) and then string-match-p returns an error as nil is not a string. So probably rather use (buffer-substring-no-properties (line-beginning-position) (line-end-position)).
    – Hubisan
    Commented Jun 9, 2023 at 10:01
5
(defun blank-line-p (&optional pos)
  "Returns `t' if line (optionally, line at POS) is empty or
composed only of whitespace."
  (save-excursion
    (goto-char (or pos (point)))
    (beginning-of-line)
    (= (point-at-eol)
       (progn (skip-syntax-forward " ") (point)))))
3

current-indentation gives you the column following leading blanks, which can be compared against the column at the end of line:

(defun blank-line-p ()
  (= (current-indentation)
     (- (line-end-position) (line-beginning-position))))
2
  • Am I missing something or this can be simplified to just (= (line-beginning-position) (line-end-position)) ?
    – Hi-Angel
    Commented Oct 5, 2023 at 8:00
  • Ah, nvm, I see, the answer is considering a line with whitespace to be empty as well. Nice answer!
    – Hi-Angel
    Commented Oct 5, 2023 at 8:10
2

Here is another simple solution for it, taken from comment-dwim-2 package

(defun is-empty-line-p ()
  (string-match-p "^[[:blank:]]*$"
        (buffer-substring (line-beginning-position)
                          (line-end-position))))
1

I suggest:

(defun blank-line-p ()
  (and (progn (skip-chars-backward " ") (bolp))
       (progn (skip-chars-forward " ") (eolp))))

(Note that the progns are in fact unnecessary because the skip functions never return nil). As Dan does in his answer, skip-syntax-* could also be used instead.

1
  • 3
    This does not identify a line containing only tabs as blank. skip-syntax-* is the right set of functions to use here. Commented Sep 21, 2015 at 21:48
1

This is a modification of what PythonNut answered which did not work for me (why?):

(defun current-line-blank ()
  (= 0 (string-match-p "^\\s-*$" (thing-at-point 'line))))

string-match-p returned the index of the next line whenever the current line wasn't blank. So I checked that the return value is 0.

3
  • The index of the next line? What do you mean exactly? (and welcome on emacs.SE!)
    – JeanPierre
    Commented Sep 10, 2019 at 18:41
  • @JeanPierre (thing-at-point 'line) includes the newline at the end of the line. If the current line is not blank, the regexp matches at that newline. The only time string-match-p returns nil here is on the last line of the buffer (and Dario, your version doesn't work on the last line if the buffer doesn't end with a newline). Commented Sep 10, 2019 at 20:12
  • A better fix would be to match the beginning of the string instead of matching the beginning of any line in the string. I've edited PythonNut's answer. Commented Sep 10, 2019 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.