📜 ⬆️ ⬇️

Improving emacs jabber

Start


On Habré was already an overview article on jabber.el - jabber-client for emacs. Having decided to try this client after pidgin, I came across the lack of such familiar things as input history or formatted messages. Unfortunately, emacs-jabber is not developing as fast as we would like. Fortunately, the emacs configuration options are almost limitless, so adding the right one is easy. In this article I will tell you how I implemented the input history. If this topic is of interest to the public, in the future I will describe sending formatted messages (html) and some other goodies.

Reservation
Everything described was done for myself. I use prelude , so some functions may be from third-party libraries and absent in pure email. Also, I only use chat rooms, for conferences the specified code will need to be corrected.


Input history


A very handy thing about pidgin is the input history. By ctrl + up you can go back through the history of sent messages, and by ctrl + down forward. Add this functionality to emacs-jabber. We need three variables: the list of entered phrases, the current position in this list, and the last entered, but not yet sent text.
(defvar my-jabber-input-history '() "Variable that holds input history") (make-variable-buffer-local 'my-jabber-input-history) (defvar my-jabber-input-history-position 0 "Current position in input history") (make-variable-buffer-local 'my-jabber-input-history-position) (defvar my-jabber-input-history-current nil "Current input value") (make-variable-buffer-local 'my-jabber-input-history-current) 

When sending a message, add it to the list:
 (defun my-jabber-input-history-hook (body id) (add-to-list 'my-jabber-input-history body t) (setq my-jabber-input-history-position (length my-jabber-input-history))) (add-hook 'jabber-chat-send-hooks 'my-jabber-input-history-hook) 

Important: my-jabber-input-history-position does not point to the last element of history, but behind it (numbering from zero). This is logical, because we have not yet gone through the list.
Function to go back through the list:
 (defun my-jabber-previous-input () (interactive) (let (current-input (pos my-jabber-input-history-position) (len (length my-jabber-input-history))) (if (= pos 0) (message "%s" "No previous input") (setq current-input (delete-and-extract-region jabber-point-insert (point-max))) (when (= pos len) ; running first time, save current input (setq my-jabber-input-history-current current-input)) (decf my-jabber-input-history-position) (insert (nth my-jabber-input-history-position my-jabber-input-history))))) 

Everything is simple, the only thing worth paying attention to is to save the current text entered. If the user changes his mind to use the story, we will be able to restore what he managed to enter.
The function for going forward through the list is:
 (defun my-jabber-next-input () (interactive) (let ((pos my-jabber-input-history-position) (len (length my-jabber-input-history))) (cond ((= pos (1- len)) ; pointing at the last element, insert saved input (incf my-jabber-input-history-position) (delete-region jabber-point-insert (point-max)) (insert my-jabber-input-history-current) (setq my-jabber-input-history-current nil)) ((= pos len) ; pointing beyound last element, notify user (message "%s" "No next input")) (t ; insert next history item (incf my-jabber-input-history-position) (delete-region jabber-point-insert (point-max)) (insert (nth my-jabber-input-history-position my-jabber-input-history)))))) 

Here the logic is smarter. If we are on the last item in the list (len - 1), then we need to insert previously saved user input. But the position is still increasing, so that next time the second condition worked.
We hang these functions on convenient buttons:
 (define-key jabber-chat-mode-map (kbd "Mp") 'my-jabber-previous-input) (define-key jabber-chat-mode-map (kbd "Mn") 'my-jabber-next-input) 

Is done. Now we have the same functionality as in pidgin + notification of reaching the beginning and end of the list + history without duplicate messages (thanks to the add-to-list).
Fans of ido-mode can come in handy with this feature:
 (defun my-jabber-input-history-choose () (interactive) (let ((choice (ido-completing-read "Select history item: " (reverse my-jabber-input-history)))) (delete-region jabber-point-insert (point-max)) (insert choice))) 

Since this is ido, then the search in the list works as you type the text (even fuzzy if the variable ido-enable-flex-matching is set) and search through the options for Cs / Cr.

the end


The text was prepared in emacs using org-mode and exporting to a docbook (C-c Ce D).
')

Links


Lis code

The source of this article

XSLT for converting XML into a clear format.

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


All Articles