0

An Unique Projectile Completion

 1 year ago
source link: http://francismurillo.github.io/2016-08-02-An-Unique-Projectile-Completion/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

An Unique Projectile Completion

I cannot live without projectile and probably helm and projectile-find-files is my bread-and-butter command. But they say, familiarity breeds contempt and once you been using it so much; you want some customization. But which part? For my contempt, I really just want to change how the helm-completion buffer displays the options.

What I really want is rather to display the filename in the front and display the file path in reverse order since my eyes naturally scan from left to right. And so if you want proof of how this looks like to me, I used the projectile-find-files on my emacs directory and this is what it looks like with just helm.

Helm Completion

After some hacking and discussion, this is what I settled on.

Customized Completion

So if you think this is weird or offensive, feel free to do something more meaningful in your life. But if you are curious, keep reading.

Or if you just want to know the code, here it is for your consumption.

(require 'dash)
(require 's)
(require 'f)

(defun fn/custom-helm-completion (prompt choices)
  "Just a custom helm completion for projection"
  (lexical-let*
      ((fn-separator "..")
       (fn-notation
        (lambda (path)
          (lexical-let ((fn-pieces (f-split path)))
            (string-join (reverse fn-pieces) fn-separator))))
       (relative-parent-path
        (lambda (path relative-path)
          (lexical-let
              ((split-path (f-split path))
               (split-relative-path (f-split relative-path)))
            (string-join
             (-drop-last (length split-relative-path) split-path)
             (f-path-separator)))))

       (as-pair (lambda (ish)
                  (if (listp ish)
                      ish (cons ish ish))))
       (swap-pair (lambda (pair)
                    (cons (cdr pair) (car pair))))
       (map-car (lambda (f pair)
                  (cons (funcall f (car pair))
                        (cdr pair))))

       (pair-as-label
        (lambda (pairs)
          (lexical-let* ((labels
                             (mapcar #'cdr pairs))
                         (label-lengths
                          (mapcar
                           (-compose
                            #'length
                            fn-notation)
                           labels))

                         (max-label-length
                          (apply #'max label-lengths))


                         (label-format
                          "%-s")

                         (description-format
                          "%-s")

                         (display-formatter
                          (lambda (name description)
                            (concat
                             (format label-format name)
                             "  |->  "
                             (format description-format description)
                             "  <-|"))))
            (lambda (pair)
              (lexical-let*
                  ((unique-path (car pair))
                   (full-path (cdr pair))
                   (parent-path
                    (funcall relative-parent-path
                             full-path
                             unique-path))

                   (display-name
                    (funcall fn-notation unique-path))
                   (display-description
                    (funcall fn-notation parent-path))

                   (display-label
                    (funcall display-formatter
                             display-name
                             display-description)))
                (cons display-label (cdr pair)))))))
       (refined-choices (f-uniquify-alist choices))
       (mapped-choices
        (mapcar (-compose
                 (funcall pair-as-label refined-choices)
                 swap-pair
                 as-pair)
                refined-choices)))
    (helm-comp-read prompt mapped-choices
                    :must-match 'confirm)))

(setq projectile-completion-system #'fn/custom-helm-completion)

I admit the code looks long, but I think it follows my functional and aesthetic instincts.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK