build-farm-utils.el 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. ;;; build-farm-utils.el --- General utility functions -*- lexical-binding: t -*-
  2. ;; Copyright © 2015–2018 Alex Kost <alezost@gmail.com>
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;;
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Commentary:
  16. ;; This file provides auxiliary general code for build-farm package.
  17. ;;; Code:
  18. (require 'bui)
  19. (defvar build-farm-preferred-package-manager
  20. (if (file-exists-p "/gnu") 'guix 'nix)
  21. "Package manager that a user probably uses.
  22. This variable influence what build farm is used by default.
  23. It should be either `guix' or `nix' symbol.")
  24. (defun build-farm-hexify (value)
  25. "Convert VALUE to string and hexify it."
  26. (url-hexify-string (bui-get-string value)))
  27. (defun build-farm-number->bool (number)
  28. "Convert NUMBER to boolean value.
  29. Return nil, if NUMBER is 0; return t otherwise."
  30. (/= 0 number))
  31. (defmacro build-farm-while-null (&rest body)
  32. "Evaluate BODY until its result becomes non-nil."
  33. (declare (indent 0) (debug t))
  34. (let ((result-var (make-symbol "result")))
  35. `(let (,result-var)
  36. (while (null ,result-var)
  37. (setq ,result-var ,@body))
  38. ,result-var)))
  39. (defun build-farm-modify (object &rest modifiers)
  40. "Apply MODIFIERS to OBJECT.
  41. OBJECT is passed as an argument to the first function from
  42. MODIFIERS list, the returned result is passed to the second
  43. function from the list and so on. Return result of the last
  44. modifier call."
  45. (if (null modifiers)
  46. object
  47. (apply #'build-farm-modify
  48. (funcall (car modifiers) object)
  49. (cdr modifiers))))
  50. (defun build-farm-modify-objects (objects &rest modifiers)
  51. "Apply MODIFIERS to each object from a list of OBJECTS.
  52. See `build-farm-modify' for details."
  53. (mapcar (lambda (object)
  54. (apply #'build-farm-modify object modifiers))
  55. objects))
  56. ;;; Completing readers
  57. (defun build-farm-completing-read (prompt table &optional predicate
  58. require-match initial-input
  59. hist def inherit-input-method)
  60. "Same as `completing-read' but return nil instead of an empty string."
  61. (let ((res (completing-read prompt table predicate
  62. require-match initial-input
  63. hist def inherit-input-method)))
  64. (unless (string= "" res) res)))
  65. (defmacro build-farm-define-reader (name read-fun completions prompt
  66. &optional require-match default)
  67. "Define NAME function to read from minibuffer.
  68. READ-FUN may be `completing-read', `completing-read-multiple' or
  69. another function that takes COMPLETIONS, PROMPT, REQUIRE-MATCH, and
  70. DEFAULT."
  71. (declare (indent 1))
  72. `(defun ,name (&optional prompt initial-contents)
  73. (,read-fun (or prompt ,prompt)
  74. ,completions nil ,require-match
  75. initial-contents nil ,default)))
  76. (defmacro build-farm-define-readers (&rest args)
  77. "Define reader functions.
  78. ARGS should have a form [KEYWORD VALUE] ... The following
  79. keywords are available:
  80. - `completions-var' - variable used to get completions.
  81. - `completions-getter' - function used to get completions.
  82. - `require-match' - if the match is required (see
  83. `completing-read' for details); default is t.
  84. - `default' - default value.
  85. - `single-reader', `single-prompt' - name of a function to read
  86. a single value, and a prompt for it.
  87. - `multiple-reader', `multiple-prompt' - name of a function to
  88. read multiple values, and a prompt for it.
  89. - `multiple-separator' - if specified, another
  90. `<multiple-reader-name>-string' function returning a string
  91. of multiple values separated the specified separator will be
  92. defined."
  93. (bui-plist-let args
  94. ((completions-var :completions-var)
  95. (completions-getter :completions-getter)
  96. (require-match :require-match t)
  97. (default :default)
  98. (single-reader :single-reader)
  99. (single-prompt :single-prompt)
  100. (multiple-reader :multiple-reader)
  101. (multiple-prompt :multiple-prompt)
  102. (multiple-separator :multiple-separator))
  103. (let ((completions
  104. (cond ((and completions-var completions-getter)
  105. `(or ,completions-var
  106. (setq ,completions-var
  107. (funcall ',completions-getter))))
  108. (completions-var
  109. completions-var)
  110. (completions-getter
  111. `(funcall ',completions-getter)))))
  112. `(progn
  113. ,(when (and completions-var
  114. (not (boundp completions-var)))
  115. `(defvar ,completions-var nil))
  116. ,(when single-reader
  117. `(build-farm-define-reader ,single-reader
  118. build-farm-completing-read ,completions ,single-prompt
  119. ,require-match ,default))
  120. ,(when multiple-reader
  121. `(build-farm-define-reader ,multiple-reader
  122. completing-read-multiple ,completions ,multiple-prompt
  123. ,require-match ,default))
  124. ,(when (and multiple-reader multiple-separator)
  125. (let ((name (intern (concat (symbol-name multiple-reader)
  126. "-string"))))
  127. `(defun ,name (&optional prompt initial-contents)
  128. (mapconcat #'identity
  129. (,multiple-reader prompt initial-contents)
  130. ,multiple-separator))))))))
  131. (provide 'build-farm-utils)
  132. ;;; build-farm-utils.el ends here