šŸ“œ ā¬†ļø ā¬‡ļø

Emacs + handy window and buffer manager

Hello habrazhiteli!

Recently, about a year ago, I started to get involved in emax. Thank you for this fellow worker, who told me a lot of things and made me fall in love with email.

But, I missed a very good and convenient buffer manager, I started searching and found emacs-purpose .
')
This is a very convenient system for building your configuration buffers and their location on the page. What is interesting is that it implies that each buffer has a purpose and, accordingly, a target place in your layout. Based on this extension, it is even possible to make your own emacs ide very easily. So, let's take a few steps to build your IDE version using this engine.

For starters, this is what my email interface looks like.

image

We will build our IDE version in several steps:

  1. building your buffer layout structure
  2. assigning to each buffer a list of modes that will be displayed in this buffer.
  3. simplified switching between buffers.
  4. other usability improvements for our IDE.

1. Build Your Buffer Location Structure


It is very easy!

In the file window-purpose-x.el, you need to change the definition of the variable purpose-x-code1 — window-layout.
Ideally, this can be done by placing the layout separately in the ~ / .emacs.d / layouts / folder and then loading the layout with the following function.

(purpose-load-window-layout-file "~/.emacs.d/layouts/full-ide.window-layout") 

but for the time being, for some reason this does not work, I sent a Pull request with a new layout to the author (we understand why it does not work).

While this is not fixed in the main repository, I had to fix the window-purpose-x.el. In general, judging by what I understood, there is a problem with new types of purposes, which I enter into the layout, the problem seems to be in the function:
pull request

Here is my configuration, which looks like this (the figure was above):

elisp code
 (nil (0 0 152 35) (t (0 0 29 35) (:purpose dired :purpose-dedicated t :width 0.16 :height 0.5 :edges (0.0 0.0 0.19333333333333333 0.5)) (:purpose buffers :purpose-dedicated t :width 0.16 :height 0.4722222222222222 :edges (0.0 0.5 0.19333333333333333 0.9722222222222222))) (t (29 0 125 35) (:purpose edit :purpose-dedicated t :width 0.6 :height 0.85 :edges (0.19333333333333333 0.0 0.8266666666666667 0.85)) (:purpose misc :purpose-dedicated t :width 0.6 :height 0.1 :edges (0.19333333333333333 0.8722222222222222 0.8266666666666667 0.9722222222222222)) ) (t (125 0 152 35) (:purpose ilist :purpose-dedicated t :width 0.15333333333333332 :height 0.6 :edges (0.82666666666666667 0.0 0.9722222222222222 0.6)) (:purpose todo :purpose-dedicated t :width 0.15333333333333332 :height 0.372222222 :edges (0.8266666666666667 0.6 0.9722222222222222 0.9722222222222222)) ) ) 

In general, it is enough to put this text in ~ / .emacs.d / layouts / full-ide.window-layout and add such a thing to our init.el

 (defun load-purpose-mode () (interactive) (purpose-load-window-layout-file "~/.emacs.d/layouts/full-ide.window-layout") (purpose-x-code1-setup) ) (global-set-key (kbd "ML") 'load-purpose-mode) 

by pressing Alt + Shift + L, I load this configuration. By the way, a hint: you can make a bunch of configurations. For example, if you switch to the analysis mode of changes in the course, you can make a configuration specifically for analyzing the state of the repository.

Gradually, we will supplement our load-purpose-mode function with other goodies.

2. Assign to each buffer a list of modes that will be displayed in this buffer.


For my IDE, I determined the following modes to be displayed in buffers with certain purpos.
misc purposetodo purposeedit purpose
inferior-python-modeorg-modecss-mode
python-inferior-modeyaml-mode
gdb-inferior-io-modeconf-unix-mode
fundamental-mode* magit *
compilation-mode
shell-mode
eshell-mode
term-mode
Make it very simple (one of the options):

 (add-to-list 'purpose-user-mode-purposes '(YOUR_MODE . PURPOSE)) 

For magit, things are a bit more complicated (from the emacs-purpose documentation):

 (defvar purpose-x-magit-single-conf (purpose-conf "magit-single" :regexp-purposes '(("^\\*magit" . misc))) "Configuration that gives each magit major mode the same purpose.") (purpose-x-magit-single-on) 

After all your changes, do not forget to run the following command in your init.el:

 (purpose-compile-user-configuration) 

Then your changes will be applied.

3. Simplify switching between buffers


Lots of buffers? But they seem to be divided by assignments, but how to switch between them? Thanks to this library it is easy enough.

Here is my list of commands for switching to buffers with different purposes:

elisp code
 ;; helper       purpose.       . (ie,   purpose ) (defun get-only-one-buffer-with-purpose (purpose) "Get buffers wih purpose" (buffer-name (nth 0 (purpose-buffers-with-purpose purpose))) ) ;;   dired buffer,  ,      ,               dired .    .     ?            purpose. ,        (define-key purpose-mode-map (kbd "Cc Cf") (lambda () (interactive) (purpose-switch-buffer-with-some-purpose 'dired)) ) ;;       .    .  .   . (define-key purpose-mode-map (kbd "Cc Cl") (lambda () (interactive) (purpose-switch-buffer (get-only-one-buffer-with-purpose 'buffers))) ) ;;       .       dired (define-key purpose-mode-map (kbd "Cc Cc") (lambda () (interactive) (purpose-switch-buffer-with-some-purpose 'edit)) ) ;;       (,     )     .    .  .   . (define-key purpose-mode-map (kbd "Cc Cd") (lambda () (interactive) (purpose-switch-buffer (get-only-one-buffer-with-purpose 'ilist))) ) ;;      todo .     .  .     (define-key purpose-mode-map (kbd "Cc Ct") (lambda () (interactive) (purpose-switch-buffer (get-only-one-buffer-with-purpose 'todo))) ) 

4. Other usability improvements for our IDE


For me personally, it is important to still see the todo list in the project, it reminds of some important things.

So I made a special buffer with purpose todo. And I open in it a file written for org-mode, which contains the todo list of a specific project.
This file is automatically generated when the window-purpose layout is activated.

In the function load-purpose-mode (cited above) you need to add (todo-mode-get-buffer-create) to the end and here is a piece of elisp responsible for this process.

elisp code
 (defconst todo-mode-buffer-name "*CodeTodo*" "Name of the buffer that is used to display todo entries.") ;;    todo  ,   ,       read only mode   @todo.      @todo        . (defun on-org-mode-todo-file-built (process event) (find-file (concat (getenv "PWD") "/todo.org")) (call-interactively 'read-only-mode) ) ;;     todo   org-mode (defun build-org-mode-file-for-todo () (start-process "Building todo things" "*CodeTodo*" "bash" "-ic" "source ~/.bashrc; collecttodotags") (set-process-sentinel (get-process "Building todo things") 'on-org-mode-todo-file-built) ) ;;      ,     (defun todo-mode-get-buffer-create () "Return the todo-mode buffer. If it doesn't exist, create it." (or (get-buffer todo-mode-buffer-name) (let ((buffer (get-buffer-create todo-mode-buffer-name))) (with-current-buffer buffer (org-mode) (build-org-mode-file-for-todo) (pop-to-buffer todo-mode-buffer-name)) buffer))) 

The collectotodotags command is an alias for the Bashy team:

 alias collecttodotags="find `pwd` -type d \( -name .git -o -name myworkenv -o -name node_modules \) -prune -o -type f \( -name todo.org \) -prune -o -type f -print -exec grep -n '@todo' '{}' \; | create_org_mode_todo_file.py > ./todo.org" 

This command finds a list of all files with reference to the place where there is a todo in the code and sends a list of these files with todo to the input to the following Python file:
github

And pay attention, how can you indicate that some todo is more important than another
github

The more @todooo has more ā€œoā€ at the end, the more important it is. I’m not quite sure how best to do it, can someone tell me?

And yes, the last goodies. The point of the misc purpos is to display there all the intermediate things, searches, etc., and so on, but the buffer is small, so I added the following shortcuts:

 (global-set-key "\C-c+" (lambda () (interactive) (enlarge-window +20))) (global-set-key "\C-c_" (lambda () (interactive) (enlarge-window -20))) 

One to increase the buffer, another to reduce, it helps when there is a lot of text in misc.

And in general, how do you like this emacs extension?
Thanks for attention!

PS If the topic is interesting, then I can continue and tell other points about my emacs config

Source: https://habr.com/ru/post/333640/


All Articles