4 ms·
What makes it easier to write in ELisp compared to JS? Also, other text editors got on the 'real programming language' train too, like Neovim with its support
by ColonelPhantom 4y ago
What makes it easier to write in ELisp compared to JS?
Also, other text editors got on the 'real programming language' train too, like Neovim with its support for Lua. There's also Lite XL which is almost fully written in Lua itself. Does ELisp still have a big advantage there?
- precompute 4y agoSure. Elisp is very well-integrated with the editor itself, because that's what emacs is written in. There are some primitive functions that written in C that everything builds on top of. This makes writing functions an extension of the text editing process itself. This is why it's truly extensible. You don't get penalized for writing your own functions, they exist at the same rank as what emacs ships with. Writing functions in lua is fine, but nvim and the like still suffer from being just text editors, and most things that interact with the operating system / syscalls or change/traverse the UI require quite a lot of legwork. In Emacs, this is all very easy. Depending on what you need, you can be perfectly satisfied with vim and a couple of plugins. However, after realizing how easy it was to write functions in elisp, I more or less moved all my text / file editing to Emacs, along with most batch functions. For example, here's a function to insert a formatted date in the current buffer: (defun timestamp () "Insert string for the current time formatted like '2:34 PM' or 1507121460" (interactive) (insert (format-time-string "[%02y-%02m-%02d %02H:%02M:%02S] "))) You'd have to consult the docs for writing this trivial function in literally any other text editor. In emacs, you can `C-h` for everything, and this program will always run properly, because you're using functions that are used by emacs internally. Chaining functions: (defun org-id-create-copy () "org-id-get-create and then org-id-copy" (interactive) (org-id-get-create) (org-id-copy)) Utilizing inbuilt syntax for a major mode in your custom function: (defun org-delete-subtree () "Delete the current subtree" (interactive) (let ((org-heading-text (nth 4 (org-heading-components)))) (save-restriction (org-narrow-to-subtree) (kill-region (point-min) (point-max)) (widen) (kill-whole-line 1)) (message "Heading deleted : %s" org-heading-text))) Using recorded macros as functions: (fset 'throwtext-c "x\C-w\C-wGp") (fset 'kindle-clippings-to-org-macro (save-excursion (kmacro-lambda-form [?d ?d ?$ ?d ?% ?O ?\s-p escape ?d ?s ?b ?O ?* ? escape ?J ?o ?* ?* ? escape ?J ?j ?^ ?d ?w ?d ?w ?l ?v ?e ?~ ?I ?* ?* ?* ? escape ?w ?d ?w ?f ?| ?r return ?d ?w ?d ?w ?V ? ?\; ?c ?o ?n ?v ?e ?r ?t return ?j ?d ?d ?V ?\C-s ?f ?n] 0 "%d"))) Capturing (copying / appending to a certain location, depending on your config / provided template) highlighted text from a PDF file opened in Emacs: (defun org-capture-pdf-c (action) "Capture the active region of the pdf-view buffer." (let* ((pdf-buf-name (plist-get org-capture-plist :original-buffer)) (pdf-buf (get-buffer pdf-buf-name))) (if (buffer-live-p pdf-buf) (cond ((= action 1) (with-current-buffer pdf-buf (buffer-name))) ((= action 2) (with-current-buffer pdf-buf (buffer-file-name))) ((= action 3) (with-current-buffer pdf-buf (if (pdf-view-active-region-p) (car (pdf-view-active-region-text)) (ignore-errors (buffer-substring-no-properties (region-beginning) (region-end)))))) ((= action 4) (with-current-buffer pdf-buf (number-to-string (pdf-view-current-page))))) (user-error "Buffer %S not alive." pdf-buf-name)))) Traversing text programmatically: (defun comments-skip-c () "Skips to the line after the next comment ends" (interactive) (search-forward-regexp comment-start-skip) (while (string-match comment-start-skip (buffer-substring (line-beginning-position) (line-end-position))) (forward-line))) Making windows larger by a ratio: (defun make-window-larger-c (&optional ratio) "Makes the current window larger or smaller. RATIO is the ratio used, default is 0.618. It switches the width before the height." (interactive) (save-excursion (let\* ((postv (if olivetti-mode (progn (olivetti-mode -1) t) nil)) (wwidth (window-width)) (wheight (window-height)) (fwidth (frame-width)) (fheight (frame-height)) (ratio (if ratio ratio 0.618)) (fl/fheight (floor (\* ratio fheight))) (fl/fwidth (floor (\* ratio fwidth)))) (if (window-full-width-p) (if (window-full-height-p) (message "Nothing to resize.") (if (>= wheight fl/fheight) (if (>= wwidth fl/fwidth) (message "Nothing to resize.") (enlarge-window (- fl/fwidth wwidth) t)) (enlarge-window (- fl/fheight wheight)))) (if (>= wwidth fl/fwidth) (if (>= wheight fl/fheight) (message "Nothing to resize.") (enlarge-window (- fl/fheight wheight))) (enlarge-window (- fl/fwidth wwidth) t))) (if postv (olivetti-mode 1))))) Querying a SQLite DB for entries and showing them in a selectable list; selected entry is copied to clipboard. (require 'sqlite3) (defun kill-new-from-global-paste-c () (interactive) (let ((mylist '())) (let* ((dbh (sqlite3-open "/home/user/.local/share/zeitgeist/activity.sqlite" sqlite-open-readonly)) (stmt (sqlite3-prepare dbh "select * from text order by id desc limit 500"))) (while (= sqlite-row (sqlite3-step stmt)) (cl-destructuring-bind (id text) (sqlite3-fetch stmt) (setq mylist (nconc mylist (list text))))) (sqlite3-finalize stmt) (sqlite3-close dbh)) (kill-new (let* ((vertico-sort-function nil) (rlist (completing-read-multiple " " mylist)) (rstr "")) (while (length> rlist 0) (setq rstr (concat rstr (pop rlist) "\n"))) rstr)))) EDIT: Oh, and changing the "face" (appearance) of text is also very easy. It's easy to make your own syntax highlighting rules or even highlight stuff according to a regex temporarily.