emacs: Use prompt for packages instead popup for edit action.
[jackhill/guix/guix.git] / emacs / guix-utils.el
index 68cad88..78ea354 100644 (file)
@@ -163,6 +163,18 @@ This function is similar to `shell-quote-argument', but less strict."
   (let ((args (mapcar #'guix-shell-quote-argument args)))
     (guix-concat-strings (cons "guix" args) " ")))
 
+(defun guix-copy-as-kill (string &optional no-message?)
+  "Put STRING into `kill-ring'.
+If NO-MESSAGE? is non-nil, do not display a message about it."
+  (kill-new string)
+  (unless no-message?
+    (message "'%s' has been added to kill ring." string)))
+
+(defun guix-copy-command-as-kill (args &optional no-message?)
+  "Put 'guix ARGS ...' string into `kill-ring'.
+See also `guix-copy-as-kill'."
+  (guix-copy-as-kill (guix-command-string args) no-message?))
+
 (defun guix-completing-read-multiple (prompt table &optional predicate
                                       require-match initial-input
                                       hist def inherit-input-method)
@@ -181,14 +193,6 @@ Return time value."
   (require 'org)
   (org-read-date nil t nil prompt))
 
-(defun guix-get-key-val (alist &rest keys)
-  "Return value from ALIST by KEYS.
-ALIST is alist of alists of alists ... which can be consecutively
-accessed with KEYS."
-  (let ((val alist))
-    (dolist (key keys val)
-      (setq val (cdr (assq key val))))))
-
 (defun guix-find-file (file)
   "Find FILE if it exists."
   (if (file-exists-p file)
@@ -203,6 +207,33 @@ accessed with KEYS."
      (while (re-search-forward ,regexp nil t)
        ,@body)))
 
+(defun guix-any (pred lst)
+  "Test whether any element from LST satisfies PRED.
+If so, return the return value from the successful PRED call.
+Return nil otherwise."
+  (when lst
+    (or (funcall pred (car lst))
+        (guix-any pred (cdr lst)))))
+
+\f
+;;; Alist accessors
+
+(defmacro guix-define-alist-accessor (name assoc-fun)
+  "Define NAME function to access alist values using ASSOC-FUN."
+  `(defun ,name (alist &rest keys)
+     ,(format "Return value from ALIST by KEYS using `%s'.
+ALIST is alist of alists of alists ... which can be consecutively
+accessed with KEYS."
+              assoc-fun)
+     (if (or (null alist) (null keys))
+         alist
+       (apply #',name
+              (cdr (,assoc-fun (car keys) alist))
+              (cdr keys)))))
+
+(guix-define-alist-accessor guix-assq-value assq)
+(guix-define-alist-accessor guix-assoc-value assoc)
+
 \f
 ;;; Diff
 
@@ -242,6 +273,27 @@ See `defun' for the meaning of arguments."
               (mapconcat #'symbol-name arglist " ")
               docstring)))
 
+(defmacro guix-memoized-defalias (symbol definition &optional docstring)
+  "Set SYMBOL's function definition to memoized version of DEFINITION."
+  (declare (doc-string 3) (indent 1))
+  `(defalias ',symbol
+     (guix-memoize #',definition)
+     ,(or docstring
+          (format "Memoized version of `%S'." definition))))
+
+(defvar guix-memoized-font-lock-keywords
+  (eval-when-compile
+    `((,(rx "("
+            (group "guix-memoized-" (or "defun" "defalias"))
+            symbol-end
+            (zero-or-more blank)
+            (zero-or-one
+             (group (one-or-more (or (syntax word) (syntax symbol))))))
+       (1 font-lock-keyword-face)
+       (2 font-lock-function-name-face nil t)))))
+
+(font-lock-add-keywords 'emacs-lisp-mode guix-memoized-font-lock-keywords)
+
 (provide 'guix-utils)
 
 ;;; guix-utils.el ends here