projects/guix·blob python-team · refs

105 lines · 3.9 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2021 Xinglu Chen <[email protected]>
3;;; Copyright © 2021 Andrew Tropin <[email protected]>
4;;;
5;;; This file is part of GNU Guix.
6;;;
7;;; GNU Guix is free software; you can redistribute it and/or modify it
8;;; under the terms of the GNU General Public License as published by
9;;; the Free Software Foundation; either version 3 of the License, or (at
10;;; your option) any later version.
11;;;
12;;; GNU Guix is distributed in the hope that it will be useful, but
13;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20(define-module (gnu home services utils)
21 #:use-module (ice-9 string-fun)
22 #:use-module (srfi srfi-1)
23 #:use-module (srfi srfi-26)
24
25 #:export (maybe-object->string
26 object->snake-case-string
27 object->camel-case-string
28 list->human-readable-list))
29
30(define (maybe-object->string object)
31 "Like @code{object->string} but don't do anything if OBJECT already is
32a string."
33 (if (string? object)
34 object
35 (object->string object)))
36
37;; Snake case: <https://en.wikipedia.org/wiki/Snake_case>
38(define* (object->snake-case-string object #:optional (style 'lower))
39 "Convert the object OBJECT to the equivalent string in ``snake
40case''. STYLE can be three `@code{lower}', `@code{upper}', or
41`@code{capitalize}', defaults to `@code{lower}'.
42
43@example
44(object->snake-case-string 'variable-name 'upper)
45@result{} \"VARIABLE_NAME\" @end example"
46 (if (not (member style '(lower upper capitalize)))
47 (error 'invalid-style (format #f "~a is not a valid style" style))
48 (let ((stringified (maybe-object->string object)))
49 (string-replace-substring
50 (cond
51 ((equal? style 'lower) stringified)
52 ((equal? style 'upper) (string-upcase stringified))
53 (else (string-capitalize stringified)))
54 "-" "_"))))
55
56(define* (object->camel-case-string object #:optional (style 'lower))
57 "Convert the object OBJECT to the equivalent string in ``camel case''.
58STYLE can be three `@code{lower}', `@code{upper}', defaults to
59`@code{lower}'.
60
61@example
62(object->camel-case-string 'variable-name 'upper)
63@result{} \"VariableName\"
64@end example"
65 (if (not (member style '(lower upper)))
66 (error 'invalid-style (format #f "~a is not a valid style" style))
67 (let ((stringified (maybe-object->string object)))
68 (cond
69 ((eq? style 'upper)
70 (string-concatenate
71 (map string-capitalize
72 (string-split stringified (cut eqv? <> #\-)))))
73 ((eq? style 'lower)
74 (let ((splitted-string (string-split stringified (cut eqv? <> #\-))))
75 (string-concatenate
76 (cons (first splitted-string)
77 (map string-capitalize
78 (cdr splitted-string))))))))))
79
80(define* (list->human-readable-list lst
81 #:key
82 (cumulative? #f)
83 (proc identity))
84 "Turn a list LST into a sequence of terms readable by humans.
85If CUMULATIVE? is @code{#t}, use ``and'', otherwise use ``or'' before
86the last term.
87
88PROC is a procedure to apply to each of the elements of a list before
89turning them into a single human readable string.
90
91@example
92(list->human-readable-list '(1 4 9) #:cumulative? #t #:proc sqrt)
93@result{} \"1, 2, and 3\"
94@end example
95
96yields:"
97 (let* ((word (if cumulative? "and " "or "))
98 (init (append (drop-right lst 1))))
99 (format #f "~a" (string-append
100 (string-join
101 (map (compose maybe-object->string proc) init)
102 ", " 'suffix)
103 word
104 (maybe-object->string (proc (last lst)))))))
105