[LINUX] Emacs perspective.el workspace is easier to use

This article is the 21st day of Emacs Advent Calendar 2019.

Day 20 @ tachiyama's article The strongest editor Emacs can do matrix (like things) I will take over from and write an article.

At the beginning

Emacs is an editor with over 10,000 built-in commands and many packages. We Emacs users have to keep improving their Emacs to their liking, even if they are ridiculed by other programmers.

Keep the joke up to here (isn't it a joke?)

Do you know the super-capable Emacs Lisp package EXWM (Emacs X Window Manager)? This package is for operating Emacs as a tiled window manager.

In my opinion, EXWM has two major merits. First, ** A function that can handle X Window applications as a buffer **. And ** the concept of workspace **.

Benefits of EXWM

Since the X Window application can be used as an Emacs buffer, you can instantly display, switch, and kill the buffer list with C-x b. EXWM is a package that embodies one of the advantages of using Emacs, ** operation with a unified interface **.

Next is the concept of workspace. You can switch workspaces with the key binding of s-n (0-9 for n). This is very convenient, workspace 1 is for programs, workspace 2 is a shell, workspace 3 is a web browser, and so on, it can be organized and refreshed in the brain.

Problems with EXWM

Of course, there are not only advantages but also inconveniences.

In the first place, since it is an EXWM tile type window manager, it is usually difficult to use when it comes to handling floating windows. (Is there a lot of scenes you want to float?)

In addition, EXWM still has some instability. Depending on the environment, you may not be able to start or key input. I've been using it on Debian testing for about a year, but one day it suddenly stopped accepting keystrokes.

Dark GNOME life

I was evacuating to GNOME with the intention of fixing it later, but before I knew it, I had been using GNOME for more than half a year. However, I always found it difficult to use Emacs on GNOME. Especially since there is only one buffer list, switching between them was tedious and unavoidable for me, who opens a lot of buffers. Also, since there is only one window, it is not possible to open a large number of buffers at once, which is really difficult to use. (Although it's much more convenient than an editor starting with V)

Started using perspective.el

So I started using perspective.el, which allows you to group buffers and switch between them. It can create a workspace and you can name it freely. And you can switch back and forth with C-c p s <name>. However, this package did not take hold very well. First of all, the key bindings are long, and typing the name is a hassle, so I tend to end up with one workspace. Therefore, I thought as follows.

** Is the switching key binding simple, you don't have to type a name, and you can't move through the perspective.el workspace? ** **

That's why I got the idea. It would be nice if we could easily switch the workspace of perspective.el with s -n like EXWM.

Finally the main subject

First, decide what you want to do.

** I want to be able to switch the workspace of perspective.el with s-n (n is a number 0-9). ** **

Method

Think appropriately about how to achieve this.

It looks like this. it's simple. By the way, my Emacs Lisp skill is only understandable by reading, and I can hardly write it. So, I think the code I wrote this time is far from the Emacs Lisp style of writing ... If you have any advice, please leave it in the comments.

I will write

Completed state

First of all, I will write the code of Emacs Lisp that works as expected. If you want to show it quickly, please write this code in init.el. By the way, please note that the key binding is registered with M-n instead of s-n.

*** * Addition * *** *** Since the cl library was abolished as standard from Emacs 27.0.91 released the other day, lexical-let can no longer be used. I changed the following code to correspond to it. *** ***

(require 'perspective)
(persp-mode 1)

;;Workspace generation
(mapc (lambda (i)
        (persp-switch (int-to-string i)))
      (number-sequence 0 9))

;;;;Function that returns the function to be registered in the key
;;(defun local-switch-workspace (i)
;;  (lexical-let ((index i))
;;    (lambda ()
;;      (interactive)
;;      (persp-switch (int-to-string index)))))

;;
;;Update 2020/04/28
;;
(defun local-switch-workspace (index)
  `(lambda ()
     (interactive)
     (persp-switch (int-to-string ,index))))

;;Register the key binding
(mapc (lambda (i)
        (global-set-key (kbd (format "M-%d" i)) (local-switch-workspace i)));;
      (number-sequence 0 9))

;The first workspace is"1"Set to
(persp-switch "1")

Creating a workspace

I want to create a workspace at startup, so write the process to create the workspace directly in init.el.

;;Workspace generation
(mapc (lambda (i)
        (persp-switch (int-to-string i)))
      (number-sequence 0 9))

The workspace is created by passing the lambda expression and the list of 0 \ ~ 9 generated by number-sequence to mapc as the function to generate the workspace. mapc is a function that takes values one by one from the list of the second argument and passes them to the function passed to the first argument to execute. This function is very convenient and quite heavily used.

;;Function that returns the function to be registered in the key
;;(defun local-switch-workspace (i)
;;  (lexical-let ((index i))
;;    (lambda ()
;;      (interactive)
;;      (persp-switch (int-to-string index)))))

;;
;;Update 2020/04/28
;;
(defun local-switch-workspace (index)
  `(lambda ()
     (interactive)
     (persp-switch (int-to-string ,index))))

This function returns a function that toggles the workspace. It is assumed that the return value of this function will be passed to global-set-key. For example, if you pass 1 to this function and execute it, the function that executes (persp-switch" 1 ") will be returned. You pass that function to global-set-key. At first, I was trying to pass a lambda expression directly to global-set-key, but it didn't work and I settled on this. As a result of seeing the wisdom of experienced Emacs Lisp programmers with Google Sensei, it became a function that uses lexical-let. This lexical-let is required to create closures, but this feature is available in Emacs 24.1 and later, so be careful if you are using an earlier Emacs. Well, now in 2019, it's rare to find someone using a version prior to Emacs 24.1. (I'm using Emacs 26.3)

;;Register the key binding
(mapc (lambda (i)
        (global-set-key (kbd (format "M-%d" i)) (local-switch-workspace i)))
      (number-sequence 0 9))

Here, the key binding is actually registered in M-n (n is a number from 0 \ to 9). The content is simple, using mapc to register the function of the return value of local-switch-workspace in the key 0 \ ~ 9.

** That's strange **

It should be registered in s-n, but it is registered in M-n. I'm sorry. The Super-Number keybinding was registered with GNOME and could not be passed to Emacs. So I compromised with the Alt key (Meta key).

;The first workspace is"1"Set to
(persp-switch "1")

Finally, set the default workspace to 1 and you're done.

Try using

I've been using it for about a week, and it's getting really good. I think that the EXWM workspace switching has been reproduced almost completely. Also, since perspective.el is running behind the scenes, there is an advantage that the functions provided by perspective.el can be used as they are. Also, I'm glad I was able to use it as a material for the Advent calendar.

Introduction of composition

Finally, I would like to introduce the usage that has become established in the author.

WS1 ~ 4 WS5 ~ 7 WS8 ~ 9
program+shell Sentences and simple scripts Free

in conclusion

If you want to switch workspaces more smoothly, please write it in init.el. Maybe you'll be addicted to it (`e') Peer

Recommended Posts

Emacs perspective.el workspace is easier to use
Is it deprecated to use pip directly?
Make SikuliX's click function easier to use
[Pandas] What is set_option [How to use]
How to use is and == in Python
Let's play with JNetHack 3.6.2 which is easier to compile!
Scraping with Python-Selenium is old! ?? ・ ・ ・ How to use Pyppeteer
Re: Python lambda is useless ^ H ^ H ^ H ^ H ^ H Difficult to use
How to use xml.etree.ElementTree
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use image-match
How to use shogun
How to use Pandas 2
How to use Virtualenv
How to use numpy.vectorize
How to use pytest_report_header
Easy to use Flask
How to use partial
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
Reasons to use logarithm
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
Easy to use SQLite3
How to use list []
How to use python-kabusapi
Python-How to use pyinstaller
How to use OptParse
How to use return
Introduce elpy to emacs
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
Made icrawler easier to use for machine learning data collection
VIM is good to use — at least a sneak peek
Microsoft's Deep Learning framework "CNTK" is now compatible with Python, making it much easier to use