Popper
Emacs minor-mode to summon and dismiss buffers easily.
Install / Use
/learn @karthink/PopperREADME
#+title: Popper: Popup Buffers for Emacs
#+html: <a href="https://elpa.gnu.org/packages/popper.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/popper.svg"/></a> #+html: <a href="https://elpa.gnu.org/devel/popper.html"><img alt="GNU-devel ELPA" src="https://elpa.gnu.org/devel/popper.svg"/></a> #+html: <a href="https://melpa.org/#/popper"><img alt="MELPA" src="https://melpa.org/packages/popper-badge.svg"/></a> #+html: <a href="https://stable.melpa.org/#/popper"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/popper-badge.svg"/></a>
Popper is a minor-mode to tame the flood of ephemeral windows Emacs produces, while still keeping them within arm's reach.
Designate any buffer to "popup" status, and it will stay out of your way. Disimss or summon it easily with one key. Cycle through all your "popups" or just the ones relevant to your current buffer. Group popups automatically so you're presented with the most relevant ones. Useful for many things, including toggling display of REPLs, documentation, compilation or shell output: any buffer you need instant access to but want kept out of your way!
There is a [[https://www.youtube.com/watch?v=E-xUNlZi3rI][detailed demo of Popper here]]. [Note (10/2021): This demo is quite out of date at this point but covers the basics.]
You can pre-designate any buffer (by name or major-mode) as a popup, and the status will be automatically applied when Emacs creates it.
By default, your popups are displayed in a non-obtrusive way, but Popper respects window rules for buffers that you might have in =display-buffer-alist= or created using a window management package like =shackle.el=. Popper summons windows defined by the user as "popups" by simply calling =display-buffer=.
*** Toggle a popup:
#+ATTR_ORG: :width 500
#+ATTR_HTML: :width 500px
[[file:images/popper-toggle-latest.gif]]
Here I toggle a REPL for quick access.
https://user-images.githubusercontent.com/8607532/135746327-c400aaf9-4aa1-4b6e-8b0a-0dd58c2690bb.mp4
*** Cycle through all your popups:
#+ATTR_ORG: :width 500
#+ATTR_HTML: :width 500px
[[file:images/popper-cycle.gif]]
Here I cycle through all "popup buffers" in quick succession. My popup buffers are the usual suspects: help buffers, REPLs, grep and occur buffers, shell and compilation output, log buffers etc.
https://user-images.githubusercontent.com/8607532/135746363-aa3c3a25-cc9d-4907-a85f-07ea0d764238.mp4
Note that popup buffers are indicated here by the marker "POP" in their modelines. *** Or jump to them instantly with hinting You can see your popups in the echo area and jump to them with a key.
https://user-images.githubusercontent.com/8607532/135746395-dfe3b3e8-9d5a-4309-b521-9555a34bb73d.mp4 *** Group your popups according to context With grouping turned on, I'm only shown the popups relevant to the current context (in this case the Popper project).
https://user-images.githubusercontent.com/8607532/135746404-d8673390-d220-46fe-9b57-9dc81458cecd.mp4
The context can be anything, see below. Projectile, Perspective and Project.el are supported out of the box. *** Turn a regular window into a popup:
#+ATTR_ORG: :width 500
#+ATTR_HTML: :width 500px
[[file:images/popper-demote.gif]]
https://user-images.githubusercontent.com/8607532/135746418-21d32c74-e1f1-48f3-ba19-792c7cb2a51a.mp4
Or promote a popup to regular window status. *** Popper respects your display buffer settings
https://user-images.githubusercontent.com/8607532/135746477-93f8fc3d-4806-4901-beae-904059584e72.mp4
And windows open the way you have specified them to: in reused windows, side windows, new or child frames, etc. All display-buffer actions are supported except for displaying in popups in new frames and in atomic windows. *** ... you can toggle all your popups at once: #+ATTR_ORG: :width 500 #+ATTR_HTML: :width 500px [[file:images/popper-toggle-all.png]]
[[file:images/popper-toggle-all.gif]]
- Usage Turn on =popper-mode=.
- Turn any buffer into a popup (or vice-versa) with =popper-toggle-type=.
There are two commands for displaying popups, you can bind them as convenient:
- =popper-toggle=: Show/hide the latest popup. Does more with prefix args.
- =popper-cycle=: Cycle through your popups in sequence.
To automatically designate buffers as popups, see the customization section. Additionally, you can kill an open popup buffer with =popper-kill-latest-popup=.
If you want the echo-area hints, turn on =popper-echo-mode=.
- Setup =popper= is available on GNU ELPA, so you can install it with =M-x package-install RET popper RET=.
** With =use-package=
#+BEGIN_SRC emacs-lisp
(use-package popper
:ensure t ; or :straight t
:bind (("C-" . popper-toggle) ("M-" . popper-cycle)
("C-M-`" . popper-toggle-type))
:init
(setq popper-reference-buffers
'("\Messages\"
"Output\*$"
"\Async Shell Command\"
help-mode
compilation-mode))
(popper-mode +1)
(popper-echo-mode +1)) ; For echo area hints
#+END_SRC
See the Customization section for details on specifying buffer types as popups.
** Without =use-package=
#+BEGIN_SRC emacs-lisp
(require 'popper)
(setq popper-reference-buffers
'("\Messages\"
"Output\*$"
"\Async Shell Command\"
help-mode
compilation-mode))
(global-set-key (kbd "C-") 'popper-toggle) (global-set-key (kbd "M-") 'popper-cycle)
(global-set-key (kbd "C-M-`") 'popper-toggle-type)
(popper-mode +1)
;; For echo-area hints (require 'popper-echo) (popper-echo-mode +1) #+END_SRC See the Customization section for details on specifying buffer types as popups.
- Customization :PROPERTIES: :ID: ce27af55-91a5-4549-97ac-d7f2c0aa9019 :END: To get started, customize this variable:
-
=popper-reference-buffers=: List of buffers to treat as popups. Each entry in the list can be a regexp (string) to match buffer names against or a major-mode (symbol) to match buffer major-modes against.
Example:
#+BEGIN_SRC emacs-lisp (setq popper-reference-buffers '("\Messages\" "Output\*$" help-mode compilation-mode)) #+END_SRC
Will treat the following as popups: The Messages buffer, any buffer ending in "Output*", and all help and compilation buffers.
Note: Because of how some shell buffers are initialized in Emacs, you may need to supply both the name and major mode to match them consistently. Take your pick:
#+BEGIN_SRC emacs-lisp ;; Match eshell, shell, term and/or vterm buffers (setq popper-reference-buffers (append popper-reference-buffers '("^\eshell.\$" eshell-mode ;eshell as a popup "^\shell.\$" shell-mode ;shell as a popup "^\term.\$" term-mode ;term as a popup "^\vterm.\$" vterm-mode ;vterm as a popup ))) #+END_SRC
As of v0.40, Popper also supports classifying a buffer as a popup based on any user supplied predicate. This predicate (function) is called with the buffer as argument and returns =t= if it should be considered a popup. Here is an example with a predicate:
#+BEGIN_SRC emacs-lisp (setq popper-reference-buffers '("\Messages\" help-mode (lambda (buf) (with-current-buffer buf (and (derived-mode-p 'fundamental-mode) (< (count-lines (point-min) (point-max)) 10))))))) #+END_SRC
This list includes the the Messages and =help-mode= buffers from before, along with a predicate: any buffer derived from the major mode =fundamental-mode= that has fewer than 10 lines will be considered a popup.
Note that for performance reasons, predicates that classify a buffer as a popup are /only run when the buffer is created/. Thus dynamically changing a buffer's popup status based on its changing state is not possible (yet).
There are other customization options, check the =popper= group.
Here is an example of how I use Popper:
https://user-images.githubusercontent.com/8607532/135748097-268f5aae-ad42-44fa-9435-b63b960d45cf.mp4
In this example:
-
Popup buffers have no modelines.
-
My popups are grouped by project, so I only see popups relevant to the current one.
-
I use the echo-area hints to select popups with the number keys.
-
These hints have their buffer names truncated so they're easier to read.
-
My popups show up in different ways on screen depending on my display-buffer settings: Help windows on the right, REPLs and command output at the bottom, grep buffers at the top etc.
This section details these (and other) customization options.
** Grouping popups by context Popper can group popups by "context", so that the popups available for display are limited to those that are relevant to the context in which =popper-toggle= or =popper-cycle= is called. For example, when cycling popups from a project buffer, you may only want to see the popups (REPLs, help buffers and compilation output, say) that were spawned from buffers in that project. This is intended to approximate DWIM behavior, so that the most relevant popup in any context is never more than one command away.
Built in contexts include projects as defined in Emacs' built in =project.el= and =projectile=, using =perspective= names (from =persp.el=), as well as the default directory of a buffer. To set this, customize =popper-group-function= or use one of
#+BEGIN_SRC emacs-lisp (setq popper-group-function #'popper-group-by-project) ; project.el projects
(setq popper-group-function #'popper-group-by-projectile) ; projectile projects
(setq popper-group-function #'popper-group-by-directory) ; group by project.el ; project root, with
Related Skills
node-connect
346.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
107.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
346.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
