5

I have a buffer (not a file) containing data. I would like a function that lets the user select 1 or more lines of this buffer, e.g., by typing a regexp, and that returns the result as a list of selected lines.

The result would be equivalent to a grep run within helm except that, as a result of validating the selection, I don't want to visit the matching lines but get them in a list.

2
  • Does M-x helm-occur do what you want?
    – itsjeyd
    Feb 23, 2015 at 10:16
  • helm-occur is closer to what I need, thanks. Feb 24, 2015 at 12:44

3 Answers 3

3

If I understood correctly, in comes the regex, out comes the list of matched lines.

Here's a starter for this:

(helm-occur-init-source)
(defvar helm-source-lines (copy-alist helm-source-occur))
(setcdr (assoc 'action helm-source-lines) 'helm-lines-action)

(defun helm-lines-action (x)
  (with-current-buffer "*helm lines*"
    (cdr
     (split-string
      (buffer-substring-no-properties
       (point-min)
       (point-max))
      "\n"
      t))))

(defun helm-lines ()
  "Preconfigured helm for Occur."
  (interactive)
  (let ((bufs (list (buffer-name (current-buffer)))))
    (helm-attrset 'moccur-buffers bufs helm-source-lines)
    (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
    (helm-set-local-variable
     'helm-multi-occur-buffer-tick
     (cl-loop for b in bufs
        collect (buffer-chars-modified-tick (get-buffer b)))))
  (helm :sources 'helm-source-lines
        :buffer "*helm lines*"
        :truncate-lines t))

(setq test (helm-lines))

If you don't want line numbers, you can change a few keys:

(setq helm-source-lines
      (assq-delete-all 'filter-one-by-one helm-source-lines))
(setcdr (assoc 'get-line helm-source-lines)
        'buffer-substring)
1
  • 1
    Thank you for your answer. I got inspired by this code from helm-occur. Feb 24, 2015 at 12:44
1

helm-swoop solves exactly this problem. You can match strings (order insensitive), regexps, and even strings against distance (try out C-u M-x helm-swoop or C-6 M-x helm-swoop...)

demo

1
  • thank you very much, I like it. My question was not clear enough. I wasn't looking for an interactive function. I was looking for a library function that I can call from my own code. Apr 8, 2015 at 8:55
0

Here is what I came up with:

(defun my--helm-source-init ()
  (helm-candidate-buffer <buffer containing data>))

(defun my--helm-source-select-action (candidate)
  (loop for candidate in (helm-marked-candidates)
        ... I can do whatever I want with the selected lines here...

(defclass my--helm-source (helm-source-in-buffer)
  ((init :initform #'my--helm-source-init)
   (nohighlight :initform t)
   (action :initform (helm-make-actions
                      "Select" #'my--helm-source-select-action))
   (requires-pattern :initform 0)))

(defun my-search-with-helm ()
  (interactive)
  (helm
   :prompt "entry: "
   :sources (helm-make-source "Entries" 'my--helm-source)))
1
  • 1
    Given that this code isn't runnable as-is, I'm not sure it should be marked as accepted... Apr 7, 2015 at 19:52

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.