1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
;;; acdw.el --- My Emacs extras -*- lexical-binding: t; -*-
;;; Code:
(defmacro defdir (name directory &optional docstring makedir)
"Define a variable and a function NAME expanding to DIRECTORY.
DOCSTRING is applied to the variable; its default is DIRECTORY's
path. If MAKEDIR is non-nil, the directory and its parents will
be created."
(declare (indent 2) (doc-string 3))
`(progn
(defvar ,name (expand-file-name ,directory)
,(concat (or docstring (format "%s" directory)) "\n"
"Defined by `defdir'."))
(defun ,name (file &optional mkdir)
,(concat "Expand FILE relative to variable `" (symbol-name name) "'.\n"
"If MKDIR is non-nil, parent directories are created.\n"
"Defined by `defdir'.")
(let ((file-name (expand-file-name
(convert-standard-filename file) ,name)))
(when mkdir
(make-directory (file-name-directory file-name) :parents))
file-name))
,(if makedir
`(make-directory ,directory :parents)
`(unless (file-exists-p ,directory)
(warn "Directory `%s' doesn't exist." ,directory)))))
(defun choose-executable (&rest programs)
"Return the first of PROGRAMS that exists in the system's $PATH.
Each of PROGRAMS can be a single string, or a list. If it's a list then its car
will be tested with `executable-find', and the entire list returned. This
enables passing arguments to a calling function."
(seq-find (lambda (x)
(executable-find (car (ensure-list x))))
programs))
(defun file-string (file)
"Return the contents of FILE as a string."
(with-current-buffer (find-file-noselect file)
(buffer-string)))
(defun unsmartify-region (begin end)
"Replace \"smart\" punctuation with \"dumb\" counterparts."
(interactive "*r")
(save-excursion
(goto-char begin)
(while (re-search-forward "[“”‘’–—]" end t)
(let ((replace (pcase (match-string 0)
((or "“" "”") "\"")
((or "‘" "’") "'")
("–" "--")
("—" "---"))))
(replace-match replace nil nil)))))
(defun ++concat (func strings)
"Concat STRINGS processed by FUNC.
Each of STRINGS can be a bare string or a list. Strings are
passed through as-is, but lists are passed to FUNC first as
arguments. Finally, all the resulting strings are `mapconcat'-ed
together.
As a special case, if `:separator' is the first of STRINGS, the
string following will be used as a separator. Otherwise, a
newline will be used."
(let (separator)
(when (eq (car strings) :separator)
(setq separator (cadr strings)
strings (cddr strings)))
(mapconcat (lambda (s)
(cond
((listp s) (apply func s))
((stringp s) s)
(t (user-error "Bad argument: %S" s))))
strings
(or separator "\n"))))
(defun format-concat (&rest strings)
"Concatenate formatted STRINGS.
Each of STRINGS can be a bare string or a list. Bare strings are passed as-is
to `mapconcat' for concatenation and separation. Lists, however, are passed to
`format' first.
If `:separator' is the first of STRINGS, the next string will be
used as a separator."
(++concat #'format strings))
(provide 'acdw)
;;; acdw.el ends here
|