al-file.el 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. ;;; al-file.el --- Additional functionality for working with files
  2. ;; Copyright © 2016–2017 Alex Kost
  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. ;;; Code:
  16. (require 'cl-lib)
  17. (defun al/file-if-exists (file)
  18. "Return FILE if it exists, or nil."
  19. (and (file-exists-p file) file))
  20. (defun al/existing-files (&rest file-names)
  21. "Return a list of existing files from FILE-NAMES."
  22. (delq nil (mapcar #'al/file-if-exists file-names)))
  23. (defun al/first-existing-file (&rest file-names)
  24. "Return the first existing file from FILE-NAMES."
  25. (cl-find-if #'file-exists-p file-names))
  26. (defmacro al/setq-file (&rest body)
  27. "Like `setq' but for setting to file name values.
  28. Check each file, and if it exists set the variable accordingly.
  29. Example:
  30. (al/setq-file v1 \"/foo\"
  31. v2 \"/tmp\")
  32. v2 will be set, while v1 will not."
  33. `(progn
  34. ,@(cl-loop for lst on body by #'cddr
  35. collect
  36. (let ((var (car lst))
  37. (file (cadr lst)))
  38. `(let ((file ,file))
  39. (when (file-exists-p file)
  40. (setq ,var file)))))))
  41. (defun al/file-regexp (&rest extensions)
  42. "Return regexp to match file name by EXTENSIONS."
  43. (rx-to-string `(and "." (or ,@extensions) string-end)
  44. 'no-group))
  45. (defun al/subdirs (directory)
  46. "Return list of DIRECTORY sub-directories."
  47. (cl-remove-if (lambda (file)
  48. (or (string-match-p (rx "/." string-end) file)
  49. (string-match-p (rx "/.." string-end) file)
  50. (not (file-directory-p file))))
  51. (directory-files directory 'full-name nil 'no-sort)))
  52. (defun al/add-to-auto-mode-alist (specs)
  53. "Add SPECS to `auto-mode-alist'.
  54. Each specification from SPECS list may have one of the following forms:
  55. (MODE-NAME . REGEXPS)
  56. (MODE-NAME REGEXP-OR-LIST t)
  57. REGEXP-OR-LIST is either a regexp (string), or a list of regexps.
  58. For the first form, specifications are added at the beginning of
  59. `auto-mode-alist'; for the second form it is added at the end."
  60. (cl-flet ((add (mode regexp &optional append?)
  61. (add-to-list 'auto-mode-alist (cons regexp mode) append?)))
  62. (dolist (spec specs)
  63. (pcase spec
  64. (`(,mode ,str-or-lst t)
  65. (if (stringp str-or-lst)
  66. (add mode str-or-lst t)
  67. (dolist (regexp str-or-lst)
  68. (add mode regexp t))))
  69. (`(,mode . ,regexps)
  70. (dolist (regexp regexps)
  71. (add mode regexp)))))))
  72. (provide 'al-file)
  73. ;;; al-file.el ends here