;;; helm-color.el --- colors and faces -*- lexical-binding: t -*-

;; Copyright (C) 2012 ~ 2020 Thierry Volpiatto <thierry.volpiatto@gmail.com>

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-elisp)

(declare-function list-colors-display "facemenu")

;;; Customize Face
;;
;;
(defun helm-custom-faces-init ()
  "Initialize buffer for `helm-source-customize-face'."
  (unless (helm-candidate-buffer)
    (save-selected-window
      (list-faces-display)
      (message nil))
    (helm-init-candidates-in-buffer
        'global
      (with-current-buffer (get-buffer "*Faces*")
        (buffer-substring
         (next-single-char-property-change (point-min) 'face)
         (point-max))))
    (kill-buffer "*Faces*")))

(defvar helm-source-customize-face
  (helm-build-in-buffer-source "Customize Face"
    :init 'helm-custom-faces-init
    :get-line 'buffer-substring
    :persistent-action (lambda (candidate)
                         (helm-elisp--persistent-help
                          (intern (car (split-string candidate)))
                          'helm-describe-face))
    :persistent-help "Describe face"
    :action '(("Customize"
               . (lambda (line)
                   (customize-face (intern (car (split-string line))))))
              ("Copy name"
               . (lambda (line)
                   (kill-new (car (split-string line " " t)))))))
  "See (info \"(emacs)Faces\")")

;;; Colors browser
;;
;;
(defun helm-colors-init ()
  (require 'facemenu)
  (unless (helm-candidate-buffer)
    (save-selected-window
      (list-colors-display)
      (message nil))
    (helm-init-candidates-in-buffer
        'global
      (with-current-buffer (get-buffer "*Colors*")
        (buffer-string)))
    (kill-buffer "*Colors*")))

(defun helm-color-insert-name (candidate)
  (with-helm-current-buffer
    (insert (helm-colors-get-name candidate))))

(defun helm-color-kill-name (candidate)
  (kill-new (helm-colors-get-name candidate)))

(defun helm-color-insert-rgb (candidate)
  (with-helm-current-buffer
    (insert (helm-colors-get-rgb candidate))))

(defun helm-color-kill-rgb (candidate)
  (kill-new (helm-colors-get-rgb candidate)))

(defun helm-color-run-insert-name ()
  "Insert name of color from `helm-source-colors'."
  (interactive)
  (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-name)))
(put 'helm-color-run-insert-name 'helm-only t)

(defun helm-color-run-kill-name ()
  "Kill name of color from `helm-source-colors'."
  (interactive)
  (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-name)))
(put 'helm-color-run-kill-name 'helm-only t)

(defun helm-color-run-insert-rgb ()
  "Insert RGB of color from `helm-source-colors'."
  (interactive)
  (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-rgb)))
(put 'helm-color-run-insert-rgb 'helm-only t)

(defun helm-color-run-kill-rgb ()
  "Kill RGB of color from `helm-source-colors'."
  (interactive)
  (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-rgb)))
(put 'helm-color-run-kill-rgb 'helm-only t)

(defvar helm-color-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map helm-map)
    (define-key map (kbd "C-c n") 'helm-color-run-insert-name)
    (define-key map (kbd "C-c N") 'helm-color-run-kill-name)
    (define-key map (kbd "C-c r") 'helm-color-run-insert-rgb)
    (define-key map (kbd "C-c R") 'helm-color-run-kill-rgb)
    map))

(defvar helm-source-colors
  (helm-build-in-buffer-source "Colors"
    :init 'helm-colors-init
    :get-line 'buffer-substring
    :keymap helm-color-map
    :persistent-help "Kill entry in RGB format."
    :persistent-action 'helm-color-kill-rgb
    :help-message 'helm-colors-help-message
    :action
    '(("Copy Name (C-c N)" . helm-color-kill-name)
      ("Copy RGB (C-c R)" . helm-color-kill-rgb)
      ("Insert Name (C-c n)" . helm-color-insert-name)
      ("Insert RGB (C-c r)" . helm-color-insert-rgb))))

(defun helm-colors-get-name (candidate)
  "Get color name."
  (replace-regexp-in-string
   " " ""
   (with-temp-buffer
     (insert (capitalize candidate))
     (goto-char (point-min))
     (search-forward-regexp "\\s-\\{2,\\}")
     (delete-region (point) (point-max))
     (buffer-string))))

(defun helm-colors-get-rgb (candidate)
  "Get color RGB."
  (replace-regexp-in-string
   " " ""
   (with-temp-buffer
     (insert (capitalize candidate))
     (goto-char (point-max))
     (search-backward-regexp "\\s-\\{2,\\}")
     (delete-region (point) (point-min))
     (buffer-string))))

;;;###autoload
(defun helm-colors ()
  "Preconfigured `helm' for color."
  (interactive)
  (helm :sources '(helm-source-colors helm-source-customize-face)
        :buffer "*helm colors*"))

(provide 'helm-color)

;;; helm-color.el ends here
