-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsensetion-utils.el
126 lines (95 loc) · 3.61 KB
/
sensetion-utils.el
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
;;; sensetion.el --- -*- lexical-binding: t; -*-
(require 'cl-lib)
(defun sensetion--beginning-of-buffer ()
(goto-char (point-min)))
(defun sensetion--map-buffer-lines (f &optional buffer)
"Apply F to each line of BUFFER.
BUFFER defaults to current buffer if not provided. F must take as
argument the line number and the line string itself."
(with-current-buffer (or buffer (current-buffer))
(save-excursion
(sensetion--beginning-of-buffer)
(let (res
(counter 0))
(while (not (eobp))
(when-let ((line-res (funcall f counter (thing-at-point 'line))))
(setf res (cons line-res res)))
(cl-incf counter)
(forward-line 1))
res))))
(defun sensetion--map-file-lines (file f)
"Apply F to each line of FILE.
F must take as argument the line number and the line string
itself."
(with-temp-buffer
(insert-file-contents file)
(sensetion--map-buffer-lines f)))
(defmacro sensetion--with-inhibiting-read-only (&rest body)
(declare (debug t))
`(let ((inhibit-read-only t))
,@body))
(defalias 'sensetion-λ #'pcase-lambda)
(defmacro sensetion-is (&rest body)
(declare (debug ([&rest [¬ ":where"] form]
&optional
gate ":where"
&rest &or (&define name def-form)
(&define name lambda-list def-body))))
(seq-let (body wclauses)
(-split-when (lambda (c) (eq :where c)) body)
(let ((body
(-reduce-from
(lambda (bd cl)
(pcase cl
(`(,var ,val)
`((let ((,var ,val))
,@bd)))
(`(,name ,arglist . ,body)
`((cl-labels ((,name ,arglist ,@body))
,@bd)))))
body
wclauses)))
(cl-first body))))
(defun sensetion--goto-line (line &optional start-line)
(unless start-line
(sensetion--beginning-of-buffer))
(let ((sl (or start-line 0)))
(forward-line (- line sl))))
(defun sensetion--spaces->underlines (str)
(cl-substitute ?_
(string-to-char " ")
str
:test #'eq))
(defsubst sensetion--put-text-property-eol (property value &optional object)
(put-text-property (line-end-position) (1+ (line-end-position))
property value object))
(defsubst sensetion--get-text-property-eol (property &optional object)
(get-text-property (line-end-position) property object))
(defun sensetion--remove-nth (n list)
(cl-remove-if (lambda (_) t) list :start n :end (1+ n)))
(defun sensetion--parse-jsonlines (&optional reverse)
"Parse and return in a list the newline-delimited JSON values following point.
Advances point until end-of-buffer.
If REVERSE is non-nil, return the results in the proper order."
(let ((res))
(while (not (eobp))
(push (json-read) res)
;; skip whitespace
(skip-chars-forward "[:space:]"))
(if reverse
(reverse res)
res)))
(defsubst sensetion--property-value-position (position prop value limit &optional object)
"From POSITION, find position where PROP has VALUE.
If LIMIT is greater then POSITION, search forward, else search backward in OBJECT.
If PROP value at POSITION is already VALUE, then look for other
non-contiguous position where this is so."
(let* ((value-here (get-text-property position prop object))
(search-fn (if (> position limit)
#'previous-single-property-change
#'next-single-property-change))
(new-position (funcall search-fn position prop object limit)))
(if (and (equal value-here value) (not (eq new-position limit)))
(funcall search-fn new-position prop object limit)
new-position)))
(provide 'sensetion-utils)