-
Notifications
You must be signed in to change notification settings - Fork 20
/
verb-util.el
174 lines (145 loc) · 6.23 KB
/
verb-util.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
;;; verb-util.el --- Utilities for Verb -*- lexical-binding: t -*-
;; Copyright (C) 2024 Federico Tedin
;; Author: Federico Tedin <federicotedin@gmail.com>
;; Maintainer: Federico Tedin <federicotedin@gmail.com>
;; Homepage: https://github.com/federicotdn/verb
;; Keywords: tools
;; Package-Version: 2.16.0
;; Package-Requires: ((emacs "26.3"))
;; This file is NOT part of GNU Emacs.
;; verb is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; verb is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
;; License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with verb. If not, see http://www.gnu.org/licenses.
;;; Commentary:
;; General utility variables and functions for Verb.
;;; Code:
(defconst verb-util--log-buffer-name "*Verb Log*"
"Default name for log buffer.")
(defconst verb-util--log-levels '(D I W E)
"Log levels for the log buffer.
D = Debug.
I = Information.
W = Warning.
E = Error.")
(defface verb-util--log-debug '((t :inherit font-lock-constant-face))
"Face for highlighting D entries in the log buffer."
:group 'verb)
(defface verb-util--log-info '((t :inherit homoglyph))
"Face for highlighting I entries in the log buffer."
:group 'verb)
(defface verb-util--log-warning '((t :inherit warning))
"Face for highlighting W entries in the log buffer."
:group 'verb)
(defface verb-util--log-error '((t :inherit error))
"Face for highlighting E entries in the log buffer."
:group 'verb)
(defconst verb-util--http-header-parse-regexp
"^\\s-*\\([[:alnum:]_-]+\\)\\s-*:\\(.*\\)$"
"Regexp for parsing HTTP headers.")
(defconst verb-util--org-hyperlink-regexp
"\\[\\[\\(.+?\\)\\]\\(\\[.*?\\]\\)?\\]"
"Regexp for parsing Org mode hyperlinks.")
(define-derived-mode verb-util-log-mode special-mode "Verb[Log]"
"Major mode for displaying Verb logs.
Each line contains a short message representing an event that has been
logged:
The first part of each line is a number that represents what
request has generated this event (the number identifies the request).
If an event does not correspond to any request, \"-\" is used instead.
If the first part of the line is empty, then the event corresponds to
the same request from the previous line.
The second part of each line represents the level at which this event
has been logged, I for information, W for warnings and E for errors.
The third part of each line is the message itself.
If this buffer is killed, it will be created again when the next
message is logged. To turn off logging, set `verb-enable-log' to nil."
(font-lock-add-keywords
nil '(;; Request number, e.g. 10.
("^[[:digit:]-]+\\s-"
(0 'bold))
;; Log level D after request number.
("^[[:digit:]-]*\\s-+\\(D\\)"
(1 'verb-util--log-debug))
;; Log level I after request number.
("^[[:digit:]-]*\\s-+\\(I\\)"
(1 'verb-util--log-info))
;; Log level W after request number.
("^[[:digit:]-]*\\s-+\\(W\\)"
(1 'verb-util--log-warning))
;; Log level E after request number.
("^[[:digit:]-]*\\s-+\\(E\\)"
(1 'verb-util--log-error)))))
(defun verb-util--log (request level &rest args)
"Log a message in the *Verb Log* buffer.
REQUEST must be a number corresponding to an HTTP request made. LEVEL
must be a value in `verb-util--log-levels'. Use the remaining ARGS to call
`format', and then log the result in the log buffer.
If `verb-enable-log' is nil, do not log anything."
(setq request (if request (number-to-string request) "-"))
(unless (member level verb-util--log-levels)
(user-error "Invalid log level: \"%s\"" level))
(when (bound-and-true-p verb-enable-log) ; Var is defined in verb.el.
(with-current-buffer (get-buffer-create verb-util--log-buffer-name)
(unless (derived-mode-p 'verb-util-log-mode)
(verb-util-log-mode))
(let ((inhibit-read-only t)
(last "")
(msg (apply #'format args)))
(unless (= (buffer-size) 0)
(insert "\n"))
;; Get last logged request number.
(when (re-search-backward "^\\(-\\|[[:digit:]]+\\)\\s-"
nil t)
(setq last (match-string 1)))
(goto-char (point-max))
;; Log new message.
(insert (format "%-5s %s "
(if (string= last request)
(make-string (length request) ? )
request)
level)
msg)
;; If logged messaged contained newlines, add a blank line
;; to make things more readable.
(when (string-match-p "\n" msg)
(newline)))
(dolist (w (get-buffer-window-list (current-buffer) nil t))
(set-window-point w (point-max))))))
(defun verb-util-show-log ()
"Switch to the *Verb Log* buffer."
(interactive)
(switch-to-buffer (get-buffer-create verb-util--log-buffer-name)))
(defun verb-util--nonempty-string (s)
"Return S. If S is the empty string, return nil."
(if (string= s "")
nil
s))
(defun verb-util--string= (s1 s2)
"Return non-nil if strings S1 and S2 are equal, ignoring case."
(string= (downcase s1) (downcase s2)))
(defun verb-util--object-intervals (object)
"Call function `object-intervals' on OBJECT if possible.
Otherwise, or if calling the function returns nil, return a single
interval covering the whole object, with no properties."
;; TODO: Update once Verb depends on Emacs 28.1+.
(let ((default (list (list 0 (length object) nil))))
(if (fboundp 'object-intervals)
(or (funcall #'object-intervals object)
default)
default)))
(defun verb-util--remove-org-hyperlinks (s)
"Remove Org hyperlinks from string S and return the result.
All hyperlinks are replaced with the link they contain."
(replace-regexp-in-string verb-util--org-hyperlink-regexp
"\\1" s t))
(provide 'verb-util)
;;; verb-util.el ends here