├── .github
└── workflows
│ └── main.yml
├── .travis.yml
├── Cask
├── README.md
├── flycheck-posframe.el
└── screenshots
└── flycheck-posframe.png
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | push:
6 |
7 | jobs:
8 | check:
9 | runs-on: ubuntu-latest
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | emacs_version:
14 | - 26.1
15 | - 26.2
16 | - 26.3
17 | - 27.1
18 | - 27.2
19 | - 28.1
20 | - snapshot
21 | # ignore_warnings:
22 | # - true
23 | include:
24 | - emacs_version: snapshot
25 | ignore_warnings: false
26 | steps:
27 | - uses: actions/checkout@v2
28 | - uses: purcell/setup-emacs@master
29 | with:
30 | version: ${{ matrix.emacs_version }}
31 | - uses: leotaku/elisp-check@master
32 | with:
33 | check: melpa
34 | file: flycheck-posframe.el
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: emacs-lisp
2 | sudo: false
3 | addons:
4 | apt:
5 | packages:
6 | - autogen
7 | - ca-certificates
8 | - curl
9 | - gcc
10 | - libgmp-dev
11 | - m4
12 | - make
13 | - pkg-config
14 | - xz-utils
15 | cache:
16 | directories:
17 | - $HOME/local
18 | before_install:
19 | - sudo sh travis-ci/travis-gnutls.sh
20 | - gnutls-cli -v
21 | - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh
22 | - evm install $EVM_EMACS --use --skip
23 | - cask
24 | env:
25 | global:
26 | - PATH=$HOME/local/bin:$PATH
27 | - EVM_EMACS=emacs-git-snapshot-travis
28 | script:
29 | - emacs --version
30 | - cask build
31 | notifications:
32 | email: false
33 |
--------------------------------------------------------------------------------
/Cask:
--------------------------------------------------------------------------------
1 | (source gnu)
2 | (source melpa)
3 |
4 | (package-file "flycheck-posframe.el")
5 |
6 | (development
7 | (depends-on "flycheck")
8 | (depends-on "posframe"))
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flycheck-posframe
2 |
3 | [](http://www.gnu.org/licenses/gpl-3.0.txt)
4 | [](http://melpa.org/#/flycheck-posframe)
5 | [](https://travis-ci.org/alexmurray/flycheck-posframe)
6 |
7 | Display flycheck error messages via
8 | [posframe](https://github.com/tumashu/posframe).
9 |
10 | 
11 |
12 | ## Installation
13 |
14 | ### MELPA
15 |
16 | The preferred way to install `flycheck-posframe` is via
17 | [MELPA](http://melpa.org) - then you can just M-x package-install RET
18 | flycheck-posframe RET
19 |
20 | To enable then simply add the following to your init file:
21 |
22 | ```emacs-lisp
23 | (with-eval-after-load 'flycheck
24 | (require 'flycheck-posframe)
25 | (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode))
26 | ```
27 |
28 | We recommend to use [use-package](https://github.com/jwiegley/use-package) to
29 | make this automatic:
30 |
31 | ```emacs-lisp
32 | (use-package flycheck-posframe
33 | :ensure t
34 | :after flycheck
35 | :config (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode))
36 | ```
37 |
38 | ### Manual
39 |
40 | If you would like to install the package manually, download or clone it and
41 | place within Emacs' `load-path`, then you can require it in your init file like
42 | this:
43 |
44 | ```emacs-lisp
45 | (require 'flycheck-posframe)
46 | (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode)
47 | ```
48 |
49 | NOTE: This will also require the manual installation of `flycheck` if you have
50 | not done so already.
51 |
52 | ## Configuration
53 |
54 | ### Default Pretty Configuration
55 |
56 | Calling `(flycheck-posframe-configure-pretty-defaults)` will configure
57 | `flycheck-posframe` to show warnings and errors with nicer faces (inheriting
58 | from `warning` and `error` respectively), and set the prefix for each to nicer
59 | unicode characters.
60 |
61 | ### Manual Configuration
62 |
63 | There are a few settings which can be configured to customise the display
64 | of error messages. These include the faces which are used to show the error
65 | messages `flycheck-posframe-info-face`, `flycheck-posframe-warning-face`
66 | and `flycheck-posframe-error-face` and a string which is used as the prefix
67 | for each message
68 | `flycheck-posframe-info-prefix``flycheck-posframe-warning-prefix` and
69 | `flycheck-posframe-error-prefix`. The background colour can be specified as
70 | the `background` attribute of the `flycheck-posframe-background-face`
71 | face. `The position, as well as the border width and colour can also be
72 | customised via the `flycheck-posframe-position`,
73 | `flycheck-posframe-border-width` and `flycheck-posframe-border-color`
74 | variables respectively.
75 |
76 | #### `flycheck-posframe-LEVEL-face`
77 |
78 | By default each of `flycheck-posframe-LEVEL-face` inherits from the `default`
79 | face so should appear like the rest of the text in the buffer. If however you
80 | want to ensure error messages stand-out you could configure them to inherit
81 | from the `error` face:
82 |
83 | ```
84 | (set-face-attribute 'flycheck-posframe-error-face nil :inherit 'error)
85 | ```
86 |
87 | #### `flycheck-posframe-LEVEL-prefix`
88 |
89 | By default `flycheck-posframe-LEVEL-prefix` is set to "➤ ". If however you
90 | wanted to show each warning message prefixed with the unicode WARNING SIGN symbol
91 | (U+26A0) "⚠ " you could configure it as follows:
92 |
93 | ```
94 | (setq flycheck-posframe-warning-prefix "\u26a0 ")
95 | ```
96 |
97 | #### `flycheck-posframe-background-face`
98 |
99 | By default `flycheck-posframe-background-face` inherits from the default
100 | face, so the background colour should be the same as the standard window
101 | frame background colour. This can be customised like any other face (ie. by
102 | using `customize-face` or manually setting the `:background` face
103 | attribute)
104 |
105 | #### `flycheck-posframe-border-face`
106 |
107 | By default `flycheck-posframe-border-face` inherits from the default face,
108 | so the background colour should be the same as the standard foreground
109 | colour. This can be customised like any other face (ie. by using
110 | `customize-face` or manually setting the `:foreground` face attribute)
111 |
112 | #### `flycheck-posframe-border-use-error-face`
113 |
114 | By default `flycheck-posframe-border-use-error-face` is nil. When non-nil, it
115 | will override `flycheck-posframe-border-face` with the foreground of the face
116 | for the highest error level that is shown by `posframe`.
117 |
118 | #### `flycheck-posframe-border-width`
119 |
120 | By default `flycheck-posframe-border-width` is zero but this can be set to
121 | an integer number of pixels to specify the width of the border.
122 |
123 | #### `flycheck-posframe-position`
124 |
125 | By default `flycheck-posframe-position` is set to
126 | `point-bottom-left-corner` so that errors are shown just below point. This
127 | can be customised to any of the existing positions supported by
128 | `posframe`. For example, to display errors at the bottom-left of the
129 | window:
130 |
131 | ```
132 | (setq flycheck-posframe-position 'window-bottom-left-corner)
133 | ```
134 |
135 | ## License
136 |
137 | Copyright © 2019 Alex Murray
138 |
139 | Distributed under GNU GPL, version 3.
140 |
--------------------------------------------------------------------------------
/flycheck-posframe.el:
--------------------------------------------------------------------------------
1 | ;;; flycheck-posframe.el --- Show flycheck error messages using posframe.el
2 |
3 | ;; Copyright (C) 2021 Alex Murray
4 |
5 | ;; Author: Alex Murray
6 | ;; Maintainer: Alex Murray
7 | ;; URL: https://github.com/alexmurray/flycheck-posframe
8 | ;; Version: 0.9
9 | ;; Package-Requires: ((flycheck "0.24") (emacs "26") (posframe "0.7.0"))
10 |
11 | ;; This file is not part of GNU Emacs.
12 |
13 | ;; This program is free software: you can redistribute it and/or modify
14 | ;; it under the terms of the GNU General Public License as published by
15 | ;; the Free Software Foundation, either version 3 of the License, or
16 | ;; (at your option) any later version.
17 |
18 | ;; This program is distributed in the hope that it will be useful,
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | ;; GNU General Public License for more details.
22 |
23 | ;; You should have received a copy of the GNU General Public License
24 | ;; along with this program. If not, see .
25 |
26 | ;;; Commentary:
27 |
28 | ;; Show flycheck error messages using posframe.el
29 |
30 | ;;;; Setup
31 |
32 | ;; (with-eval-after-load 'flycheck
33 | ;; (require 'flycheck-posframe)
34 | ;; (add-hook 'flycheck-mode-hook #'flycheck-posframe-mode))
35 |
36 | ;;; Code:
37 | (require 'flycheck)
38 | (require 'posframe)
39 |
40 | (defgroup flycheck-posframe nil
41 | "Display Flycheck errors in tooltips using posframe.el."
42 | :prefix "flycheck-posframe-"
43 | :group 'flycheck
44 | :link '(url-link :tag "Github" "https://github.com/alexmurray/flycheck-posframe"))
45 |
46 | (defcustom flycheck-posframe-position 'point-bottom-left-corner
47 | "Where to position the flycheck-posframe frame."
48 | :group 'flycheck-posframe
49 | :type '(choice
50 | (const :tag "Center of the frame" frame-center)
51 | (const :tag "Centered at the top of the frame" frame-top-center)
52 | (const :tag "Left corner at the top of the frame" frame-top-left-corner)
53 | (const :tag "Right corner at the top of the frame" frame-top-right-corner)
54 | (const :tag "Left corner at the bottom of the frame" frame-bottom-left-corner)
55 | (const :tag "Right corner at the bottom of the frame" frame-bottom-right-corner)
56 | (const :tag "Center of the window" window-center)
57 | (const :tag "Left corner at the top of the window" window-top-left-corner)
58 | (const :tag "Right corner at the top of the window" window-top-right-corner)
59 | (const :tag "Left corner at the bottom of the window" window-bottom-left-corner)
60 | (const :tag "Right corner at the bottom of the window" window-bottom-right-corner)
61 | (const :tag "Top left corner of point" point-top-left-corner)
62 | (const :tag "Bottom left corner of point" point-bottom-left-corner))
63 | :package-version '(flycheck-posframe . "0.6"))
64 |
65 | (defcustom flycheck-posframe-border-width 0
66 | "Width of the border for a flycheck-posframe frame."
67 | :group 'flycheck-posframe
68 | :type 'integer
69 | :package-version '(flycheck-posframe . "0.6"))
70 |
71 | (defcustom flycheck-posframe-border-use-error-face nil
72 | "If non-nil, `flycheck-posframe-border-face' will be overriden by the foreground of the highest error level face."
73 | :group 'flycheck-posframe
74 | :type 'boolean
75 | :package-version '(flycheck-posframe . "0.7"))
76 |
77 | (defcustom flycheck-posframe-prefix "\u27a4 "
78 | "String to be displayed before every default message in posframe."
79 | :group 'flycheck-posframe
80 | :type 'string
81 | :package-version '(flycheck-posframe . "0.3"))
82 |
83 | (defcustom flycheck-posframe-info-prefix flycheck-posframe-prefix
84 | "String to be displayed before every info message in posframe."
85 | :group 'flycheck-posframe
86 | :type 'string
87 | :package-version '(flycheck-posframe . "0.3"))
88 |
89 | (defcustom flycheck-posframe-warning-prefix flycheck-posframe-prefix
90 | "String to be displayed before every warning message in posframe."
91 | :group 'flycheck-posframe
92 | :type 'string
93 | :package-version '(flycheck-posframe . "0.3"))
94 |
95 | (defcustom flycheck-posframe-error-prefix flycheck-posframe-prefix
96 | "String to be displayed before every error message in posframe."
97 | :group 'flycheck-posframe
98 | :type 'string
99 | :package-version '(flycheck-posframe . "0.1"))
100 |
101 | (defface flycheck-posframe-face
102 | '((t :inherit default))
103 | "The default face to use for displaying messages in posframe."
104 | :group 'flycheck-posframe
105 | :package-version '(flycheck-posframe . "0.2"))
106 |
107 | (defface flycheck-posframe-info-face
108 | '((t :inherit flycheck-posframe-face))
109 | "The face to use for displaying info messages in posframe."
110 | :group 'flycheck-posframe
111 | :package-version '(flycheck-posframe . "0.3"))
112 |
113 | (defface flycheck-posframe-warning-face
114 | '((t :inherit flycheck-posframe-face))
115 | "The face to use for displaying warning messages in posframe."
116 | :group 'flycheck-posframe
117 | :package-version '(flycheck-posframe . "0.3"))
118 |
119 | (defface flycheck-posframe-error-face
120 | '((t :inherit flycheck-posframe-face))
121 | "The face to use for displaying warning messages in posframe."
122 | :group 'flycheck-posframe
123 | :package-version '(flycheck-posframe . "0.3"))
124 |
125 | (defface flycheck-posframe-background-face
126 | '((t))
127 | "The background color of the flycheck-posframe frame.
128 | Only the `background' is used in this face."
129 | :group 'flycheck-posframe
130 | :package-version '(flycheck-posframe . "0.4"))
131 |
132 | (defface flycheck-posframe-border-face
133 | '((t))
134 | "The border color of the flycheck-posframe frame.
135 | Only the `foreground' is used in this face."
136 | :group 'flycheck-posframe
137 | :package-version '(flycheck-posframe . "0.6"))
138 |
139 | (defvar flycheck-posframe-buffer "*flycheck-posframe-buffer*"
140 | "The posframe buffer name use by flycheck-posframe.")
141 |
142 | (defvar flycheck-posframe-old-display-function nil
143 | "The former value of `flycheck-display-errors-function'.")
144 |
145 | (defvar flycheck-posframe-last-position nil
146 | "Last position for which a flycheck posframe was displayed.")
147 |
148 | (defun flycheck-posframe-check-position ()
149 | "Update `flycheck-posframe-last-position', returning t if there was no change."
150 | (equal flycheck-posframe-last-position
151 | (setq flycheck-posframe-last-position
152 | (list (current-buffer) (buffer-modified-tick) (point)))))
153 |
154 | (defcustom flycheck-posframe-inhibit-functions nil
155 | "Functions to inhibit display of flycheck posframe."
156 | :type 'hook
157 | :group 'flycheck-posframe)
158 |
159 | (defun flycheck-posframe-get-prefix-for-error (err)
160 | "Return the prefix which should be used to display ERR."
161 | (pcase (flycheck-error-level err)
162 | ('info flycheck-posframe-info-prefix)
163 | ('warning flycheck-posframe-warning-prefix)
164 | ('error flycheck-posframe-error-prefix)
165 | (_ flycheck-posframe-prefix)))
166 |
167 | (defun flycheck-posframe-get-face-for-error (err)
168 | "Return the face which should be used to display ERR."
169 | (pcase (flycheck-error-level err)
170 | ('info 'flycheck-posframe-info-face)
171 | ('warning 'flycheck-posframe-warning-face)
172 | ('error 'flycheck-posframe-error-face)
173 | (_ 'flycheck-posframe-face)))
174 |
175 | (defun flycheck-posframe-highest-error-level-face (errs)
176 | "Return the face corresponding to the highest error level from ERRS."
177 | (flycheck-posframe-get-face-for-error (cl-reduce
178 | (lambda (err1 err2) (if (flycheck-error-level-< err1 err2) err2 err1))
179 | errs)))
180 |
181 | (defun flycheck-posframe-format-error (err)
182 | "Formats ERR for display."
183 | (propertize (concat
184 | (flycheck-posframe-get-prefix-for-error err)
185 | (flycheck-error-format-message-and-id err))
186 | 'face
187 | `(:inherit ,(flycheck-posframe-get-face-for-error err))) )
188 |
189 | (defun flycheck-posframe-format-errors (errors)
190 | "Formats ERRORS messages for display."
191 | (let ((messages (sort
192 | (mapcar #'flycheck-posframe-format-error
193 | (delete-dups errors))
194 | 'string-lessp)))
195 | (mapconcat 'identity messages "\n")))
196 |
197 | (defun flycheck-posframe-hidehandler (_info)
198 | "Hide posframe if position has changed since last display."
199 | (not (flycheck-posframe-check-position)))
200 |
201 | (defun flycheck-posframe-show-posframe (errors)
202 | "Display ERRORS, using posframe.el library."
203 | (posframe-hide flycheck-posframe-buffer)
204 | (when (and errors
205 | (not (run-hook-with-args-until-success 'flycheck-posframe-inhibit-functions)))
206 | (let ((poshandler (intern (format "posframe-poshandler-%s" flycheck-posframe-position))))
207 | (unless (functionp poshandler)
208 | (setq poshandler nil))
209 | (flycheck-posframe-check-position)
210 | (posframe-show
211 | flycheck-posframe-buffer
212 | :string (flycheck-posframe-format-errors errors)
213 | :background-color (face-background 'flycheck-posframe-background-face nil t)
214 | :position (point)
215 | :internal-border-width flycheck-posframe-border-width
216 | :internal-border-color (face-foreground (if flycheck-posframe-border-use-error-face
217 | (flycheck-posframe-highest-error-level-face errors)
218 | 'flycheck-posframe-border-face) nil t)
219 | :poshandler poshandler
220 | :hidehandler #'flycheck-posframe-hidehandler))))
221 |
222 | ;;;###autoload
223 | (defun flycheck-posframe-configure-pretty-defaults ()
224 | "Configure some nicer settings for prettier display."
225 | (setq flycheck-posframe-warning-prefix "\u26a0 ")
226 | (setq flycheck-posframe-error-prefix "\u274c ")
227 | (set-face-attribute 'flycheck-posframe-warning-face nil :inherit 'warning)
228 | (set-face-attribute 'flycheck-posframe-error-face nil :inherit 'error))
229 |
230 | ;;;###autoload
231 | (define-minor-mode flycheck-posframe-mode
232 | "A minor mode to show Flycheck error messages in a posframe."
233 | :lighter nil
234 | :group 'flycheck-posframe
235 | (cond
236 | ;; Use our display function and remember the old one but only if we haven't
237 | ;; yet configured it, to avoid activating twice.
238 | ((and flycheck-posframe-mode
239 | (not (eq flycheck-display-errors-function
240 | #'flycheck-posframe-show-posframe)))
241 | (setq-local flycheck-posframe-old-display-function
242 | flycheck-display-errors-function)
243 | (setq-local flycheck-display-errors-function
244 | #'flycheck-posframe-show-posframe))
245 | ;; Reset the display function and remove ourselves from all hooks but only
246 | ;; if the mode is still active.
247 | ((and (not flycheck-posframe-mode)
248 | (eq flycheck-display-errors-function
249 | #'flycheck-posframe-show-posframe))
250 | (setq-local flycheck-display-errors-function
251 | flycheck-posframe-old-display-function)
252 | (setq-local flycheck-posframe-old-display-function nil))))
253 |
254 | (provide 'flycheck-posframe)
255 | ;;; flycheck-posframe.el ends here
256 |
--------------------------------------------------------------------------------
/screenshots/flycheck-posframe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alexmurray/flycheck-posframe/19896b922c76a0f460bf3fe8d8ebc2f9ac9028d8/screenshots/flycheck-posframe.png
--------------------------------------------------------------------------------