I am looking for a way to improve searching by repeating pattern. Let's say some program prints lots of log messages with the same pattern:

copying path '/nix/store/lqfjx7x6imy5a9xab1ff5nhg90v089rq-postgresql-12.8' from 'https://cache.nixos.org'...
copying path '/nix/store/i80hgssxz2710ysawck5k9im6ccbic89-postgresql-13.4' from 'https://cache.nixos.org'...
copying path '/nix/store/qnq00zsw837kiyhvi3jxcizw0gim5g6f-util-linux-2.36.2-bin' from 'https://cache.nixos.org'...
copying path '/nix/store/kr4w1cjjcy4ml7wpb5x6i8dbivdx36rh-postgresql-libpq-' from 'https://cache.nixos.org'...

Cursor is on a line starting with copying path and my goal is to jump to the nearest line above/below containing copying path; meanwhile neighbor line doesn't have matching pattern.

Such a function and shortcut would boost navigation performance across shell buffer. I hope the library I am interested in exists.

  • Doesn't isearch-forward or isearch-backward work for this? They are bound to C-s and C-r resp. and you can give it the pattern the first time. After that each C-s or C-r searches for the same pattern in the indicated direction. Although the description in the title and the description in the body of the question seem different to me. Maybe you can clarify by editing the question?
    – NickD
    Nov 6, 2021 at 6:20
  • 1
    Standard search forward/backward has no sense because it moves cursor just to next line, because pattern is found on closest hundreds of lines. I need to jump the border between lines where pattern matches and doesn't match. Nov 6, 2021 at 12:59
  • Ah, thanks for the explanation!
    – NickD
    Nov 6, 2021 at 13:02
  • 1
    Consider using M-x keep-lines, to just (at least temporarily) remove the lines that don't start that way. Use undo to restore them, if you need them later. Or work with a copy of the text, where you don't mind deleting the uninteresting lines.
    – Drew
    Nov 6, 2021 at 18:34

1 Answer 1


I am not sure how you would like this function to work exactly, but it sounds like you can achieve it with only a few lines of code, e.g. the following:

(defun my-jump-to-non-matching-line (arg)
  (interactive "P")
  (let ((regexp (if arg
                    (thing-at-point 'word t)
                  (read-string "Jump to first line not matching regexp: "))))
    (while (and (string-match regexp (thing-at-point 'line))
                (not (eobp)))

You can simply do M-x my-jump-to-non-matching-line and enter some (part of the repeating) pattern that is not contained in the line where you would like to jump to. By doing C-u M-x my-jump-to-non-matching-line, the function automatically uses the word under the cursor as pattern (in your example, for example, place the cursor on 'copying' and press C-u M-x my-jump-to-non-matching-line).

Of course, you can also create a keybinding for this command.

Finally, you can make a search-backward version by changing eobp to bobp and adding a -1 behind forward-line.

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.