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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
|
;;; flymake-ui.el --- A universal on-the-fly syntax checker -*- lexical-binding: t; -*-
;; Copyright (C) 2003-2017 Free Software Foundation, Inc.
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: Leo Liu <sdl.web@gmail.com>
;; Version: 0.3
;; Keywords: c languages tools
;; This file is part of GNU Emacs.
;; GNU Emacs 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 of the License, or
;; (at your option) any later version.
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Flymake is a minor Emacs mode performing on-the-fly syntax checks.xo
;;
;; This file contains the UI for displaying and interacting with the
;; results of such checks, as well as entry points for backends to
;; hook on to. Backends are sources of diagnostic info.
;;
;;; Code:
(eval-when-compile (require 'cl-lib))
(defgroup flymake nil
"Universal on-the-fly syntax checker."
:version "23.1"
:link '(custom-manual "(flymake) Top")
:group 'tools)
(defcustom flymake-error-bitmap '(exclamation-mark error)
"Bitmap (a symbol) used in the fringe for indicating errors.
The value may also be a list of two elements where the second
element specifies the face for the bitmap. For possible bitmap
symbols, see `fringe-bitmaps'. See also `flymake-warning-bitmap'.
The option `flymake-fringe-indicator-position' controls how and where
this is used."
:group 'flymake
:version "24.3"
:type '(choice (symbol :tag "Bitmap")
(list :tag "Bitmap and face"
(symbol :tag "Bitmap")
(face :tag "Face"))))
(defcustom flymake-warning-bitmap 'question-mark
"Bitmap (a symbol) used in the fringe for indicating warnings.
The value may also be a list of two elements where the second
element specifies the face for the bitmap. For possible bitmap
symbols, see `fringe-bitmaps'. See also `flymake-error-bitmap'.
The option `flymake-fringe-indicator-position' controls how and where
this is used."
:group 'flymake
:version "24.3"
:type '(choice (symbol :tag "Bitmap")
(list :tag "Bitmap and face"
(symbol :tag "Bitmap")
(face :tag "Face"))))
(defcustom flymake-fringe-indicator-position 'left-fringe
"The position to put flymake fringe indicator.
The value can be nil (do not use indicators), `left-fringe' or `right-fringe'.
See `flymake-error-bitmap' and `flymake-warning-bitmap'."
:group 'flymake
:version "24.3"
:type '(choice (const left-fringe)
(const right-fringe)
(const :tag "No fringe indicators" nil)))
(defcustom flymake-start-syntax-check-on-newline t
"Start syntax check if newline char was added/removed from the buffer."
:group 'flymake
:type 'boolean)
(defcustom flymake-no-changes-timeout 0.5
"Time to wait after last change before starting compilation."
:group 'flymake
:type 'number)
(defcustom flymake-gui-warnings-enabled t
"Enables/disables GUI warnings."
:group 'flymake
:type 'boolean)
(make-obsolete-variable 'flymake-gui-warnings-enabled
"it no longer has any effect." "26.1")
(defcustom flymake-start-syntax-check-on-find-file t
"Start syntax check on find file."
:group 'flymake
:type 'boolean)
(defcustom flymake-log-level -1
"Logging level, only messages with level lower or equal will be logged.
-1 = NONE, 0 = ERROR, 1 = WARNING, 2 = INFO, 3 = DEBUG"
:group 'flymake
:type 'integer)
(defcustom flymake-backends '()
"Ordered list of backends providing syntax check information for a buffer.
Value is an alist of conses (PREDICATE . CHECKER). Both PREDICATE
and CHECKER are functions called with a single argument, the
buffer in which `flymake-mode' was enabled. PREDICATE is expected
to (quickly) return t or nil if the buffer can be syntax checked
by CHECKER, which in can performs more morose operations,
possibly asynchronously."
:group 'flymake
:type 'alist)
(defvar-local flymake-timer nil
"Timer for starting syntax check.")
(defvar-local flymake-last-change-time nil
"Time of last buffer change.")
(defvar-local flymake-check-start-time nil
"Time at which syntax check was started.")
(defvar-local flymake-check-was-interrupted nil
"Non-nil if syntax check was killed by `flymake-compile'.")
(defvar-local flymake-err-info nil
"Sorted list of line numbers and lists of err info in the form (file, err-text).")
(defvar-local flymake-new-err-info nil
"Same as `flymake-err-info', effective when a syntax check is in progress.")
(defun flymake-log (level text &rest args)
"Log a message at level LEVEL.
If LEVEL is higher than `flymake-log-level', the message is
ignored. Otherwise, it is printed using `message'.
TEXT is a format control string, and the remaining arguments ARGS
are the string substitutions (see the function `format')."
(if (<= level flymake-log-level)
(let* ((msg (apply #'format-message text args)))
(message "%s" msg))))
(defun flymake-ins-after (list pos val)
"Insert VAL into LIST after position POS.
POS counts from zero."
(let ((tmp (copy-sequence list)))
(setcdr (nthcdr pos tmp) (cons val (nthcdr (1+ pos) tmp)))
tmp))
(defun flymake-set-at (list pos val)
"Set VAL at position POS in LIST.
POS counts from zero."
(let ((tmp (copy-sequence list)))
(setcar (nthcdr pos tmp) val)
tmp))
(defun flymake-er-make-er (line-no line-err-info-list)
(list line-no line-err-info-list))
(defun flymake-er-get-line (err-info)
(nth 0 err-info))
(defun flymake-er-get-line-err-info-list (err-info)
(nth 1 err-info))
(cl-defstruct (flymake-ler
(:constructor nil)
(:constructor flymake-ler-make-ler (file line type text &optional full-file)))
file line type text full-file)
(defun flymake-ler-set-file (line-err-info file)
(flymake-ler-make-ler file
(flymake-ler-line line-err-info)
(flymake-ler-type line-err-info)
(flymake-ler-text line-err-info)
(flymake-ler-full-file line-err-info)))
(defun flymake-ler-set-full-file (line-err-info full-file)
(flymake-ler-make-ler (flymake-ler-file line-err-info)
(flymake-ler-line line-err-info)
(flymake-ler-type line-err-info)
(flymake-ler-text line-err-info)
full-file))
(defun flymake-ler-set-line (line-err-info line)
(flymake-ler-make-ler (flymake-ler-file line-err-info)
line
(flymake-ler-type line-err-info)
(flymake-ler-text line-err-info)
(flymake-ler-full-file line-err-info)))
(defun flymake-get-line-err-count (line-err-info-list type)
"Return number of errors of specified TYPE.
Value of TYPE is either \"e\" or \"w\"."
(let* ((idx 0)
(count (length line-err-info-list))
(err-count 0))
(while (< idx count)
(when (equal type (flymake-ler-type (nth idx line-err-info-list)))
(setq err-count (1+ err-count)))
(setq idx (1+ idx)))
err-count))
(defun flymake-get-err-count (err-info-list type)
"Return number of errors of specified TYPE for ERR-INFO-LIST."
(let* ((idx 0)
(count (length err-info-list))
(err-count 0))
(while (< idx count)
(setq err-count (+ err-count (flymake-get-line-err-count (nth 1 (nth idx err-info-list)) type)))
(setq idx (1+ idx)))
err-count))
(defun flymake-highlight-err-lines (err-info-list)
"Highlight error lines in BUFFER using info from ERR-INFO-LIST."
(save-excursion
(dolist (err err-info-list)
(flymake-highlight-line (car err) (nth 1 err)))))
(defun flymake-overlay-p (ov)
"Determine whether overlay OV was created by flymake."
(and (overlayp ov) (overlay-get ov 'flymake-overlay)))
(defun flymake-make-overlay (beg end tooltip-text face bitmap)
"Allocate a flymake overlay in range BEG and END."
(when (not (flymake-region-has-flymake-overlays beg end))
(let ((ov (make-overlay beg end nil t))
(fringe (and flymake-fringe-indicator-position
(propertize "!" 'display
(cons flymake-fringe-indicator-position
(if (listp bitmap)
bitmap
(list bitmap)))))))
(overlay-put ov 'face face)
(overlay-put ov 'help-echo tooltip-text)
(overlay-put ov 'flymake-overlay t)
(overlay-put ov 'priority 100)
(overlay-put ov 'evaporate t)
(overlay-put ov 'before-string fringe)
;;+(flymake-log 3 "created overlay %s" ov)
ov)
(flymake-log 3 "created an overlay at (%d-%d)" beg end)))
(defun flymake-delete-own-overlays ()
"Delete all flymake overlays in BUFFER."
(dolist (ol (overlays-in (point-min) (point-max)))
(when (flymake-overlay-p ol)
(delete-overlay ol)
;;+(flymake-log 3 "deleted overlay %s" ol)
)))
(defun flymake-region-has-flymake-overlays (beg end)
"Check if region specified by BEG and END has overlay.
Return t if it has at least one flymake overlay, nil if no overlay."
(let ((ov (overlays-in beg end))
(has-flymake-overlays nil))
(while (consp ov)
(when (flymake-overlay-p (car ov))
(setq has-flymake-overlays t))
(setq ov (cdr ov)))
has-flymake-overlays))
(defface flymake-errline
'((((supports :underline (:style wave)))
:underline (:style wave :color "Red1"))
(t
:inherit error))
"Face used for marking error lines."
:version "24.4"
:group 'flymake)
(defface flymake-warnline
'((((supports :underline (:style wave)))
:underline (:style wave :color "DarkOrange"))
(t
:inherit warning))
"Face used for marking warning lines."
:version "24.4"
:group 'flymake)
(defun flymake-highlight-line (line-no line-err-info-list)
"Highlight line LINE-NO in current buffer.
Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting."
(goto-char (point-min))
(forward-line (1- line-no))
(pcase-let* ((beg (progn (back-to-indentation) (point)))
(end (progn
(end-of-line)
(skip-chars-backward " \t\f\t\n" beg)
(if (eq (point) beg)
(line-beginning-position 2)
(point))))
(tooltip-text (mapconcat #'flymake-ler-text line-err-info-list "\n"))
(`(,face ,bitmap)
(if (> (flymake-get-line-err-count line-err-info-list "e") 0)
(list 'flymake-errline flymake-error-bitmap)
(list 'flymake-warnline flymake-warning-bitmap))))
(flymake-make-overlay beg end tooltip-text face bitmap)))
(defun flymake-find-err-info (err-info-list line-no)
"Find (line-err-info-list pos) for specified LINE-NO."
(if err-info-list
(let* ((line-err-info-list nil)
(pos 0)
(count (length err-info-list)))
(while (and (< pos count) (< (car (nth pos err-info-list)) line-no))
(setq pos (1+ pos)))
(when (and (< pos count) (equal (car (nth pos err-info-list)) line-no))
(setq line-err-info-list (flymake-er-get-line-err-info-list (nth pos err-info-list))))
(list line-err-info-list pos))
'(nil 0)))
(defun flymake-line-err-info-is-less-or-equal (line-one line-two)
(or (string< (flymake-ler-type line-one) (flymake-ler-type line-two))
(and (string= (flymake-ler-type line-one) (flymake-ler-type line-two))
(not (flymake-ler-file line-one)) (flymake-ler-file line-two))
(and (string= (flymake-ler-type line-one) (flymake-ler-type line-two))
(or (and (flymake-ler-file line-one) (flymake-ler-file line-two))
(and (not (flymake-ler-file line-one)) (not (flymake-ler-file line-two)))))))
(defun flymake-add-line-err-info (line-err-info-list line-err-info)
"Update LINE-ERR-INFO-LIST with the error LINE-ERR-INFO.
For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'.
The new element is inserted in the proper position, according to
the predicate `flymake-line-err-info-is-less-or-equal'.
The updated value of LINE-ERR-INFO-LIST is returned."
(if (not line-err-info-list)
(list line-err-info)
(let* ((count (length line-err-info-list))
(idx 0))
(while (and (< idx count) (flymake-line-err-info-is-less-or-equal (nth idx line-err-info-list) line-err-info))
(setq idx (1+ idx)))
(cond ((equal 0 idx) (setq line-err-info-list (cons line-err-info line-err-info-list)))
(t (setq line-err-info-list (flymake-ins-after line-err-info-list (1- idx) line-err-info))))
line-err-info-list)))
(defun flymake-add-err-info (err-info-list line-err-info)
"Update ERR-INFO-LIST with the error LINE-ERR-INFO, preserving sort order.
Returns the updated value of ERR-INFO-LIST.
For the format of ERR-INFO-LIST, see `flymake-err-info'.
For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'."
(let* ((line-no (if (flymake-ler-file line-err-info) 1 (flymake-ler-line line-err-info)))
(info-and-pos (flymake-find-err-info err-info-list line-no))
(exists (car info-and-pos))
(pos (nth 1 info-and-pos))
(line-err-info-list nil)
(err-info nil))
(if exists
(setq line-err-info-list (flymake-er-get-line-err-info-list (car (nthcdr pos err-info-list)))))
(setq line-err-info-list (flymake-add-line-err-info line-err-info-list line-err-info))
(setq err-info (flymake-er-make-er line-no line-err-info-list))
(cond (exists (setq err-info-list (flymake-set-at err-info-list pos err-info)))
((equal 0 pos) (setq err-info-list (cons err-info err-info-list)))
(t (setq err-info-list (flymake-ins-after err-info-list (1- pos) err-info))))
err-info-list))
(defvar-local flymake-is-running nil
"If t, flymake syntax check process is running for the current buffer.")
(defun flymake-on-timer-event (buffer)
"Start a syntax check for buffer BUFFER if necessary."
(when (buffer-live-p buffer)
(with-current-buffer buffer
(when (and (not flymake-is-running)
flymake-last-change-time
(> (- (float-time) flymake-last-change-time)
flymake-no-changes-timeout))
(setq flymake-last-change-time nil)
(flymake-log 3 "starting syntax check as more than 1 second passed since last change")
(flymake--start-syntax-check)))))
(define-obsolete-function-alias 'flymake-display-err-menu-for-current-line
'flymake-popup-current-error-menu "24.4")
(defun flymake-popup-current-error-menu (&optional event)
"Pop up a menu with errors/warnings for current line."
(interactive (list last-nonmenu-event))
(let* ((line-no (line-number-at-pos))
(errors (or (car (flymake-find-err-info flymake-err-info line-no))
(user-error "No errors for current line")))
(menu (mapcar (lambda (x)
(if (flymake-ler-file x)
(cons (format "%s - %s(%d)"
(flymake-ler-text x)
(flymake-ler-file x)
(flymake-ler-line x))
x)
(list (flymake-ler-text x))))
errors))
(event (if (mouse-event-p event)
event
(list 'mouse-1 (posn-at-point))))
(title (format "Line %d: %d error(s), %d warning(s)"
line-no
(flymake-get-line-err-count errors "e")
(flymake-get-line-err-count errors "w")))
(choice (x-popup-menu event (list title (cons "" menu)))))
(flymake-log 3 "choice=%s" choice)
(when choice
(flymake-goto-file-and-line (flymake-ler-full-file choice)
(flymake-ler-line choice)))))
(defun flymake-goto-file-and-line (file line)
"Try to get buffer for FILE and goto line LINE in it."
(if (not (file-exists-p file))
(flymake-log 1 "File %s does not exist" file)
(find-file file)
(goto-char (point-min))
(forward-line (1- line))))
;; flymake minor mode declarations
(defvar-local flymake-mode-line nil)
(defvar-local flymake-mode-line-e-w nil)
(defvar-local flymake-mode-line-status nil)
(defun flymake-report-status (e-w &optional status)
"Show status in mode line."
(when e-w
(setq flymake-mode-line-e-w e-w))
(when status
(setq flymake-mode-line-status status))
(let* ((mode-line " Flymake"))
(when (> (length flymake-mode-line-e-w) 0)
(setq mode-line (concat mode-line ":" flymake-mode-line-e-w)))
(setq mode-line (concat mode-line flymake-mode-line-status))
(setq flymake-mode-line mode-line)
(force-mode-line-update)))
;; Nothing in flymake uses this at all any more, so this is just for
;; third-party compatibility.
(define-obsolete-function-alias 'flymake-display-warning 'message-box "26.1")
(defun flymake-report-fatal-status (status warning)
"Display a warning and switch flymake mode off."
;; This first message was always shown by default, and flymake-log
;; does nothing by default, hence the use of message.
;; Another option is display-warning.
(if (< flymake-log-level 0)
(message "Flymake: %s. Flymake will be switched OFF" warning))
(flymake-mode 0)
(flymake-log 0 "switched OFF Flymake mode for buffer %s due to fatal status %s, warning %s"
(buffer-name) status warning))
(defvar-local flymake--backend nil
"The currently active backend selected by `flymake-mode'")
(defun flymake--can-syntax-check-buffer (buffer)
(let ((all flymake-backends)
(candidate))
(catch 'done
(while (setq candidate (pop all))
(when (with-current-buffer buffer (funcall (car candidate)))
(throw 'done (cdr candidate)))))))
(defun flymake--start-syntax-check ()
(funcall flymake--backend))
;;;###autoload
(define-minor-mode flymake-mode nil
:group 'flymake :lighter flymake-mode-line
(cond
;; Turning the mode ON.
(flymake-mode
(let* ((backend (flymake--can-syntax-check-buffer (current-buffer))))
(cond
((not backend)
(flymake-log 2 "flymake cannot check syntax in buffer %s" (buffer-name)))
(t
(setq flymake--backend backend)
(add-hook 'after-change-functions 'flymake-after-change-function nil t)
(add-hook 'after-save-hook 'flymake-after-save-hook nil t)
(add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t)
;;+(add-hook 'find-file-hook 'flymake-find-file-hook)
(flymake-report-status "" "")
(setq flymake-timer
(run-at-time nil 1 'flymake-on-timer-event (current-buffer)))
(when (and flymake-start-syntax-check-on-find-file
;; Since we write temp files in current dir, there's no point
;; trying if the directory is read-only (bug#8954).
(file-writable-p (file-name-directory buffer-file-name)))
(with-demoted-errors
(flymake--start-syntax-check)))))
)
)
;; Turning the mode OFF.
(t
(setq flymake--backend nil)
(remove-hook 'after-change-functions 'flymake-after-change-function t)
(remove-hook 'after-save-hook 'flymake-after-save-hook t)
(remove-hook 'kill-buffer-hook 'flymake-kill-buffer-hook t)
;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t)
(flymake-delete-own-overlays)
(when flymake-timer
(cancel-timer flymake-timer)
(setq flymake-timer nil))
(setq flymake-is-running nil))))
;; disabling flymake-mode is safe, enabling - not necessarily so
(put 'flymake-mode 'safe-local-variable 'null)
;;;###autoload
(defun flymake-mode-on ()
"Turn flymake mode on."
(flymake-mode 1)
(flymake-log 1 "flymake mode turned ON for buffer %s" (buffer-name)))
;;;###autoload
(defun flymake-mode-off ()
"Turn flymake mode off."
(flymake-mode 0)
(flymake-log 1 "flymake mode turned OFF for buffer %s" (buffer-name)))
(defun flymake-after-change-function (start stop _len)
"Start syntax check for current buffer if it isn't already running."
;;+(flymake-log 0 "setting change time to %s" (float-time))
(let((new-text (buffer-substring start stop)))
(when (and flymake-start-syntax-check-on-newline (equal new-text "\n"))
(flymake-log 3 "starting syntax check as new-line has been seen")
(flymake--start-syntax-check))
(setq flymake-last-change-time (float-time))))
(defun flymake-after-save-hook ()
(if (local-variable-p 'flymake-mode (current-buffer)) ; (???) other way to determine whether flymake is active in buffer being saved?
(progn
(flymake-log 3 "starting syntax check as buffer was saved")
(flymake--start-syntax-check)))) ; no more mode 3. cannot start check if mode 3 (to temp copies) is active - (???)
(defun flymake-kill-buffer-hook ()
(when flymake-timer
(cancel-timer flymake-timer)
(setq flymake-timer nil)))
;;;###autoload
(defun flymake-find-file-hook ()
;;+(when flymake-start-syntax-check-on-find-file
;;+ (flymake-log 3 "starting syntax check on file open")
;;+ (flymake--start-syntax-check)
;;+)
(when (and (not (local-variable-p 'flymake-mode (current-buffer)))
(flymake--can-syntax-check-buffer (current-buffer)))
(flymake-mode)
(flymake-log 3 "automatically turned ON flymake mode")))
(defun flymake-get-first-err-line-no (err-info-list)
"Return first line with error."
(when err-info-list
(flymake-er-get-line (car err-info-list))))
(defun flymake-get-last-err-line-no (err-info-list)
"Return last line with error."
(when err-info-list
(flymake-er-get-line (nth (1- (length err-info-list)) err-info-list))))
(defun flymake-get-next-err-line-no (err-info-list line-no)
"Return next line with error."
(when err-info-list
(let* ((count (length err-info-list))
(idx 0))
(while (and (< idx count) (>= line-no (flymake-er-get-line (nth idx err-info-list))))
(setq idx (1+ idx)))
(if (< idx count)
(flymake-er-get-line (nth idx err-info-list))))))
(defun flymake-get-prev-err-line-no (err-info-list line-no)
"Return previous line with error."
(when err-info-list
(let* ((count (length err-info-list)))
(while (and (> count 0) (<= line-no (flymake-er-get-line (nth (1- count) err-info-list))))
(setq count (1- count)))
(if (> count 0)
(flymake-er-get-line (nth (1- count) err-info-list))))))
(defun flymake-skip-whitespace ()
"Move forward until non-whitespace is reached."
(while (looking-at "[ \t]")
(forward-char)))
(defun flymake-goto-line (line-no)
"Go to line LINE-NO, then skip whitespace."
(goto-char (point-min))
(forward-line (1- line-no))
(flymake-skip-whitespace))
(defun flymake-goto-next-error ()
"Go to next error in err ring."
(interactive)
(let ((line-no (flymake-get-next-err-line-no flymake-err-info (line-number-at-pos))))
(when (not line-no)
(setq line-no (flymake-get-first-err-line-no flymake-err-info))
(flymake-log 1 "passed end of file"))
(if line-no
(flymake-goto-line line-no)
(flymake-log 1 "no errors in current buffer"))))
(defun flymake-goto-prev-error ()
"Go to previous error in err ring."
(interactive)
(let ((line-no (flymake-get-prev-err-line-no flymake-err-info (line-number-at-pos))))
(when (not line-no)
(setq line-no (flymake-get-last-err-line-no flymake-err-info))
(flymake-log 1 "passed beginning of file"))
(if line-no
(flymake-goto-line line-no)
(flymake-log 1 "no errors in current buffer"))))
(defun flymake-patch-err-text (string)
(if (string-match "^[\n\t :0-9]*\\(.*\\)$" string)
(match-string 1 string)
string))
(provide 'flymake-ui)
;;; flymake-ui.el ends here
|