diff --git a/out.md b/out.md index d7e75db..5891da9 100644 --- a/out.md +++ b/out.md @@ -1,6 +1,242 @@ -## u/vkazanov [πŸ”—](https://www.reddit.com/r/emacs/comments/1bdm6mc/comment/kuo1f9y) +## u/TheDrownedKraken [πŸ”—](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h2rdkkz) +**Votes:** 34 + +Do you think it might be good to make this a little less frequently refreshed? There are usually some great tips that get lost to Reddit’s ephemerality pretty quickly. + +I think monthly would be better, given the modest size of this subreddit. + +## u/celeritasCelery [πŸ”—](https://www.reddit.com/r/emacs/comments/gienra/comment/fqe6yop) +**Votes:** 34 + +> I had received the advice to not install anything and just start with plain emacs so I can learn emacs. ... it was miserable. +> Enter Doom Emacs. I decided to give Doom Emacs a try because it was also highly recommended in my initial RFC, especially since it is designed for Vim users. In short I love it. + +This is why I disagree with the subreddits de facto advice to β€œlearn vanilla first”. People who have used emacs for a long time don’t realize how much **time** it takes to get it to level of a normal modern editor people are used to. I recommend distros to *everyone* who is new unless they are that certain personality type that wants to do everything themselves. + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/10qo7vb/comment/j6rmvvf) +**Votes:** 33 + +When you have an active region, `undo` will only undo changes in that region instead of the whole file. + +## u/gausby [πŸ”—](https://www.reddit.com/r/emacs/comments/e5dzv6/comment/f9jp341) +**Votes:** 33 + +Shouldn't it be `/etc/tips/trick` ? + +(…I'll show myself out) + +## u/zupatol [πŸ”—](https://www.reddit.com/r/emacs/comments/xdw6ok/comment/iodig8c) +**Votes:** 29 + +After years of using emacs, I wrote my second ever elisp function to open on github the code I'm browsing in emacs. + +```elisp +(defun open-on-github () + (interactive) + (let + ((repo-url (magit-git-string "remote" "get-url" "--push" "origin")) + (commit-hash (magit-git-string "rev-parse" "HEAD")) + (start-line (if (use-region-p) + (line-number-at-pos (region-beginning)) + (line-number-at-pos))) + (end-line (if (use-region-p) (line-number-at-pos (region-end))))) + (unless repo-url (error "not in a git repo")) + (browse-url + (concat + (substring repo-url 0 -4) + "/blob/" + commit-hash + "/" + (substring buffer-file-name (length (projectile-project-root))) + "#L" (number-to-string start-line) + (if (and (use-region-p) (< 0 (- end-line start-line))) + (concat "..L" (number-to-string end-line))) + )))) +``` + +## u/unbelievable_sc2 [πŸ”—](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f81dslh) +**Votes:** 28 + +I often use the compile feature to compile and run my projects to see the results in the compilation buffer. This works well unless you are waiting for user input in your terminal. I recently found out that you can invoke the compile with an additional non nil value to start compilation in comint-mode which allows for user input! +The drawback is, that you then no longer can press q to close the window or g to recompile. Because of that I added a simple lambda, that switches to compilation-mode to the compilation-finish-functions. So I can give input while compiling and running, and after compilation I can close the window as usual with q. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3m1liu) +**Votes:** 26 + +[removed] + +## u/Gangsir [πŸ”—](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hepqmq1) +**Votes:** 22 + +back-to-indentation. Before I found this function I would always do some awkward triple key combo like C-a M-f M-b. + +It's just bound to M-m. Jumps you right to the first non-white space character on the line. What's even spicier is that it works in reverse too - if you're at the front of the line it jumps you forward, if you're at the end or middle it jumps backward. + +It still works even on lines that aren't indented, same as C-a in that case. + +So useful, especially for resetting point during macros that need to start at the first char on the line. + +## u/howardthegeek [πŸ”—](https://www.reddit.com/r/emacs/comments/xdw6ok/comment/ioeh1ly) +**Votes:** 21 + +I just learned that in eshell, $$ is replaced with the output from the last command. + +## u/thehaas [πŸ”—](https://www.reddit.com/r/emacs/comments/e5dzv6/comment/f9k6yyf) +**Votes:** 21 + +After using Emacs for maybe 10 years I finally started using registers and I really should have started earlier. For those who don't know: + +​ + +* Highlight text and C-x r s to save to register +* C-x r i to put the contents of the register at the cursor point. The text is still there -- use it over and over again + +It seems like quite a few keystrokes but it's really not. Of course you can re-assign them to other keys if you don't like the defaults. + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8m9rlj) +**Votes:** 20 + +With an active region, you can freely toggle between rectangle mark mode and normal, you don't need to get rid of your active region to switch between the two. + +## u/AndreaSomePostfix [πŸ”—](https://www.reddit.com/r/emacs/comments/12cd23k/comment/jf167qh) +**Votes:** 19 + +org-mode is amazing! + +I discovered \`org-copy-visible\` the other day, when I wanted to send somebody only the outline of my notes. + +That function (which is bound to C-c C-x v by default) let you copy just the outline for the selected region: very useful! + +## u/sauntcartas [πŸ”—](https://www.reddit.com/r/emacs/comments/vnals8/comment/ie7p6ja) +**Votes:** 18 + +I recently discovered `thing-at-point-looking-at`, which seems much easier to use on its own than to fully define a new kind of "thing." + +For a while I've been wanting to conveniently identify a Jira ticket identifier at point so I can browse to it. Ticket IDs are basically a sequence of letters, a hyphen, and a sequence of digits. First I tried using `symbol-at-point`, but that can include extraneous neighboring characters, like `/` when the ticket ID is part of a URL. Eventually, while poring over the `thingatpt` source, I found `thing-at-point-looking-at`, which quickly led to: + +```elisp +(defun browse-ticket-at-point () + (interactive) + (if (thing-at-point-looking-at (rx (+ alpha) "-" (+ digit))) + (browse-url (format "https://jirahost/browse/%s" (match-string 0))) + (error "No ticket at point"))) + +``` +Easy peasy! + +## u/tryptych [πŸ”—](https://www.reddit.com/r/emacs/comments/v2by7z/comment/iauyzbl) +**Votes:** 18 + +It's not worth a separate post, but after spending some pleasant yak-shaving time optimising my startup using use-package, I wrote a [post about it](https://blog.markhepburn.com/posts/understanding-use-package-optimisations/). There's a few posts around suggesting features of `use-package` to optimise startup, but none of them really explained how they tied back to `autoload`, `eval-after-load`, etc so I was trying to encourage people to dig out `macroexpand` and find out. + +## u/TeMPOraL_PL [πŸ”—](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3ov7vq) +**Votes:** 18 + +`shortdoc` - one of the new things in Emacs 28.1 - is great for maintaining your own "cheat sheets" of Elisp functions as you discover them. For example, eval this in your Emacs session: + +```elisp +(define-short-documentation-group my-datetime + "Querying current time" + (current-time + :eval (current-time)) + (float-time + :eval (float-time)) + + "Time formats" + (time-convert + :eval (time-convert (current-time)) + :eval (time-convert (current-time) 'list) + :eval (time-convert (current-time) 100000) + :eval (time-convert (current-time) 200000) + :eval (time-convert (current-time) t) + :eval (time-convert (current-time) 'integer)) + + (float-time + :eval (float-time (current-time)))) + +``` +After this, the `my-datetime` group will show as an option in `M-x shortdoc-display-group`. Additionally, if you view help for any of the functions mentioned above, the Help buffer will refer back to the `my-datetime` shortdoc group! + +The example used here is a cheatsheet I just started writing for myself, as I've been researching the built-in time functions. For additional instructions on use, see `define-short-documentation-group` macro. For use examples, jump to the source of `define-short-documentation-group` and scroll down a bit - the default shortdoc groups are defined there. + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h2rizey) +**Votes:** 18 + +I have two org mode link tips: + +1. `(setq org-return-follows-link t)` lets you press RET to follow a + link. Don't worry, the traditional behavior of RET, namely inserting + a newline, is still easy: `C-q C-j`. + +2. I often want to see what the destination of a link is. I used to + use one of these methods: + + - mouse hover, + - running and canceling `org-insert-link` (`C-c C-l`, read the +```elisp + destination, `C-g`), +``` + - `org-toggle-link-display`, which toggles between the neat formatting of +```elisp + links and the raw source and is pretty ugly. + +``` + But a better option is to use `display-local-help` (`C-h .`), which + will show the tooltip in the echo area. And, you can even have the + tooltip at point echoed automatically with `(setq + help-at-pt-display-when-idle t)`. There is a delay controlled by + the variable `help-at-pt-timer-delay` which I like to set to 0. + Beware that just using `(setq help-at-pt-timer-delay 0)` has no effect, + you need to use `customize-set-variable` or manually cancel the + timer and set a new one (see below). + + Now, these `help-at-pt` variables aren't specifically for org + links, they control the behavior of all tooltips, and I quickly + realized I really only wanted to change the behavior in org mode + buffers. You can do that as follows: + +```elisp + (defun echo-area-tooltips () + "Show tooltips in the echo area automatically for current buffer." + (setq-local help-at-pt-display-when-idle t + help-at-pt-timer-delay 0) + (help-at-pt-cancel-timer) + (help-at-pt-set-timer)) + + (add-hook 'org-mode-hook #'echo-area-tooltips) +``` + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/12rlq4a/comment/jgwlxuw) +**Votes:** 17 + +Often when literate programming I want to split up a code block, maybe copy-pasted with multiple functions in it, into separate blocks so I can put some text in between them. The command, with cursor within a `BEGIN_SRC` block, is `org-babel-demarcate-block` `(C-c C-v d)`. + +## u/alvarogonzalezs [πŸ”—](https://www.reddit.com/r/emacs/comments/12jexep/comment/jg34ody) +**Votes:** 17 + +I'm a big user of `ffap`. I use this function with `M-x` each time I want to open a file whose name is under the cursor. + +But this week I discovered `ffap-bindings`. This function replaces some key bindings to use `ffap` when it makes sense. For example, it replaces `find-file` with `find-file-at-point`, so the usual keybindings are enriched at no cost. + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/x27yc9/comment/imi3kzz) +**Votes:** 17 + +Update from a couple of weeks ago: after some grinding, I've set the parsing of past comments from this thread to auto update on a weekly basis here: [https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md](https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md) + +I've also fixed the broken highlighting of some code snippets, and hopefully parsed all past threads. There's 200+ comments there (sorted by upvotes), so ctrl-f ing e.g. \`magit\` may help you if you're looking for something specific + +## u/SamTheComputerSlayer [πŸ”—](https://www.reddit.com/r/emacs/comments/sijcap/comment/hvbbnjq) **Votes:** 17 +Just figured this out, maybe a bit of a hack... + +In flyspell, I was annoyed I had to use mouse-2 when I wanted to correct a word, and I didn't want to sacrifice a major-mode keybinding to do it from the keyboard. But flyspell actually creates an overlay for misspelled words and attaches a keymap to it, which you can do I just realized- very cool. So I just bound `flyspell-correct-at-point` to "" in the `flyspell-mouse-map`, and now return corrects words when my cursor is on a misspelled word! + +But the fact you can attach keymaps to overlays just seems so useful, will definitely use in the future. + +## u/vkazanov [πŸ”—](https://www.reddit.com/r/emacs/comments/1bdm6mc/comment/kuo1f9y) +**Votes:** 16 + A dump of my Emacs-related principles after 18 years of tinkering: 1. Don't try to replicate a static IDE setup, Emacs is fluid. @@ -15,20 +251,3711 @@ A dump of my Emacs-related principles after 18 years of tinkering: I am a beginner though, things might change. -## u/geza42 [πŸ”—](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/ksifwh1) -**Votes:** 12 +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/1758wua/comment/k4g09iw) +**Votes:** 16 -If you use an LSP server with semantic highlighting, it's worth checking out the value of `font-lock-maximum-decoration`. For example, I use `c++-mode` with `lsp-mode` (with clangd), I decreased `font-lock-maximum-decoration` to `2`, and I didn't notice any highlighting difference (because the lost highlighting by `c++-mode` gets highlighted by `lsp-mode`), while `c++-mode` font-locking become faster (`c++-mode` 's font-locking works well 99.9% of the time, but sometimes it can become slow in some circumstances, these slowdowns seems to be gone). +`(delete-blank-lines)` `(C-x C-o)` is massively useful; I use it every day for text cleanup. Press it once and it deletes all but one blank line. Press it twice and it deletes that one, too. -I use:`(setq font-lock-maximum-decoration '((c-mode . 2) (c++-mode . 2) (t . t)))` +## u/agumonkey [πŸ”—](https://www.reddit.com/r/emacs/comments/y7wrdn/comment/isze25m) +**Votes:** 16 -## u/LionyxML [πŸ”—](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/kslwb72) -**Votes:** 8 +not emacs per se, but jack rusher did a talk about programming 'ux / ergonomics / pragmatics' with a lot of fun ideas about coding, past (lisp machines, smalltalk ... ) or more recent clojure based tools -A blog post regarding my own Emacs config aiming to get the same user experience on both TUI and GUI. -[https://www.rahuljuliato.com/posts/lemacs](https://www.rahuljuliato.com/posts/lemacs) +https://www.youtube.com/watch?v=8Ab3ArE8W3s -## u/demosthenex [πŸ”—](https://www.reddit.com/r/emacs/comments/1b7uj43/comment/ktogga6) +hope you enjoy it + +warning: poop emoji + +## u/slinchisl [πŸ”—](https://www.reddit.com/r/emacs/comments/xw4muy/comment/ir96qmu) +**Votes:** 16 + +I finally got around to writing a small README for my Emacs config, highlighting some homegrown parts that I really like. I reckon most of these things are pretty standard, but maybe some people here still find it useful: + + https://gitlab.com/slotThe/dotfiles/-/tree/master/emacs/.config/emacs + +## u/pathemata [πŸ”—](https://www.reddit.com/r/emacs/comments/un4wf8/comment/i86hwzi) +**Votes:** 16 + +Something amazin that I have been using recently is `ripgrep-all` as the `consult-ripgrep` command to search in pdfs. + +It is amazing with the `orderless` dispatchers to control the search filtering. +I use `!` to exclude a string and `=` to match exactly. + +Also amazing with `embark-collect` which allows collapsing features. +Or within the collect buffer use `consult-line` to further filter. +And even open the pdf. + +## u/AffectionateAd8985 [πŸ”—](https://www.reddit.com/r/emacs/comments/sd10q9/comment/hu9xfed) +**Votes:** 16 + +`(add-hook 'org-mode-hook (lambda () (org-next-visible-heading 1)))` + +Move to first heading when open org files, with `org-use-speed-commands`, I can quick browse org file with only `n/p` keys. + +## u/hxlr666 [πŸ”—](https://www.reddit.com/r/emacs/comments/rvagin/comment/hr4bbl5) +**Votes:** 16 + +Use org capture + +## u/TeMPOraL_PL [πŸ”—](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnx4z28) +**Votes:** 16 + +If you're like me, and your day ends way past midnight, handling those last few tasks in your Org Mode agenda gets tricky. Fortunately, it turns out Org Mode has what I call "25th hour mode". + +```elisp +;; consider the current day to end at 3AM +(setq org-extend-today-until 3) + +;; make timestamp processing functions aware of this +(setq org-use-effective-time t) + +``` +Combined, this allows to extend the day past midnight, with things like agenda views, scheduling commands, repeaters, etc. thinking the current time is 23:59 up until the `org-extend-today-until` limit. With this enabled, if I have a task that has a repeater of and complete it at 01:00, I no longer have to then manually reschedule the task back one day. + +## u/github-alphapapa [πŸ”—](https://www.reddit.com/r/emacs/comments/p6mwx2/comment/h9e6uqq) +**Votes:** 16 + +Here's a popular Emacs config I just rediscovered. Some cool stuff here. https://github.com/angrybacon/dotemacs + +## u/gopar [πŸ”—](https://www.reddit.com/r/emacs/comments/k4gv0x/comment/ge9det9) +**Votes:** 16 + +A very simple thing I've done is remap ";" (semicolon) to to "\_" (underscore) in almost all modes. Since I work with mainly Python, this is so much easier than always doing SHIFT-DASH every couple of keystrokes. And if I want a regular semicolon, I just do "C-u ;" and insert a semicolon + +I also set this in modes such as C/C++, etc. This works by automatically setting the last character (if it was an underscore) to a semicolon on enter. + +eg. "|" is cursor + +int a = 10\*10\_| + +turns into + +int a = 10\*10; + +| (cursor on new line) + +​ + +Pretty simple time saver \\o/ + +## u/com4 [πŸ”—](https://www.reddit.com/r/emacs/comments/xq6rpa/comment/iqb2fci) +**Votes:** 15 + +In preparation for the inclusion of eglot into Emacs core I've switched away from lsp-mode. As a result I've also switched from flycheck and to flymake. One nice thing about flycheck is that it allowed for stacking checkers. When coding Python I liked to stack flake8 for styles and mypy for types (plus the LSP's since it's already there). + +Flymake allows for stacking checkers but it turns out eglot clobbers these checkers when "adding" the LSP's checker. To get stacked Flymake checkers with Eglot you can simply add them back after Eglot has done it's thing. + +For example, here is a simple setup for Python which includes Pyright's type checking and flake8 style checking + +```elisp +;; Use flake8 as the python style checker by default +(setq python-flymake-command '("flake8" "-")) + +(use-package eglot + :hook ((python-mode . eglot-ensure) + (eglot-managed-mode + . (lambda () + ;; re-enable flymake checkers because eglot clobbers + ;; them when starting + (when (derived-mode-p 'python-mode) + (add-hook 'flymake-diagnostic-functions + 'python-flymake nil t))))) + + :custom + ;; shutdown server after killing last managed buffer + (eglot-autoshutdown t) + :bind + (("C-c l r" . eglot-rename)) + :config + (add-to-list 'eglot-server-programs + `(python-mode "pyright-langserver" "-w" "--stdio"))) + +``` +Now all that's left is mypy. Flymake originally used a ["Proc"](https://www.gnu.org/software/emacs/manual/html_mono/flymake.html#The-legacy-Proc-backend) method for creating checkers which existing mypy ones use. So for a bonus tip & trick [I've written a mypy checker in the new style](http://github.com/com4/flymake-mypy). It can be enabled when using eglot like this: + +```elisp +(use-package flymake-mypy + :straight (flymake-mypy + :type git + :host github + :repo "com4/flymake-mypy") + :hook ((eglot-managed-mode . (lambda () + (when (derived-mode-p 'python-mode) + (flymake-mypy-enable)))))) + +``` +After opening a Python buffer and executing `M-x flymake-running-backends` we are greeted with a list of stacked checkers: `Running backends: eglot-flymake-backend, flymake-mypy--run, python-flymake`. + +## u/meain [πŸ”—](https://www.reddit.com/r/emacs/comments/wwdpju/comment/ilotsc5) +**Votes:** 15 + +I use the following snippet to change background color of compilation buffer to a light red if the compilation failed. I use compilation buffer to run tests on a second monitor and this is pretty useful. + +```elisp +(defun meain/compilation-colorcode (_buffer string) + "Change background color of compilation `_BUFFER' to red on failure." + (unless (string-prefix-p "finished" string) ; Having color for success was distracting + (face-remap-add-relative 'default 'diff-hl-delete))) +(add-to-list 'compilation-finish-functions 'meain/compilation-colorcode) +``` + +## u/el_tuxo [πŸ”—](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnp5rhn) +**Votes:** 15 + +Working on a remote server with Tramp in eshell it's so easy that I'm always worried that I could run by mistake a command on the wrong machine. + +So I implemented a small function that makes me aware that I'm in a Tramp session by changing the prompt color. + +```elisp +(require 'subr-x) +(defun tuxo/prompt-color-tramp () +"Change prompt color if a tramp session is open" + (if (file-remote-p default-directory) + (set-face-foreground 'eshell-prompt "red") + (set-face-foreground 'eshell-prompt "green"))) + +(use-package eshell + :hook (eshell-post-command . tuxo/prompt-color-tramp)) + +``` +Do you have any suggestions on how I could improve this issue? + +## u/globalcandyamnesia [πŸ”—](https://www.reddit.com/r/emacs/comments/ooldn6/comment/h67qge6) +**Votes:** 15 + +I'm trying to feminize my voice and org mode has been invaluable. + +```elisp +(org-babel-do-load-languages 'org-babel-load-lanuages + '((shell . t))) + +(setq org-capture-templates + `(("v" "Voice" entry + (file+olp+datetree ,(concat my-org-directory "voice/training.org")) + ,(concat + "* Record \n" + "\n" + " #+begin_src sh\n" + " rec %(format-time-string \"%Y-%m-%d-%H.%M.%S\").aiff\n" + " #+end\_src\n" + "\n" + "* Play\n" + " #+begin_src sh\n" + " play %(format-time-string \"%Y-%m-%d-%H.%M.%S\").aiff\n" + " #+end_src\n") + :immediate-finish t + :jump-to-captured t))) + +``` +This requires 'SoX' for linux. You can go into the record src block and press \`C-c C-c\` to start recording and \`C-g\` to end. To play back the recording, press \`C-c C-c\` within the play src block. I imagine this might be useful beyond the trans community for basic voice journaling. + +## u/Tatrics [πŸ”—](https://www.reddit.com/r/emacs/comments/n9q662/comment/gxpeh9v) +**Votes:** 15 + +I'm slowly working on an alternative shell: [https://github.com/TatriX/tshell](https://github.com/TatriX/tshell) + +Instead of using repl-like interface, all the commands go to one buffer (and file if you want) and output goes to another buffer. Like if you put your elisp code in \*scratch\* buffer and then evaluate it with \`C-x C-e\`. + +It's in a very early stage, but it already allows me to solve most tasks I usually do with more traditional shells. + +Let me know what is your first impression, what can be improved and what do you think in general! + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/mujxm7/comment/gv8jxz5) +**Votes:** 15 + +I use, and love, [transient](https://github.com/magit/transient). I have a ton of commands set up, but the below command is for window manipulation. Personally, I bind it to `s-w`. I use [buffer-move](https://github.com/lukhas/buffer-move) for rearranging windows in a frame. + +```elisp +(define-transient-command transient-window () + "Most commonly used window commands" + [["Splits" + ("s" "Horizontal" split-window-below) + ("v" "Vertical" split-window-right) + ("b" "Balance" balance-windows) + ("f" "Fit" fit-window-to-buffer) + ["Window" + ("c" "Clone Indirect" clone-indirect-buffer) + ("t" "Tear Off" tear-off-window) + ("k" "Kill" delete-window) + ("K" "Kill Buffer+Win" kill-buffer-and-window) + ("o" "Kill Others" delete-other-windows) + ("m" "Maximize" maximize-window)] + ["Navigate" + ("" "←" windmove-left :transient t) + ("" "β†’" windmove-right :transient t) + ("" "↑" windmove-up :transient t) + ("" "↓" windmove-down :transient t)] + ["Move" + ("S-" "S-←" buf-move-left :transient t) + ("S-" "S-β†’" buf-move-right :transient t) + ("S-" "S-↑" buf-move-up :transient t) + ("S-" "S-↓" buf-move-down :transient t)] + ["Undo/Redo" + ("s-z" "Winner Undo" winner-undo :transient t) + ("s-Z" "Winner Redo" winner-redo :transient t)]]) +``` + +## u/TheDrownedKraken [πŸ”—](https://www.reddit.com/r/emacs/comments/jn6m14/comment/gazzdyz) +**Votes:** 15 + +It would be good to archive the questions and tips put in here. I feel like I always find cool stuff in here, but then it becomes very hard to find it later. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/hqxm5v/comment/fy1rq34) +**Votes:** 15 + +Migrated to native compiled emacs branch this week. Some hiccups but everything seems to work out of box, including pdf-tools. Great performance improvement. + +## u/freesteph [πŸ”—](https://www.reddit.com/r/emacs/comments/eoigxl/comment/fed40nx) +**Votes:** 15 + +If you needed more reasons to love Magit I've just found out can add the Git meta-fields in the commit message (`Co-authored-by`, `Signed-off-by`, etc, which I can never remember correctly) by typing `C-c TAB` which will interactively ask you for the field (`C-a` -> `Co-authored-by`) and then also interactively fill the relevant team member with their name and e-mail (probably from the repo's list of committers). Awesome! + +## u/laralex [πŸ”—](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5pgfu3) +**Votes:** 15 + +A small basic thing, but once I'd discovered it, I started using dired. +```C-x C-j``` is most likely bound to ```dired-jump```, and this function opens dired for this window's file, without promting for directory (and this prompt was an issue for my workflow when using ```C-x d```). That makes finding and switching files just as convenient as in OS GUI. I've also bound a few keys when in dired mode (I find them decent): + +```a``` - prompt a name and create empty file + +```d``` - prompt a name and create empty dir + +```u``` - go to parent dir (the key is a mnemonic to "go Up in directory tree) + +```j``` - if it's a dir go into it, otherwise find this file (key is near to 'u' so jumping up and down is not a big deal with one hand, also the 'j' is the easiest key for me as a touchtyper) + +```n```/```p``` - move one entry down/up, which resembles ```C-n```/```C-p``` + +## u/geza42 [πŸ”—](https://www.reddit.com/r/emacs/comments/11lqkbo/comment/jbe06qv) +**Votes:** 14 + +You can toggle vertico's height between 15 and "almost full frame" with this. When vertico is invoked, it will always have a height of 15. But if you have a lot of matches, and like to have a better overview, press the binding, and vertico will show a full frame of matches. This is useful for example when `consult-buffer` presents a lot of buffers. + +```elisp +(advice-add 'vertico--setup :before (lambda () (setq vertico-count 15))) +(define-key minibuffer-local-map (kbd "s-'") (lambda () + (interactive) + (let ((vertico-resize t)) + (setq vertico-count (if (= vertico-count 15) (- (frame-height) 5) 15)) + (vertico--exhibit)))) + +``` +Another useful feature is to kill buffers in `consult-buffer` without manually invoking `embark-act`. I miss this feature from Helm, where you can do actions using only one binding (no need to press an intermediate binding which invokes `embark-act`). Note, I just blindly copied some of the logic from `embark`, maybe there are some unnecessary things here. + +```elisp +(defun my-embark-M-k (&optional arg) + (interactive "P") + (require 'embark) + (if-let ((targets (embark--targets))) + (let* ((target + (or (nth + (if (or (null arg) (minibufferp)) + 0 + (mod (prefix-numeric-value arg) (length targets))) + targets))) + (type (plist-get target :type))) + (cond + ((eq type 'buffer) + (let ((embark-pre-action-hooks)) + (embark--act 'kill-buffer target))))))) + +(define-key minibuffer-local-map (kbd "M-k") 'my-embark-M-k) + +``` +I'm not sure whether these two can be achieved out-of-the box, but I didn't find these functionalities, so I created them. + +## u/gusbrs [πŸ”—](https://www.reddit.com/r/emacs/comments/y1y0kq/comment/is1ygyw) +**Votes:** 14 + +I've been using `mu4e` for some years now, and I really love it. However, I'm also a Gmail user, don't love it, but consider myself stuck with it (given budget constraints and it being my email for several years already). This makes me always weary of "the next Google shenanigan" which might break my workflow. One of the things I have learned to cherish about using `mu4e` is its integration with Org, with it's `org-capture` support, which enables me not to confuse my Inbox with my todo list, thus keeping my Inbox clean. So I came up with a preventive function, leveraging `org-protocol` to be able to capture a Gmail message from a bookmarklet on the browser. Not particularly pretty code, but functional. + +```elisp +(with-eval-after-load 'org + ;; Add org-protocol to capture email in Gmail. + (add-to-list 'org-protocol-protocol-alist + '("org-gmail-capture" :protocol "gmail-capture" + :function gb/org-protocol-gmail-capture)) + + ;; Bookmarklet: + ;; javascript:location.href = 'org-protocol://gmail-capture?' + + ;; new URLSearchParams({ + ;; msg: document.getElementById("raw_message_text").innerHTML}); + ;; Must be called from the "Original message" page. + (defun gb/org-protocol-gmail-capture (info) + "Process an org-protocol://gmail-capture style url with INFO. + +This function detects the raw message text element from the \"Original +message\" page of a Gmail message. It then parses relevant message +fields and calls the \"email\" org-capture template. + +The location for a browser's bookmark looks like this: + + javascript:location.href = \\='org-protocol://gmail-capture?\\=' + + new URLSearchParams({ + msg: document.getElementById(\"raw_message_text\").innerHTML}); + +The sub-protocol used to reach this function is set in +`org-protocol-protocol-alist'." + (when-let* ((parts (org-protocol-parse-parameters info)) + (msg (plist-get parts ':msg))) + ;; FIXME I'm not sure why this is needed, but the protocol fails on a + ;; fresh session (before 'org-capture' is loaded), and the new frame + ;; just flashes on the screen. + (require 'org-capture) + (let (subj id to from date + from-name from-email to-name to-email from-to-name) + (with-temp-buffer + (insert msg) + ;; 'mu4e~view-render-buffer' is responsible in mu4e to view / + ;; display a new message, it handles decoding, fontification + ;; etc. However, the message we get from org-protocol is not + ;; really the "original" it is rather a html rendered version of + ;; it. A "Download original" button exists, but we wouldn't be + ;; able to retrieve it, since only the browser is logged into + ;; the Gmail account, so we have to do with whatever the page + ;; displays. That given, prettifying the buffer is of little + ;; use for the fields we are interested in. + (goto-char (point-min)) + (let ((case-fold-search)) + (while (re-search-forward + (rx + line-start + (group + (or + "From:" + "To:" + "Subject:" + "Date:" + "Message-ID:")) + " " + (group (zero-or-more not-newline)) + line-end) + nil t) + (pcase (match-string 1) + ("From:" (setq from (match-string 2))) + ("To:" (setq to (match-string 2))) + ("Subject:" (setq subj (match-string 2))) + ("Date:" (setq date (match-string 2))) + ("Message-ID:" (setq id (match-string 2))))))) + + ;; Ensure values + (when (or (not from) (string-blank-p from)) + (setq from "")) + (when (or (not to) (string-blank-p to)) + (setq to "")) + (when (or (not subj) (string-blank-p subj)) + (setq subj "No subject")) + (unless date (setq date "")) + (unless id (setq id "")) + ;; Clean fields + (setq from (replace-regexp-in-string "<" "<" from t t)) + (setq from (replace-regexp-in-string ">" ">" from t t)) + (setq to (replace-regexp-in-string "<" "<" to t t)) + (setq to (replace-regexp-in-string ">" ">" to t t)) + (setq id (replace-regexp-in-string "<" "" id t t)) + (setq id (replace-regexp-in-string ">" "" id t t)) + + (let ((addr (mail-extract-address-components from))) + (if (car addr) + (progn + (setq from-name (car addr)) + (setq from (format "%s <%s>" (car addr) (cadr addr)))) + (setq from-name (cadr addr)) + (setq from (format "<%s>" (cadr addr)))) + (setq from-email (cadr addr))) + (let ((addr (mail-extract-address-components to))) + (if (car addr) + (progn + (setq to-name (car addr)) + (setq to (format "%s <%s>" (car addr) (cadr addr)))) + (setq to-name (cadr addr)) + (setq to (format "<%s>" (cadr addr)))) + (setq to-email (cadr addr))) + (setq from-to-name + (if (member from-email + '("myemail1@domain.com" + "myemail2@domain.com" + "myemail3@domain.com" + "myemail4@domain.com")) + to-name + from-name)) + + (let ((props `(:type "gmail" + :date ,date + :from ,from + :fromname ,from-name + :message-id ,id + :subject ,subj + :to ,to + :toname ,to-name + :annotation ,(org-link-make-string + (concat "gmail:" id) subj) + :link ,(org-link-make-string (concat "gmail:" id)) + :description ,(format "%s (%s)" subj from-to-name) + :annotation ,(concat "gmail:" id))) + ;; Avoid call to `org-store-link', see 'org-protocol-capture'. + (org-capture-link-is-already-stored t)) + (apply #'org-link-store-props props) + + (raise-frame) + ;; Hard-coding the "e" capture template, since this function is very + ;; much tailor made for it. + (org-capture nil "e"))) + ;; Make sure we do not return a string, see 'org-protocol-capture'. + nil)) + + (org-link-set-parameters "gmail" :follow #'gb/org-link-gmail-open) + (defun gb/org-link-gmail-open (link _) + (kill-new (concat "rfc822msgid:" link)) + (message "Message id copied to clipboard."))) + +``` +The corresponding bookmarklet is: + +```elisp +javascript:location.href = 'org-protocol://gmail-capture?' + new URLSearchParams({msg: document.getElementById("raw_message_text").innerHTML}); + +``` +This must be called from the "Original message" page (which you can get with the "Show original" menu item). It won't work elsewhere. + +The link created is a `gmail:` type link which essentially just copies `rfc822msgid:` to the kill-ring/clipboard, which you can paste in Gmail's search bar to go to the message of interest. + +Not that it matters much, but the corresponding capture template is: + + +```elisp + ("e" "email" entry + (file+headline (lambda () + (expand-file-name gb/email-capture-file + gb/org-files-directory)) + "Email") + "* TODO %?%:description %(org-set-tags \":email:\") +:PROPERTIES: +:Message: %a +:From: %:from +:To: %:to +:Date: %:date +:END: +:LOGBOOK: +- Created on %U +:END:" + :empty-lines 1) +``` + +## u/thr33body [πŸ”—](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikqxn0r) +**Votes:** 14 + +I don’t have any specific tip but I just want to throw it out there that if you are tired of using spacemacs or doom it was much easier to set up my own install than I thought. It only took me a couple of days of active work and now diagnosing problems is so much simpler. Not to say that you should not use either one but I wanted to learn more about emacs and I’ve been really happy with the results. + +## u/rucci99 [πŸ”—](https://www.reddit.com/r/emacs/comments/r69w7i/comment/hmryv5o) +**Votes:** 14 + +I just found out that Magit can backup changes of uncommitted files automatically. Here's the link to online manual: +[Magit Wip Modes](https://magit.vc/manual/magit/Wip-Modes.html#Wip-Modes). + +## u/Stefan-Kangas [πŸ”—](https://www.reddit.com/r/emacs/comments/q76kok/comment/hgk3wik) +**Votes:** 14 + +This is pretty neat: scrolling up/down one line at a time while keeping the position of point: + +`(setq scroll-preserve-screen-position 1)` +`(global-set-key (kbd "M-n") (kbd "C-u 1 C-v"))` +`(global-set-key (kbd "M-p") (kbd "C-u 1 M-v"))` + + +From: http://pragmaticemacs.com/emacs/scrolling-and-moving-by-line/ + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/lapujj/comment/glr8pkr) +**Votes:** 14 + +You can use EWW to bypass pay-walls on news sites, and other Javascript-enabled nastiness. Plus, eww can copy from what it sees into equivalent orgmode syntax, and it's also compatible with SPRAY for speed-reading. In otherwords, EWW is great for when you just need to READ the internet. + +## u/sauntcartas [πŸ”—](https://www.reddit.com/r/emacs/comments/fs93hk/comment/fm1fw1x) +**Votes:** 14 + +For me, learning about `kill-whole-line` (control-shift-delete) was a revelation. Compared to the "classic" Emacs method of deleting lines (C-a to go to the beginning of the line if not already there, C-k once to kill to the end of line, C-k again to kill the newline), it feels like a major speedup. + +I still use C-k frequently, but it's effectively just a kill-to-end-of-line command. + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/fgahb2/comment/fk3in25) +**Votes:** 14 + +Most people probably know that `M-t` (`transpose-words`) when used between two words swaps them. But it has other a few other features that are useful: + +- You don't have to be between words to use it: if you are on a word, from the second character on, it will swap that word with the next. + +- If you are at the end of the buffer and use it you get an error message, "Don’t have two things to transpose", _but_ you additionally get placed at the beginning of the last word in the buffer. So `M-t M-t` used at the end of the buffer will swap the last two words! + +- You can use it to swap _non-adjacent_ words too! If you call it with a numeric argument of 0, it will swap the word at the start of the region with the next word after the end of the region. For example, say you want to swap "two" with "five" in the following line: + +```elisp + one five three four two six + +``` + You can mark the words "five three four" (but don't mark "two") and then `M-0 M-t` will swap "five", the first word in the region, with "two" the first word _after_ the region. + +That last trick works with the other `transpose-` commands as well, not just words: `transpose-chars`, `transpose-lines`, `transpose-paragraphs`, `transpose-sentences`, and `transpose-sexps`. Of course, if that `C-0` trick can't be used with any of those commands to swap the two things you want, there is always `transpose-regions`. + +## u/mullikine [πŸ”—](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fc1u840) +**Votes:** 14 + +Making your own hooks using advice. So a hook doesn't exist where you'd like to be hooking into? You can use advice to create a hook. + +```elisp +(defvar eww-restore-history-after-hook '()) +(defun eww-restore-history-after-advice (&rest args) + (run-hooks 'eww-restore-history-after-hook)) +(advice-add 'eww-restore-history :after 'eww-restore-history-after-advice) +(add-hook 'eww-restore-history-after-hook (lambda () + (interactive) + (rename-eww-buffer-unique)) t) +``` + +## u/MCHerb [πŸ”—](https://www.reddit.com/r/emacs/comments/e8nv40/comment/fadjl3w) +**Votes:** 14 + +A narrowing toggle that does what I need most of the time so a single key can do all narrowing and un-narrowing. + +```elisp +(defun narrow-dwim () + "Toggle narrowing." + (interactive) + (cond ((region-active-p) + ;; If region is highlighted, narrow to that + (call-interactively #'narrow-to-region) + (deactivate-mark t)) + ((buffer-narrowed-p) + ;; Otherwise widen if narrowed + (widen)) + ((derived-mode-p 'org-mode) + (call-interactively #'org-narrow-to-subtree)) + (t + (message "Do not know what to narrow to.") + (call-interactively #'narrow-to-defun)))) +``` + +## u/alvarogonzalezs [πŸ”—](https://www.reddit.com/r/emacs/comments/16tes2a/comment/k2gb81l) +**Votes:** 13 + +If you need to find all the occurrences of a string in the project files, but only **on some specific type of files**, you can use `consult-ripgrep` with `-- -t` in the search pattern. + +For example, If you need occurrences of `fancystr` in files of type `html`, the search pattern should be `fancystr -- -t html` + +From `consult-grep` documentation, command line options can be passed to grep, specified behind `--.` The overall prompt input has the form: + +```elisp +#async-input -- rg-opts#filter-string + +``` +I have just discovered this, and it made my day. + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/11rq2gl/comment/jc9t4tc) +**Votes:** 13 + +Plain old `query-replace` has many cool features, first of all it respects the active region (if it's active it will only query for replacements in the active region). There are many useful keys in addition to plain `y`/`n`: + +`!`: replaces all remaning matches + +`u`: undo last replacement + +`E`: changes replacement string on the fly + +And many more you can see using `?`. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/sd10q9/comment/hubjy3j) +**Votes:** 13 + +I was reading through the org manual, and learnt about two variables `org-agenda-category-icon-alist` and `org-agenda-prefix-format`, the first allows you to set icons for categories (`CATEGORY` property), icons can be images or symbols, this is the code I came up with and the agenda already looks more colorful and clear + + +```elisp +(setq org-agenda-category-icon-alist nil) +(setq agenda-categories-alist +'(("WORK" "πŸ’Ό") ("SOFTWARE" "πŸ’»") ("SETUP" "🐧") ("EMAIL" "βœ‰οΈ") +("HOME" "🏠") ("WOOD" "πŸͺ΅") ("FAMILY" "πŸ‘ͺ") ("REPORTS" "πŸ“š") +("INCOME" "πŸ’°"))) +(dolist (icon agenda-categories-alist) (add-to-list 'org-agenda-category-icon-alist +`(,(car icon) ,(cdr icon) nil nil :width (16.) :ascent center))) +(defun format-agenda-prefix () (interactive) +(setcar org-agenda-prefix-format '(agenda . " %-2i %?-12t% s"))) +(add-hook 'org-agenda-mode-hook 'format-agenda-prefix) + +``` +Of course for the emojis to show up correctly I use this: + +```elisp +(set-fontset-font "fontset-default" 'symbol (font-spec :family "Noto Color Emoji")) + +``` +I am sure a lot of you know about these, please share your customization + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/ofen99/comment/h4dxjbz) +**Votes:** 13 + +If you want to search and replace but with preview for the matches, don't use `query-replace-regexp` directly. Instead start by searching for your regexp in `isearch-forward-regexp`, which highlights the matches interactively, and once you have the correct regexp, run `isearch-query-replace` (bound to `M-%` in `isearch-mode-map`). + +Note that there is also an `isearch-query-replace-regexp` command but you don't need it: `isearch-query-replace` will automatically detect if your isearch session was for regexps. The docstring for `isearch-query-replace` doesn't seem to mention this nice feature. + +## u/emacs-noob [πŸ”—](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj1kn9i) +**Votes:** 13 + +I use Emacs for React development and it's usually great (rjsx-mode). We recently introduced styled components into our app and while they're very handy, not having proper css support inside rjsx-mode was pretty annoying. I was looking for solutions, maybe extending rjsx-mode, but I wasn't up to that task. I then realized the built-in emacs commands and buffers themselves could solve my problem! What I want is for css inside a styled component, which always looks something like this: + +```elisp +const myDiv = styled.div` // notice the backtick + Some css... + ` // ending backtick + +``` +to *actually* use scss-mode when editing, and then return to rjsx-mode when finished. The elisp is very simple and leads to a trivial workflow: + +```elisp +;; The following 2 functions allow editing styled components with all scss mode features. +(defun edit-styled-component () + (interactive) + (progn + (save-excursion + (let ((start (search-backward "`")) + (end (search-forward "`" nil nil 2))) ; second occurrence, since first is `start' + (narrow-to-region start end))) + (scss-mode))) + +(spacemacs/set-leader-keys-for-major-mode 'rjsx-mode + "ms" 'edit-styled-component) + +;; When editing is done, use the same key sequence to return to the original file. +(defun return-from-styled-component () + (interactive) + (progn + (widen) + (rjsx-mode))) + +(spacemacs/set-leader-keys-for-major-mode 'scss-mode + "ms" 'return-from-styled-component) + + +``` +So now when I edit a styled component I just hit **, m s**, which narrows the region to whatever is enclosed by backticks (i.e. all the css) and actually treats it as a bona fide css buffer, with all my snippets, completion, etc. Then when I'm done I just got **, m s** again to widen back to the original (rjsx) buffer! + +## u/mullikine [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fwbtnte) +**Votes:** 13 + +## Use chrome DOM for eww + +Basically, a lot of websites these days generate the DOM using javascript. You can dump the DOM from chrome and inject it into eww just before it renders. + +It's set to wait 3 seconds before dumping the DOM. This allows many pages to load. + +Since I'm using the `unbuffer` program, this requires `expect` to be installed on your system. It creates a tty so that chrome doesn't crash when run in this way. + +`dump-dom` shell script + +```elisp +#!/bin/bash + +url="$1" +test -n "$url" || exit 1 + +0/dev/null" + +``` +Make these modifications to `eww-display-html`. + +`eww-display-html` + +```elisp +(defun eww-display-html (charset url &optional document point buffer encode) + (unless (fboundp 'libxml-parse-html-region) + (error "This function requires Emacs to be compiled with libxml2")) + (unless (buffer-live-p buffer) + (error "Buffer %s doesn't exist" buffer)) + ;; There should be a better way to abort loading images + ;; asynchronously. + (setq url-queue nil) + ;; If document exists then the html is already parsed into a DOM + (let* ((html (shell-command-to-string (concat "dom-dump " (shell-quote-argument url)))) + (document + (or nil ;; document + (list + 'base (list (cons 'href url)) + (progn + (setq encode (or encode charset 'utf-8)) + (condition-case nil + (decode-coding-region (point) (point-max) encode) + (coding-system-error nil)) + (save-excursion + ;; Remove CRLF before parsing. + (while (re-search-forward "\r$" nil t) + (replace-match "" t t))) + (save-mark-and-excursion + ;; Delete from here to the end. Replace with the new html + (kill-region (point) (point-max)) + (insert (encode-coding-string html 'utf-8))) + (libxml-parse-html-region (point) (point-max)))))) + (source (and (null document) + (buffer-substring (point) (point-max))))) + (with-current-buffer buffer + (setq bidi-paragraph-direction nil) + (plist-put eww-data :source html) + (plist-put eww-data :dom document) + (let ((inhibit-read-only t) + (inhibit-modification-hooks t) + (shr-target-id (url-target (url-generic-parse-url url))) + (shr-external-rendering-functions + (append + shr-external-rendering-functions + '((title . eww-tag-title) + (form . eww-tag-form) + (input . eww-tag-input) + (button . eww-form-submit) + (textarea . eww-tag-textarea) + (select . eww-tag-select) + (link . eww-tag-link) + (meta . eww-tag-meta) + (a . eww-tag-a))))) + (erase-buffer) + (shr-insert-document document) + (cond + (point + (goto-char point)) + (shr-target-id + (goto-char (point-min)) + (let ((point (next-single-property-change + (point-min) 'shr-target-id))) + (when point + (goto-char point)))) + (t + (goto-char (point-min)) + ;; Don't leave point inside forms, because the normal eww + ;; commands aren't available there. + (while (and (not (eobp)) + (get-text-property (point) 'eww-form)) + (forward-line 1))))) + (eww-size-text-inputs)))) + +``` +Demonstration: +https://asciinema.org/a/UAAVfp5O8SofJZvKBusTOP8QQ + +## u/rhmatthijs [πŸ”—](https://www.reddit.com/r/emacs/comments/gzivu3/comment/ftgqnbp) +**Votes:** 13 + +Working in education, I often find myself having to assign students into groups. This week I made a function in ELisp that helps me do this. Select a region in a buffer that contains a list of students (presumably), call this function, say how many students should be in each group and the function then randomly assigns groups. + +```elisp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Shuffling things. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mcj/shuffle (input) + " Shuffle a list in place. For some reason does not exist in +Emacs by default. Uses Fisher-Yates shuffle. +" + (let ((swap (lambda (list-to-swap i1 i2) + (let ((tmp (elt list-to-swap i1))) + (setf (elt list-to-swap i1) (elt list-to-swap i2)) + (setf (elt list-to-swap i2) tmp))))) + (dotimes (i (length input) input) + (funcall swap input i (random (+ i 1)))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Pairing off things (students, say). ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun mcj/pair-off (input num) + "Return the elements of input paired off into pairs of length + num" + (cond ((< (length input) (* num 2)) (list input)) + (t + (cons (butlast input (- (length input)num)) (mcj/pair-off (nthcdr num input) num))))) + + + +(defun mcj/pair-off-region (num) + " Pair off lines in a region" + (interactive (list + (read-number "Members per pair (num):" 2))) + (let ((newcontents + (mapconcat (lambda (item-pair) + (mapconcat (lambda (item) item) item-pair " + ")) + (mcj/pair-off + (mcj/shuffle + (split-string + (buffer-substring-no-properties (mark) (point)) "[\n]" t )) + num) + "\n"))) + (delete-region (mark) (point)) + (insert newcontents))) +``` + +## u/_hmenke [πŸ”—](https://www.reddit.com/r/emacs/comments/gqsz8u/comment/fruqs1k) +**Votes:** 13 + +Any **BibTeX** users here? + +- Tired of journals forcing you to download a file to get the BibTeX record of an article? +- Tired of their usually broken formatting? +- The journal doesn't offer BibTeX download in the first place? (Looking at you Nature) + +Did you know that doi.org has query interface that gives you the BibTeX record when you call it with the article DOI? Of course you can access this via Emacs: + +```elisp +(require 'url) +(defun user/url-bibtex-from-doi (doi) + (interactive "sDOI: ") + (let* ((url (concat "https://doi.org/" doi)) + (url-mime-accept-string "application/x-bibtex")) + (insert + (with-current-buffer (url-retrieve-synchronously url) + (let* ((start url-http-end-of-headers) + (end (point-max)) + (all (buffer-string)) + (body (buffer-substring start end))) + (replace-regexp-in-string "^\t" " " (url-unhex-string body))))))) + +``` +Just paste the DOI of the article at the prompt and the BibTeX record will be inserted at point. + +Here is how I bind it in `bibtex-mode` (plus my other bindings for good measure) + +```elisp +;; bibtex +(use-package bibtex + :bind (:map bibtex-mode-map + ("C-c d" . user/url-bibtex-from-doi) + ("C-c v" . bibtex-validate) + ("C-c s" . bibtex-sort-buffer) + ([down-mouse-3] . imenu)) + :config + (setq + bibtex-maintain-sorted-entries t)) +``` + +## u/celeritasCelery [πŸ”—](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqdnyhk) +**Votes:** 13 + +Shells in emacs like `shell-mode` and `eshell` can write multi line input using `comint-accumulate`. Normally bound to `C-c SPC`. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/g11mp9/comment/fnd7zkx) +**Votes:** 13 + +If you're not using [`native-comp`](http://akrl.sdf.org/gccemacs.html) feature yet, I strongly recommend you to try it out! Have been using it for two weeks for now and everything seem to run pretty smooth and rock solid! The speed difference is quite noticeable in some interactive aspects like completion, although my machine is quite slow, so this may not be that noticeable on newer machines. + +## u/loopsdeer [πŸ”—](https://www.reddit.com/r/emacs/comments/f972tf/comment/fiqj0dn) +**Votes:** 13 + +You can store a bookmark on a Magit status window and it WORKS! + +I just tried it last night figuring it would err when I tried to open the bookmark later, and it worked and I'm very excited about it. + +This is the perfect entry point for projects for me, being reminded of what state source control is in. I used to jump to Dired in the .git root or some main code window but neither were helpful to start my day. This is perfect. + +I set the bookmark with \`helm-filtered-bookmarks\` by just being on the Magit window and running that then typing in my name, and this is what was added to my bookmark file: + +```elisp +("my magit bookmark title" + (front-context-string . "Unstaged changes") + (rear-context-string . "[redacted for reddit]\n\n") + (position . 124) + (handler . magit--handle-bookmark) + (mode . magit-status-mode) + (filename . "/redacted/path/to/.git") + (magit-hidden-sections + (stashes . "refs/stash") + (unpushed . "@{upstream}.."))) + +``` +I quit Emacs, made an edit in my .git elsewhere, opened Emacs back up and jumped to this bookmark and it showed me the change! + +It's funny how excited I am to remove two keystrokes from the beginning of my day. Probably I am also excited that my random experiment worked. Obviously it's not so random as magit knew exactly what I wanted. Magit is life! + +## u/geza42 [πŸ”—](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/ksifwh1) +**Votes:** 12 + +If you use an LSP server with semantic highlighting, it's worth checking out the value of `font-lock-maximum-decoration`. For example, I use `c++-mode` with `lsp-mode` (with clangd), I decreased `font-lock-maximum-decoration` to `2`, and I didn't notice any highlighting difference (because the lost highlighting by `c++-mode` gets highlighted by `lsp-mode`), while `c++-mode` font-locking become faster (`c++-mode` 's font-locking works well 99.9% of the time, but sometimes it can become slow in some circumstances, these slowdowns seems to be gone). + +I use:`(setq font-lock-maximum-decoration '((c-mode . 2) (c++-mode . 2) (t . t)))` + +## u/leothrix [πŸ”—](https://www.reddit.com/r/emacs/comments/13jvhp7/comment/jl5zu6z) +**Votes:** 12 + +For `use-package` users (which I assume is many of us), did you know that profiling is easy to do? I'm not talking about `esup`, but a built-in capability that makes it very straightforward to find places to optimize your `init.el` for significantly faster start times. + +Enable `use-package-compute-statistics` right after you load `use-package`: + +```elisp +(setq use-package-compute-statistics t) + +``` +Restart emacs, and then invoke `use-package-report`. You'll get a table of the load times for each package that `use-package` manages. I discovered this and found an immediate way to cut my startup time in half by fixing a few packages that weren't deferred properly by adding the right `:hook` keyword. + +## u/eleven_cupfuls [πŸ”—](https://www.reddit.com/r/emacs/comments/10ktqj0/comment/j5umed8) +**Votes:** 12 + +I jump into the built-in Elisp files a lot to see how things work. The indentation there is GNU standard, which uses a mix of tabs and spaces for alignment. The tabs have to be rendered as 8 spaces wide for the alignment to work, and I don't actually want that setting anywhere else. Since the files on Mac are inside the application bundle, I don't want to just add a .dir-locals.el file next to them, either. + +[Directory classes](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html) to the rescue! My config makes a new directory variable class, `builtin-elisp`, with a list saying that `emacs-lisp-mode` should use a `tab-width` of 8. Then it applies that class to the Elisp files in the application bundle: + +```elisp +(use-package elisp-mode + :config + (dir-locals-set-class-variables + 'builtin-elisp + '((emacs-lisp-mode . ((tab-width . 8))))) + (dir-locals-set-directory-class + (file-name-directory (directory-file-name (invocation-directory))) + 'builtin-elisp)) + +``` +And now when I visit one of those files, the alignment is always correct. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/wf0t0d/comment/iirl0ea) +**Votes:** 12 + +Org mode - insert a complete set of export options: + +`org-export-insert-default-template` + +This inserts all export keywords with default values at beginning of line. + +This command is not documented in `info emacs` (v27.1). + +## u/ainstr [πŸ”—](https://www.reddit.com/r/emacs/comments/vcpk6u/comment/ichiccu) +**Votes:** 12 + +The other day I discovered that you can access Spotify through dbus. Most of my use-case for spotify is hitting shuffle on ~20 of my playlists; not much searching, discovering, charts, etc. So, I didn't need any of the existing packages that require an auth token or extra local server. + +This basically wraps `completing-read` over the alist stored in spotify-playlists. You can probably translate the qdbus call to dbus-send or whatever. + +```elisp +;; Inspired by sp.sh: https://gist.github.com/wandernauta/6800547 +;; Could use https://codeberg.org/jao/espotify, but don't need all the functionalities +;; Potential Issues: https://community.spotify.com/t5/Desktop-Linux/DBus-OpenUri-issue/td-p/1376397 + +;; Could just write a fn to extract the ID, and use that in spotify-playlists +;; Current way with full uri allows for playlist vs artist, etc. +;; but probably don't need flexiblity for my use case +(defun spotify--clean-uri (raw-uri) + "Clean RAW-URI into a dbus-acceptable uri." + (let* ((url-fields (split-string + raw-uri + (rx (or "/" "?")))) + (type (nth 3 url-fields)) + (id (nth 4 url-fields))) + (concat "spotify:" type ":" id))) + +(defvar spotify-playlists + '(("Artist" . "https://open.spotify.com/playlist/1v4UqI9mEEB4ry3a3uaorO?si=bc675402c7384080")) + "Alist of spotify playlists for spotify-playlists to select from. + RAW-URI is from right-click on playlist > Share > Copy Link to Playlist.") + +(defun spotify--open-uri (raw-uri) + "Open RAW-URI." + (let ((prefix "qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.OpenUri ") + (uri (spotify--clean-uri raw-uri))) + (shell-command (concat prefix uri)))) + +(defun spotify--open-playlist () + "Prompt to select and play a playlist from spotify-playlists." + (let* ((key (completing-read "Playlist: " spotify-playlists)) + (raw-uri (cdr (assoc key spotify-playlists)))) + (spotify--open-uri raw-uri) + (message (format "Now Playing: %s" key)))) + +(defun spotify-open-playlist () + "Wrapper around `spotify--open-playlist`, to check if spotify is running." + (interactive) + (pcase + (shell-command "pgrep spotify") + (1 (message "Spotify not running.")) + (0 (spotify--open-playlist)))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/mg98ki/comment/gstteeo) +**Votes:** 12 + +I just discovered the [selected](https://github.com/Kungsgeten/selected.el) package, which is brilliant. It creates a keymap that becomes active any time you have an active region. I have bindings for next-line, previous-line, rectangle-mark-mode, end-of-line, upcase-dwim, exchange-point-and-mark, etc. It makes editing and acting on the active region super easy. Sort of like god-mode or Vim's visual mode. + +## u/b3n [πŸ”—](https://www.reddit.com/r/emacs/comments/lvw44q/comment/gpeb8n3) +**Votes:** 12 + +Here's a nice eshell command: + +```elisp +(defun eshell/history () + (interactive) + (insert + (completing-read "History: " (delete-dups (ring-elements eshell-history-ring))))) + +``` +It lets you use your normal completion framework to select an item from history. Suddenly fzf-like history! + +## u/zoechi [πŸ”—](https://www.reddit.com/r/emacs/comments/fwgpkd/comment/fmo9d5v) +**Votes:** 12 + +I (Emacs rookie) just found out that native/fast JSON support is not guaranteed when emacs 27+ is used. jansson-dev needs to be installed when Emacs is built https://github.com/emacs-lsp/lsp-mode/issues/1557#issuecomment-608409056 + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/f25er5/comment/fhar795) +**Votes:** 12 + +Make a `.desktop` file for emacsclient and make sure to include `-c` in the command line ([my .desktop](https://github.com/cadadr/configuration/blob/master/candy/emacsclient.desktop)). Then, you can associate Emacs with many filetypes with emacsclient, and view them in Emacs. E.g., this is how I view PDF files. `-c` is useful because it opens in a new frame, thus your window setup is left intact and the OS window is always in the current workspace (useful if you've set up your WM to not focus urgent windows automatically). + +In a similar vein, I use [this script](https://github.com/cadadr/configuration/blob/master/emacs.d/extras/mailto.el.in) to redirect `mailto:` links to Emacs so that I can write my mails in `message-mode` within Emacs. I've set it as the mail program in Firefox. It's probably possible to write a `.desktop` file for this so that you can set it in `mimeapps.list` or whatever as the global mail composer, but IDK how to do that. + +With emacsclient and a bit of Elisp, it's really easy to integrate Emacs to a FreeDesktop environment. I can't speak for Windows or Mac OS tho, because I don't use those often. + +## u/clemera [πŸ”—](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6ncyes) +**Votes:** 12 + + + +```elisp +emacs --batch -l cl-lib --eval "(cl-loop (print (eval (read))))" +``` + +## u/ProfessorSexyTime [πŸ”—](https://www.reddit.com/r/emacs/comments/dlethf/comment/f4wdyaf) +**Votes:** 12 + +I feel like a lot of us average Emacs users miss out on a lot of functionality Emacs provides outside of the box. So some things you might find interesting: + +#### [Registers](https://www.gnu.org/software/emacs/manual/html_node/emacs/Registers.html) + +Someone posted this in a weekly tips/trick/etc thread a few weeks ago, but I thought I'd mention it again. + +Registers just let you store *things* in them. This can be + +- Cursor positions in buffers (`C-x r SPC [name you want to give the register]`) +- Text in a region (`C-x r s [name you want to give the register]`) +- Rectangles (`C-x r r [name you want to give the register]`) +- State of windows in frames (`C-x r w [name you want to give the register]`) +- State of all frames and their windows (`C-x r f [name you want to give the register]`) +- Numbers (`C-x r n [name you want to give the register]`) and you can increment those numbers (`C-x r + [name of register you want to increment`] +- Whole file names (it's not bound, but you can do `M-: (set-register ?z '(file . "/some_file/somewhere/some_text.txt"))`) +- Keyboard macros instead of saving them (` C-x C-k x [name you want to give the register]`) + +You can insert text, registers, or numbers with `C-x r i [name of register with stuff to insert]`. You can also append or prepend stuff to registers with `append-to-register` or `prepend-to-register`. + +`C-x r j [name of register]` can jump to a point, restore a window or frame configuration, or visit a file with a specific name. + +You could always use [bookmarks](https://www.gnu.org/software/emacs/manual/html_node/emacs/Bookmarks.html#Bookmarks). + +One thing I would like to do is automatically give registers names, say like a1, a2, et cetera then b1, b2 et cetera, and then A1, A2 and yaddah yaddah. + +I'm an idiot though and generating that sort of collection escapes me a bit. + +I'd rather not do just + +```elisp +(loop n from 0 to 99 + collect (concat "a" n)) + +``` +for every alphabetical character. Then it'd be a matter of going through those collections for every register created and making sure they use different names. Was wondering if I could get some help. + +#### [Isearch](https://www.emacswiki.org/emacs/IncrementalSearch) and [Query Replace](https://www.gnu.org/software/emacs/manual/html_node/emacs/Query-Replace.html) + +Not much to say here, just that I might recommend that one go over the default keys for [isearch](https://www.emacswiki.org/emacs/IncrementalSearch#toc2) and query-replace. + +Also I would switch `C-s` and `C-r` to use `isearch-forward-regex` and `isearch-backward-regex`, and `M-%` to use `query-replace-regex` because you can disable the use of regex for both. You can even start a query-replace from isearch with `M-%` or `C-M-%`. + +#### `event-apply-*` Keys + +I don't really know what I can use these keys for, but with which-key you can press `C-x @` to see them. They allow you to apply control, shift, alt, meta, super, or hyper keys. + +## u/algor512 [πŸ”—](https://www.reddit.com/r/emacs/comments/18xebux/comment/kg4ni5d) +**Votes:** 11 + +Recently I discovered that `C-h C-q` (or `M-x help-quick`) opens a small window showing \*Quick Help\* buffer with a nice overview of some basic keybindings. It seems that the content of this buffer is configurable via the variable `help-quick-sections`. + +I intend to use it as a cheatsheet, reminding me about rare keybindings I always forget; I believe it is easy to make it context-dependent, just by changing the value of `help-quick-sections`. + +## u/ayy_ess [πŸ”—](https://www.reddit.com/r/emacs/comments/18hc301/comment/kdobd72) +**Votes:** 11 + +I recently discovered `(setq read-minibuffer-restore-windows nil)` which resolves my frustration that quitting the minibuffer would discard any changes to the window layout while the minibuffer was open. For example, by default, `M-x C-h k k C-g` quits the just opened help buffer. I'm sure to have missed many more QOL improvements from NEWS. + +## u/leothrix [πŸ”—](https://www.reddit.com/r/emacs/comments/17qh1hn/comment/k8dlt4c) +**Votes:** 11 + +Need to remove an element from a list when you're tinkering with elisp? + +Sometimes when I'm adding and removing elements from hooks or variables like `completion-at-point-functions` I'll often need to tinker with the symbols I've added. You could evaluate some form somewhere, but I like to be lazy and just: + +```elisp +M-x remove-hook + +``` +And you've got an interactive interface (using `completing-read`) for removing arbitrary elements from any list-like variable. It's _technically_ for altering hooks, but you can abuse it to fool around with lists, too. + +## u/AnugNef4 [πŸ”—](https://www.reddit.com/r/emacs/comments/112t0uo/comment/ja41lso) +**Votes:** 11 + +How I got my Info Directory node `C-h i` to display all my installed .info files living under `/opt/homebrew` on an M1 Mac. I run emacs-plus@29 from [d12frosted on github](https://github.com/d12frosted/homebrew-emacs-plus). + +init.el snippet + +```elisp +(require 'info) +(info-initialize) +(push "/opt/homebrew/share/info" Info-directory-list) + +``` +run this shell script to update the Directory node. + +```elisp +#!/usr/bin/env bash + +INFO_DIR="/opt/homebrew/share/info" +while read -r f; do + install-info --debug --keep-old "$f" "$INFO_DIR"/dir +done <<< $(find /opt/homebrew/Cellar -name \*.info) +``` + +## u/char1zard4 [πŸ”—](https://www.reddit.com/r/emacs/comments/v2by7z/comment/iarzi1s) +**Votes:** 11 + +This week I learned that: + +- You can redefine all yes/no prompts to y/n: +`(defalias β€˜yes-or-no-p β€˜y-or-n-p)` + +- `C-c C-c` in LaTeX-mode buffers will allow you to compile/view output (I’ve used LaTeX-preview-pane for the last couple of years) + +- Tab-stops in yas-snippet are very handy for filling out multiple parts of a template, didn’t even know these existed: +https://joaotavora.github.io/yasnippet/snippet-development.html#org41a4ac7 + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/s21457/comment/hsgj7a6) +**Votes:** 11 + +Prevent horizontal scrolling from going too far left. + +I use Emacs on a laptop and quite often scroll with a touchpad. I also don't use line wrapping, as in code it usually looks misleading, so lines can sometimes exceed window width, either because of some long names or because the current window configuration is too narrow. + +However, when scrolling text sideways, there's a small annoyance that the scroll can go way too far to the left. E.g. if this is your window, and your text exceeds it: + + +```elisp +|Short line | +|Some really long line o| +|Another short line | + +``` +What I'd like to is to prevent scrolling any further than that: + +```elisp +|line | +|eally long line of text| +|r short line | + +``` +But Emacs actually allows to scroll as far as one would want to, like here: + +```elisp +| | +|t | +| | + +``` +This doesn't make sense to me, as you can't see anything at all. +Probably handy, when you write in really long lines, and you wish to have some buffer for adding more text without triggering scrolling, but I never needed that. So I wrote such predicate: + +```elisp +(defun truncated-lines-p () + "Non-nil if any line is longer than `window-width' + `window-hscroll'. + +Returns t if any line exceeds the right border of the window. +Used for stopping scroll from going beyond the longest line. +Based on `so-long-detected-long-line-p'." + (save-excursion + (goto-char (point-min)) + (let* ((window-width + ;; this computes a more accurate width rather than `window-width', and respects + ;; `text-scale-mode' font width. + (/ (window-body-width nil t) (window-font-width))) + (hscroll-offset + ;; `window-hscroll' returns columns that are not affected by + ;; `text-scale-mode'. Because of that, we have to recompute the correct + ;; `window-hscroll' by multiplying it with a non-scaled value and + ;; dividing it with a scaled width value, rounding it to the upper + ;; boundary. Since there's no way to get unscaled value, we have to get + ;; a width of a face that is not scaled by `text-scale-mode', such as + ;; `window-divider' face. + (ceiling (/ (* (window-hscroll) (window-font-width nil 'window-divider)) + (float (window-font-width))))) + (line-number-width + ;; compensate line numbers width + (if (bound-and-true-p display-line-numbers-mode) + (- display-line-numbers-width) + 0)) + ;; subtracting 2 for extra space in case some calculations were imprecise + (threshold (+ window-width hscroll-offset line-number-width -2))) + (catch 'excessive + (while (not (eobp)) + (let ((start (point))) + (save-restriction + (narrow-to-region start (min (+ start 1 threshold) + (point-max))) + (forward-line 1)) + (unless (or (bolp) + (and (eobp) (<= (- (point) start) + threshold))) + (throw 'excessive t)))))))) + +``` +This function can calculate window width, and line width, and check if any line in the buffer exceeds the window width screen-wise. By screen-wise I mean that if you've scrolled text to the left, it will begin to return `nil` once all lines don't exceed the right border of the window, thus achieving the described behavior in the diagrams. I then define advice around the `scroll-left` function, and it works pretty good: + +```elisp +(define-advice scroll-left (:around (foo &optional arg set-minimum)) + (when (and truncate-lines + (not (memq major-mode '(vterm-mode term-mode))) + (truncated-lines-p)) + (funcall foo arg set-minimum))) + +``` +Though it's not very accurate when using `text-scale-adjust`, as line width is not the same as before, the function, that reports how much the window was scrolled to the left still returns unscaled values. You can see my thoughts in the function's comments. Any suggestions on how to make it more accurate? + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/r69w7i/comment/hmst3ih) +**Votes:** 11 + +macros in emacs are like a secret, forgotten art, but I use them with regexp search, orgmode commands to tweak repeating events (or any number of other uses). Learn macros; they gave emacs its name! One usage here: https://orys.us/ug + +## u/Stefan-Kangas [πŸ”—](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hf1gzs2) +**Votes:** 11 + +Read [SICP](https://mitpress.mit.edu/sites/default/files/sicp/index.html). Preferably in Info, installable through MELPA or: [https://github.com/webframp/sicp-info](https://github.com/webframp/sicp-info) + +## u/Stefan-Kangas [πŸ”—](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hexdfiq) +**Votes:** 11 + +Replace the binding for `count-words-region` with `count-words`. The latter has better semantics: it only shows words in region if the region is active. + +`(global-set-key (kbd "M-=") #'count-words)` + +## u/dmartincy [πŸ”—](https://www.reddit.com/r/emacs/comments/polxft/comment/hcxub77) +**Votes:** 11 + +If you write Lisp, there's a couple of old Emacs commands to help you write code while keeping parenthesis balanced: `M-(` (`insert-parenthesis`), and `M-)` (`move-past-close-and-reindent`). They used to be documented in old Emacs manuals, but presumably their description was removed to make room for other content. + +With a prefix argument, `M-(` wraps in parenthesis that number of sexps. For example with point represented as "*": + +*foo -> C-u 1 M-( -> (foo) + +There's more information in EmacsWiki: https://www.emacswiki.org/emacs/InsertPair + +## u/vatai [πŸ”—](https://www.reddit.com/r/emacs/comments/ojzv53/comment/h5584no) +**Votes:** 11 + +The emacs lisp tutorial is the real tutorial for emacs ;) + +## u/Bodertz [πŸ”—](https://www.reddit.com/r/emacs/comments/lfww57/comment/gmtk79e) +**Votes:** 11 + +From the mailing list, I've just learned of `generic-x.el`, which provides syntax highlighting for `/etc/fstab` or `/etc/passwd` and the like. I appreciated that vim provided that out of the box and I was surprised that emacs also does, but it's just disabled. + +`(require 'generic-x)` to enable it. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/ikgfxd/comment/g3zeprg) +**Votes:** 11 + +**Suggestion for moderators** - Consider putting a note in the weekly announcement for this thread that using 3 backquotes or tildes to make code blocks doesn't work for those of us using old reddit (so the code people post that way is almost unreadable) - and that indenting by 4 spaces is better for compatibility. +(Am I the only one who still uses old reddit? :-) ) + +## u/Rotatop [πŸ”—](https://www.reddit.com/r/emacs/comments/hij4ga/comment/fwi4ikt) +**Votes:** 11 + +I've made it ! + +After 6 month of emacs, I m able to open a side buffer when I m on ivy without using C-c C-O or hydra or alt-enter but directly with shift + arrow (except for Up because I need to go on buffer) + + +```elisp +;; Auto create new window +(setq windmove-create-window t) +;; thanks to https://people.gnome.org/~federico/blog/bringing-my-emacs-from-the-past.html +;; Let me switch windows with shift-arrows instead of "C-x o" all the time +(windmove-default-keybindings) + +;; Ugly hack : +;; What I want is to Shift arrow, then it open the selection on a new splitted window (up left right, down) +(defun tim/ivy-down-other () + (interactive) + (ivy-exit-with-action #'tim/ivy-down-exit)) + +(defun tim/ivy-left-other () + (interactive) + (ivy-exit-with-action #'tim/ivy-left-exit)) + +(defun tim/ivy-right-other () + (interactive) + (ivy-exit-with-action #'tim/ivy-right-exit)) + +(defun tim/ivy-down-exit (ivy-body) + (split-window-below) + (other-window 1) + (tim/reuse-open-goto-line ivy-body)) + +(defun tim/ivy-left-exit (ivy-body) + (split-window-right) + (tim/reuse-open-goto-line ivy-body)) + +(defun tim/ivy-right-exit (ivy-body) + (split-window-right) + (other-window 1) + (tim/reuse-open-goto-line ivy-body)) + + +;; Thanks to +;; https://github.com/abo-abo/swiper/blob/master/doc/ivy.org#actions and +;; https://www.reddit.com/r/emacs/comments/efg362/ivy_open_selection_vertically_or_horizontally/ +(defun tim/reuse-open-goto-line (ivy-body) + (message "reuse-open-goto-line ivy-body: %s" ivy-body) + (let* ((tim/list (split-string ivy-body ":")) + (file (car tim/list)) + (tim/number (car (cdr tim/list)))) + + (condition-case err + (counsel-projectile-find-file-action file) + (void-function ; <- that s the error handler name + (message "open fail with projectile, try find-file. Error was: %s" err) + (find-file file))) + ;; Thanks to https://stackoverflow.com/questions/3139970/open-a-file-at-line-with-filenameline-syntax + (when tim/number + ;; goto-line is for interactive use + (goto-char (point-min)) + (forward-line (1- (string-to-number tim/number)))))) + ;; (ivy-resume)) ; It s strange but ivy-resume here change the way that 'ENTER' or ivy-done works afterwards + ;; Try, as a workaround , in a timer ; no luck + ;; (run-with-timer 0.1 nil 'ivy-resume)) + +(use-package! ivy + :bind (:map ivy-minibuffer-map + ("C-p" . ivy-previous-history-element) + ("" . tim/ivy-down-other) + ;; no up to avoid changing buffer problems + ("" . tim/ivy-left-other) + ("" . tim/ivy-right-other)) + +``` + +Emacs is good + +## u/jimm [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvqvedf) +**Votes:** 11 + +I can't say how often I use `dabbrev-expand` (`M-/`) to complete words. Saves me a ton of time. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvqq7ck) +**Votes:** 11 + +Undo-tree and kill-ring are two of the best features in Emacs / packages. Change your life today. + +## u/hale314 [πŸ”—](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqg7qys) +**Votes:** 11 + +I tend to have a lot of function that is defined solely to be added to a hook. Turns out I can customize `defun-declarations-alist` to define a new `hook` property in the `declare` form. Now I can specify the hook that the function is intended for right inside the function definition. + +```elisp +;; Need to be done during compilation as well if your functions are getting compiled +(eval-and-compile + (setf (alist-get 'hook defun-declarations-alist) + (list (lambda (fun _args hook &optional depth) + `(add-hook ',hook #',fun ,@(when depth (list depth))))))) + +(defun ask-about-scratch-buffer () + "Confirm that user want to discard the content of the scratch buffer." + (declare (hook kill-emacs-query-functions)) + (let ((scratch (get-buffer "*scratch*"))) + (or (zerop (buffer-size scratch)) + (progn (pop-to-buffer scratch) + (y-or-n-p "Scratch buffer is not empty, discard?"))))) +;; no longer needed +;; (add-hook 'kill-emacs-query-functions #'ask-about-scratch-buffer) +``` + +## u/xu_chunyang [πŸ”—](https://www.reddit.com/r/emacs/comments/fo1fm3/comment/flcwsu4) +**Votes:** 11 + +Happy Birthday from Emacs, let's assume March 24 is your birthday, put this to your init file, when you open Emacs on your birthday, you'll receive a birthday present from Emacs + +```elisp +(when (string= "03-24" (format-time-string "%m-%d")) + (animate-birthday-present user-full-name)) +``` + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/ei02j1/comment/fcmosxh) +**Votes:** 11 + +Here's how I open pdf files in mupdf with the colors of my current emacs theme: + +```elisp +(defun mupdf-reader (file) + (let* ((background (face-attribute 'default :background)) + (foreground (face-attribute 'default :foreground)) + ;; if it's a hex code then remove the # prefix + ;; if it's a color name then convert it to hex code + (backg-color (if (equal (substring background 0 1) "#") + (substring background 1) + (substring (color-name-to-hex background) 1))) + (font-color (if (equal (substring foreground 0 1) "#") + (substring foreground 1) + (substring (color-name-to-hex foreground) 1)))) + (make-process + :name "book-reader" + :connection-type 'pipe + :command (list "mupdf-gl" "-B" font-color "-C" backg-color file)))) + +``` +The above function depends on `color-name-to-hex`, which basically combines two inbuilt functions: + +```elisp +(defun color-name-to-hex (name) + (let ((rgb (color-name-to-rgb name))) + (when rgb + (setcdr (last rgb) '(2)) + (apply 'color-rgb-to-hex rgb)))) + +``` +Here's a simple handler function to open all pdf and epub files from emacs with mupdf: + +```elisp +(defun mupdf-file-handler (operation &rest args) + (mupdf-reader (car args)) + (kill-buffer nil) + ;; the error here is to avoid a bug that tries to + ;; match the true filename with the deleted buffer + (error "")) + +``` +Add the magic filenames to init.el so that emacs will know when to use the handler: + +```elisp +(put 'mupdf-file-handler 'safe-magic t) +(put 'mupdf-file-handler 'operations '(insert-file-contents)) +(add-to-list 'file-name-handler-alist '("\\(\\.\\(?:epub\\|pdf\\)\\)$" . mupdf-file-handler)) +``` + +## u/human_banana [πŸ”—](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fbyevye) +**Votes:** 11 + +Have multiple machines where some things are available and other aren't? + +`when-available` takes a function name and if it exists, executes the rest. + +```elisp +(defmacro when-available (func cmd) + "Execute CMD if FUNC exists as a function." + `(when (fboundp ,func) ,cmd)) + +``` +So you can deal with different environments. + +I mostly use this for things that are nice to have, but aren't required and don't need to be installed if they aren't already. + +## u/bopboa [πŸ”—](https://www.reddit.com/r/emacs/comments/1aky57w/comment/kphrvz3) +**Votes:** 10 + +This is how to have a beacon without installing any packages. + +```elisp + (defun pulse-line (_) + (pulse-momentary-highlight-one-line (point))) + (setq window-selection-change-functions '(pulse-line)) +``` + +## u/JDRiverRun [πŸ”—](https://www.reddit.com/r/emacs/comments/1933co6/comment/khe4dq6) +**Votes:** 10 + +I have long had convenience bindings for `org-emphasize` like `super-i` for /italic/, that match system bindings. But I always wanted these to *be smarter*, i.e. do something useful when there is no text selected. Something like intelligently toggling emphasis depending on whether you were already in the right kind of emphasized text, or just emphasize the word at point if not. + +[Check out my solution](https://gist.github.com/jdtsmith/55e6a660dd4c0779a600ac81bf9bfc23) (scroll down to see how it acts). Will miss this behavior in other apps! + +## u/camel_case_t [πŸ”—](https://www.reddit.com/r/emacs/comments/18xebux/comment/kgce54q) +**Votes:** 10 + +This is maybe more a macOS tip than an Emacs tip, but it always bothered me that `C-f`, `C-b`, etc worked in any text box, but not `M-f`, etc -- turns out that you can easily change that throughout the OS! + +I created this file and now Emacs keybindings work everywhere: + +```elisp +/* ~/Library/KeyBindings/DefaultKeyBinding.dict */ +{ + /* Additional Emacs bindings */ + "~f" = "moveWordForward:"; + "~b" = "moveWordBackward:"; + "~<" = "moveToBeginningOfDocument:"; + "~>" = "moveToEndOfDocument:"; + "~v" = "pageUp:"; + "~d" = "deleteWordForward:"; + "~^h" = "deleteWordBackward:"; + "~\010" = "deleteWordBackward:"; /* Option-backspace */ + "~\177" = "deleteWordBackward:"; /* Option-delete */ +} + +``` +You can read more here: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/15sjm3k/comment/jwff8bw) +**Votes:** 10 + +I've been slowly accumulating cases for "flexing" the thing at point as a more general `capitalize-word` replacement: + +```elisp +;; Stolen from the wiki somewhere +(defun increment-number-at-point () + "Increment the number at point." + (interactive) + (skip-chars-backward "0-9") + (or (looking-at "[0-9]+") + (error "No number at point")) + (replace-match (number-to-string (1+ (string-to-number (match-string 0)))))) + +(defun lw-flex () + "Perform smart flexing at point. + +E.g. capitalize or decapitalize the next word, increment number at point." + (interactive) + (let ((case-fold-search nil)) + (call-interactively + (cond ((looking-at "[0-9]+") #'increment-number-at-point) + ((looking-at "[[:lower:]]") #'capitalize-word) + ((looking-at "==") (delete-char 1) (insert "!") (forward-char 2)) + ((looking-at "!=") (delete-char 1) (insert "=") (forward-char 2)) + ((looking-at "+") (delete-char 1) (insert "-") (forward-char 1)) + ((looking-at "-") (delete-char 1) (insert "+") (forward-char 1)) + ((looking-at "<=") (delete-char 2) (insert ">=") (forward-char 2)) + ((looking-at ">=") (delete-char 2) (insert "<=") (forward-char 2)) + ((looking-at "<") (delete-char 1) (insert ">") (forward-char 1)) + ((looking-at ">") (delete-char 1) (insert "<") (forward-char 1)) + (t #'downcase-word))))) + +``` +I bind it to `M-c`. + +## u/gusbrs [πŸ”—](https://www.reddit.com/r/emacs/comments/14l3jn8/comment/jpwn2ts) +**Votes:** 10 + +I was converting some old `.odt` notes files to `.org` today, and one of the things I wanted to do was to add two spaces after end of sentence periods for proper sentence navigation. So there I was figuring out a general enough regexp for the nth time and, of course, I regretted not having taken note of this the last time. So I decided to do some searching for a good regexp and write it down this time, since this was obviously shared by someone somewhere. And it turns out Emacs has us covered, and I never knew: `repunctuate-sentences`. I have no idea if this is new or has always been there. It is new to me. It uses `query-replace-regexp`, so it's the same experience. And also can be configured for exclusions with `repunctuate-sentences-filter`. Neat! + +## u/pathemata [πŸ”—](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8mpo5y) +**Votes:** 10 + +Does anyone have an `aspell` setup with multiple dictionaries? + +When I try `--extra-dict` option I get an error: `Expected language "en" but got "de"`. + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/108zin2/comment/j420ea0) +**Votes:** 10 + +Do you want a key binding to wrap the selection in some kind of delimiter? Here's a built-in solution: + +```elisp +(defvar insert-pair-map + (let ((map (make-sparse-keymap))) + (define-key map [t] #'insert-pair) + map)) + +(global-set-key (kbd "C-S-w") insert-pair-map) + +``` +This setups up `C-S-w` to be a prefix map, `insert-pair-map`. The only key binding in `insert-pair-map` is for `[t]`, which means it is the default key binding and any key after the prefix will run the same command: `insert-pair`. Now, `insert-pair` looks at which key was used to invoke it and if it is an opening delimiter it inserts both it and the corresponding closing delimiter (and if the region is active it insert the opening delimiter at the start and the closing delimiter at the end, wrapping the region). + +## u/luiggi_oasis [πŸ”—](https://www.reddit.com/r/emacs/comments/zred55/comment/j14grej) +**Votes:** 10 + +What's the deal with all these completion framework I keep hearing about? Vertical elm ivy company and whatnot. + +I think I have company in my init.el but I'm not even sure I'm actually using it (maybe I am and I'm just unaware). But why are they everywhere? I see them mentioned in at least every any two emacs threads. + +## u/kickingvegas1 [πŸ”—](https://www.reddit.com/r/emacs/comments/x7zfs2/comment/innk62a) +**Votes:** 10 + +TIL when working with an Org table that `S-RET` will fill the current cell value with the value above it. + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/x7zfs2/comment/inqralq) +**Votes:** 10 + +I use follow-mode (built-in to #emacs) to split reading buffers across modern wide screens to use all the real estate. The mode keeps the panes in sync with eachother. http://images.toryanderson.com/follow-mode.gif + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikrx30z) +**Votes:** 10 + +I've parsed and prettified some of the comments (I think I'm missing some, but hopefully should be fixed soonish) from past weekly tips and tricks thread here: [https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md](https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md) + +If you fancy procrastinating for a bit today... + +## u/tryptych [πŸ”—](https://www.reddit.com/r/emacs/comments/w3gx6o/comment/ih6ievs) +**Votes:** 10 + +Emacs has better long-lines support now?? + +I just noticed while looking at the latest additions in the NEWS: + +>\*\* Emacs is now capable of editing files with arbitrarily long lines. The display of long lines has been optimized, and Emacs no longer chokes when a buffer on display contains long lines. If you still experience slowdowns while editing files with long lines, this is either due to font locking, which you can turn off with M-x font-lock-mode or C-u C-x x f, or to the current major mode or one of the enabled minor modes, in which case you should open the the file with M-x find-file-literally instead of C-x C-f. The variable 'long-line-threshold' controls whether and when these display optimizations are used. + +That sounds like great news! Does anyone know what went into it? + +(edit to add: this was added some time this week. I rebuild from master weekly, and check out the NEWS diff each time) + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/us7zae/comment/i92mn8w) +**Votes:** 10 + +[deleted] + +## u/shitterwithaclitter [πŸ”—](https://www.reddit.com/r/emacs/comments/s7lac1/comment/htnz373) +**Votes:** 10 + +I recently had the idea to start emacs in org-mode but have a src block at the top so I can still write elisp snippets easily. Here's the code for anyone interested: + +```elisp +;; start in org-mode with a source block for lisp evaluation +(setq initial-major-mode #'org-mode + initial-scratch-message "#+begin_src emacs-lisp\n;; This block is for text that is not saved, and for Lisp evaluation.\n;; To create a file, visit it with \\[find-file] and enter text in its buffer.\n\n#+end_src\n\n") +``` + +## u/yogsototh [πŸ”—](https://www.reddit.com/r/emacs/comments/qgrpte/comment/hi8crmc) +**Votes:** 10 + +I just made this nice combination of emacs packages and personal theme to achieve the cool effect of iAWriter + +See here: https://her.esy.fun/posts/0021-ia-writer-clone-within-doom-emacs/index.html + +## u/SamTheComputerSlayer [πŸ”—](https://www.reddit.com/r/emacs/comments/qbvyza/comment/hhinrm4) +**Votes:** 10 + +I use a lot of toggles in my config. I used to do it ad-hoc every time, but the pattern ends up the same so I made this macro: +```elisp +(defun deftoggle-var-doc (name) + (concat "Non-nil if " name " is enabled.\n\n" + "See " name + " command for a description of this toggle.")) +(defun deftoggle-fun-doc (name doc) + (concat "Toggle " name " on or off.\n\n" doc)) +(defmacro deftoggle (name doc enabler disabler) + `(progn + (defvar ,name nil ,(deftoggle-var-doc (symbol-name name))) + (defun ,name (&optional enable) + ,(deftoggle-fun-doc (symbol-name name) doc) + (interactive) + (if (called-interactively-p 'interactive) + (progn + (if ,name + ,disabler + ,enabler) + (setq ,name (not ,name))) + (progn + (if enable + ,enabler + ,disabler) + (setq ,name enable)))))) +``` + +It's very similar to define-minor-mode, but with all the hooks, keymaps, and lighters stripped out, so it's less verbose. Here I use it to toggle my theme for example: +```elisp +(deftoggle sam-toggle-theme + "Toggle theme between light and dark." + (progn (disable-theme 'dracula) + (load-theme 'spacemacs-light t)) + (progn (disable-theme 'spacemacs-light) + (load-theme 'dracula t))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/q76kok/comment/hghtyfo) +**Votes:** 10 + +before you load evil `(setq evil-want-minibuffer t)` to use evil-mode in the minibuffer. + +## u/github-alphapapa [πŸ”—](https://www.reddit.com/r/emacs/comments/q2g1gq/comment/hfldw8n) +**Votes:** 10 + +One of the most useful bindings for me: + +```elisp +(use-package avy + :bind* (("C-j" . avy-goto-char-timer))) +``` + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/ojzv53/comment/h55vkl6) +**Votes:** 10 + +I often find myself wanting to be able to switch between `master` and a feature branch in magit quickly: + +```elisp +(defun lw-magit-checkout-last (&optional start-point) + (interactive) + (magit-branch-checkout "-" start-point)) +(transient-append-suffix 'magit-branch "w" + '("-" "last branch" lw-magit-checkout-last)) + +``` +So that `C-x g b -` switches to the last branch I was on, similar to `cd -`. + +## u/sauntcartas [πŸ”—](https://www.reddit.com/r/emacs/comments/o0zvb5/comment/h1znz1s) +**Votes:** 10 + +I keep forgetting how useful the `pcase` macro is. Recently I wrote a command that expected to find a single jar file in a certain directory and operate on it. I started with a more "traditional" implementation: + +```elisp +(let ((jars (directory-files some-dir t (rx ".jar" eos)))) + (if (= 1 (length jars)) + (do-something-with (car jars)) + (error "Didn't find exactly one jar file"))) + +``` +Then I remembered `pcase`: + +```elisp +(pcase (directory-files some-dir t (rx ".jar" eos)) + (`(,jar) (do-something-with jar)) + (_ (error "Didn't find exactly one jar file"))) + +``` +Much more readable! + +## u/PotentiallyAlice [πŸ”—](https://www.reddit.com/r/emacs/comments/n9q662/comment/gxx6frj) +**Votes:** 10 + +I thought it might be a fun project to make a package to expose org-capture templates as endpoints, so I can add reminders to my TODO list via any device on the network. Turns out, it was easy enough that a package would be kinda pointless: + +```elisp +(defservlet* capture/:keys/:contents text/plain () (org-capture-string contents keys)) + +``` +Now I can hit "localhost:8080/capture/t/test reminder" and it'll put a "* TODO test reminder" line into my todo.org. Neat! + +## u/b3n [πŸ”—](https://www.reddit.com/r/emacs/comments/ml4wql/comment/gtkc524) +**Votes:** 10 + +Skeletons are one of Emacs' killer features, especially when combined with `abbrev-mode`. Here's a macro I wrote to make them a little easier to handle: + +```elisp +(defmacro snip (name &rest skeleton) + (let* ((snip-name (symbol-name `,name)) + (func-name (intern (concat "snip-" snip-name)))) + `(progn + (define-skeleton ,func-name + ,(concat snip-name " skeleton") + ,@skeleton) + (define-abbrev global-abbrev-table ,snip-name + "" ',func-name)))) + +``` +Here's a simplistic example using the macro: + +```elisp +(snip dd "" (format-time-string "%Y-%m-%d")) + +``` +Now (assuming you have `abbrev-mode` enabled), type `dd ` into your buffer (that's `d` `d` `SPC`) and it'll be replaced with the current date. + +This is just scratching the surface, skeletons are extremely powerful. Once you start using them they become a superpower and can take your Emacs usage to the next level. + +## u/jumpUpHigh [πŸ”—](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj33uht) +**Votes:** 10 + +AucTeX + +When you compile your TeX file and there are errors, the message asks you to see error messages using + +```elisp + C-c ` + +``` +This leads to the last error which is sometimes incomprehensible and you are left to yourself to figure out what went wrong. + +Instead of getting the last error, you can get an overview of all the errors by setting below variable to `t`: + +```elisp + (setq TeX-error-overview-open-after-TeX-run t) + +``` +You can pop this up in a separate frame using: + +```elisp + (setq TeX-error-overview-setup 'separate-frame) + +``` +Related docs are [here](https://www.gnu.org/software/auctex/manual/auctex/Error-overview.html). + +This totally changes the way you can handle errors messages. + +## u/Krautoni [πŸ”—](https://www.reddit.com/r/emacs/comments/ja97xs/comment/g8pgyy1) +**Votes:** 10 + +Since I find myself pair programming quite a bit, I made a small helper: + +```elisp +(defvar pair-programming--pair-programmer + nil + "The current pair programmer as (name email)") + +(defun enable-pair-programming-mode () + "Sets visuals for pair programming mode and prompt for your buddy." + (global-display-line-numbers-mode 1) + (let ((pair-programmer (git-commit-read-ident nil))) +(setq pair-programming--pair-programmer pair-programmer) +(message (concat "Pair programming with " (car pair-programmer))))) + +(defun disable-pair-programming-mode () + "Disable pair programming visuals and settings." + (setq pair-programming--pair-programmer nil) + (global-display-line-numbers-mode -1) + (message "PP mode disabled")) + +(define-minor-mode pair-programming-mode () + "Toggle Pair Programming Mode. + +This prompts for a pair programmer from your current git commit history. +When you commit with (ma)git, the pair programmer is inserted as a co-author. +Additionally, line number mode is enabled." + :global t + :lighter " PP" + (if pair-programming-mode + (enable-pair-programming-mode) +(disable-pair-programming-mode))) + +(defun insert-pair-programmer-as-coauthor () + "Insert your pair programer into the current git commit." + (when (and pair-programming-mode git-commit-mode) +(pcase pair-programming--pair-programmer + (`(,name ,email) (git-commit-insert-header "Co-authed-by" name email)) + (_ (error "No pair programmer found or wrong content"))))) + +(add-hook 'git-commit-setup-hook 'insert-pair-programmer-as-coauthor) +``` + +It sets up a co-authored-by for git commits, and enables line numbers. + +## u/sauntcartas [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvrlu40) +**Votes:** 10 + +I've been using `M-|` (`shell-command-on-region`) frequently for years, and I only just stumbled on the fact that the region need not be active to use it. If it isn't, the command operates on the text from point to the end of the buffer. That's very reasonable and in line with various other commands, but the documentation doesn't mention it and so I never thought to try it. + +That saves me a call to `C-x h` (`mark-whole-buffer`) whenever I want to process the entire buffer, which is most of the time. Also, it's a minor distraction for the entire buffer to be highlighted when I'm composing my shell command, so it's nice to avoid that. + +Edited to add: Sorry folks, this doesn't work like I thought it did. See the coments below for details. + +## u/rhmatthijs [πŸ”—](https://www.reddit.com/r/emacs/comments/h9zoy9/comment/fuzucay) +**Votes:** 10 + +On a Mac: make Emacs detect if you have light or dark mode enabled system wide. + +If you have two themes, a light one and a dark one, and you want the dark theme by default unless you have light mode enabled, add this to your init.el: + +```elisp +;; If we're on a Mac and the file "~/bin/get_dark.osascript" exists +;; and it outputs "false", activate light mode. Otherwise activate +;; dark mode. +(cond ((and (file-exists-p "~/bin/get_dark.osascript") + (string> (shell-command-to-string "command -v osascript") "") + (equal "false\n" + (shell-command-to-string "osascript ~/bin/get_dark.osascript"))) + (mcj/theme-set-light)) + (t (mcj/theme-set-dark))) + +``` +(mcj/theme-set-light and mcj/theme-set-light are functions that enable the light and the dark theme, respectively). + +~/bin/get_dark.osascript contains the following: + +```elisp +tell application "System Events" + tell appearance preferences + get dark mode + end tell +end tell +``` + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/g5bat3/comment/fo362s8) +**Votes:** 10 + +`rx` isn't just an (extensible!) sexp syntax for regexps, it's an optimizing compiler! + +Examples: + +- `(rx (or "dude@home.org" "dude@work.com"))` produces +```elisp +`"\\(?:dude@\\(?:home\\.org\\|work\\.com\\)\\)"` +``` +- `(rx (intersection (any (?g . ?z)) (any (?a . ?p))))` produces `"[g-p]"` + +And from Lisp code it's easy to plug in computed portions, using `eval`. +For example I recently used this in some silly code to count mentions +of animals in the bible :P: + +```elisp +(defun plural (word) + (pcase word + ("mouse" "mice") + ("wolf" "wolves") + ("fish" "fishes") + (word (concat word "s")))) + +(defun bible-count (word) + "Count number of times WORD or its plural appears in the bible." + (with-current-buffer "king-james-bible.txt" + (count-matches + (rx-to-string `(word-start (or ,word ,(plural word)) word-end))))) + +``` +Which I used to make an Org mode table with an Emacs Lisp column formula: + +```elisp +#+TBLFM: $2='(bible-count $1) + +``` +**EDIT**: A previous version of the `bible-count` function used the `rx` macro and the `eval` construct: + +```elisp +(defun bible-count (word) + "Count number of times WORD or its plural appears in the bible." + (with-current-buffer "king-james-bible.txt" + (count-matches (rx word-start + (or (eval word) (eval (plural word))) + word-end)))) + +``` +This version is incorrect: `eval` is meant to be used only for value known at compile time. It's actual [behavior is very complicated](https://www.reddit.com/r/emacs/comments/g5bat3/weekly_tipstricketc_thread/fo7qdas) and depends on plenty of seemingly extraneous circumstances. + +## u/primitiveinds [πŸ”—](https://www.reddit.com/r/emacs/comments/erro41/comment/ff90d5b) +**Votes:** 10 + +I just now figured out that you can interactively pass flags to commands like `counsel-rg` by putting the `--` separator between the flags and the search string, so something like `-g '*.txt' -- whatever` will search for `whatever` only in `txt` files. `counsel` uses a function called `counsel--split-command-args` to split the parts before and after the `--`. + +## u/itistheblurstoftimes [πŸ”—](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f8978oj) +**Votes:** 10 + +I just started using mu4e and wanted to have some visual indication of which account was associated with each email. Did this quickly but it seems to work well. This is akin to what K9 mail does on android. + +The names "account1" refer to the folders in your Maildir for each account, i.e., \~/Maildir/account1 + +​ + +```elisp +(setq x-mu4e-account-colors '(("account1" . "orange") + ("account2" . "red") + ("account3" . "blue"))) + +(setq x-mu4e-account-colors-prefix " ") + +(defun x-mu4e-header-colors (msg line) + "Add a small color block to headers view indicating the account for each email" + (let* ((maildir (nth 1 (s-split "/" (plist-get msg :maildir)))) + (color (cdr (assoc maildir x-mu4e-account-colors)))) + (setq line (concat x-mu4e-account-colors-prefix line)) + (put-text-property 0 (- (length x-mu4e-account-colors-prefix) 2) 'face `(:background ,color) line) + line)) + +(add-to-list 'mu4e~headers-line-handler-functions 'x-mu4e-header-colors t) +``` + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f848ctb) +**Votes:** 10 + +A simple ivy function to play soma.fm with mpv in emacs: + +```elisp +(defun launcher-somafm () + (interactive) + (let ((stations + '(("BAGeL Radio: What alternative rock radio should sound like. [explicit]" + . "http://somafm.com/bagel32.pls") + ("Beat Blender: A late night blend of deep-house and downtempo chill." + . "http://somafm.com/beatblender32.pls") + ("Black Rock FM: From the Playa to the world, for the annual Burning Man festival." + . "http://somafm.com/brfm32.pls") + ("Boot Liquor: Americana Roots music for Cowhands, Cowpokes and Cowtippers" + . "http://somafm.com/bootliquor32.pls") + ("Christmas Lounge: Chilled holiday grooves and classic winter lounge tracks. (Kid and Parent safe!)" + . "http://somafm.com/christmas32.pls") + ("Christmas Rocks!: Have your self an indie/alternative holiday season!" + . "http://somafm.com/xmasrocks32.pls") + ("Cliqhop idm: Blips'n'beeps backed mostly w/beats. Intelligent Dance Music." + . "http://somafm.com/cliqhop32.pls") + ("Covers: Just covers. Songs you know by artists you don't. We've got you covered." + . "http://somafm.com/covers32.pls") + ("DEF CON Radio: Music for Hacking. The DEF CON Year-Round Channel." + . "http://somafm.com/defcon32.pls") + ("Deep Space One: Deep ambient electronic, experimental and space music. For inner and outer space exploration." + . "http://somafm.com/deepspaceone32.pls") + ("Digitalis: Digitally affected analog rock to calm the agitated heart." + . "http://somafm.com/digitalis32.pls") + ("Doomed (Special): For Halloween: Dark industrial/ambient music for tortured souls." + . "http://somafm.com/specials32.pls") + ("Drone Zone: Served best chilled, safe with most medications. Atmospheric textures with minimal beats." + . "http://somafm.com/dronezone32.pls") + ("Dub Step Beyond: Dubstep, Dub and Deep Bass. May damage speakers at high volume." + . "http://somafm.com/dubstep32.pls") + ("Fluid: Drown in the electronic sound of instrumental hiphop, future soul and liquid trap." + . "http://somafm.com/fluid32.pls") + ("Folk Forward: Indie Folk, Alt-folk and the occasional folk classics." + . "http://somafm.com/folkfwd32.pls") + ("Groove Salad: A nicely chilled plate of ambient/downtempo beats and grooves." + . "http://somafm.com/groovesalad32.pls") + ("Groove Salad Classic: The classic (early 2000s) version of Groove Salad" + . "http://somafm.com/gsclassic32.pls") + ("Illinois Street Lounge: Classic bachelor pad, playful exotica and vintage music of tomorrow." + . "http://somafm.com/illstreet32.pls") + ("Indie Pop Rocks!: New and classic favorite indie pop tracks." + . "http://somafm.com/indiepop32.pls") + ("Jolly Ol' Soul: Where we cut right to the soul of the season." + . "http://somafm.com/jollysoul32.pls") + ("Left Coast 70s: Mellow album rock from the Seventies. Yacht not required." + . "http://somafm.com/seventies32.pls") + ("Lush: Sensuous and mellow vocals, mostly female, with an electronic influence." + . "http://somafm.com/lush32.pls") + ("Metal Detector: From black to doom, prog to sludge, thrash to post, stoner to crossover, punk to industrial." + . "http://somafm.com/metal32.pls") + ("Mission Control: Celebrating NASA and Space Explorers everywhere." + . "http://somafm.com/missioncontrol32.pls") + ("PopTron: Electropop and indie dance rock with sparkle and pop." + . "http://somafm.com/poptron32.pls") + ("Secret Agent: The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!" + . "http://somafm.com/secretagent32.pls") + ("Seven Inch Soul: Vintage soul tracks from the original 45 RPM vinyl." + . "http://somafm.com/7soul32.pls") + ("SF 10-33: Ambient music mixed with the sounds of San Francisco public safety radio traffic." + . "http://somafm.com/sf103332.pls") + ("Sonic Universe: Transcending the world of jazz with eclectic, avant-garde takes on tradition." + . "http://somafm.com/sonicuniverse32.pls") + ("Space Station Soma: Tune in, turn on, space out. Spaced-out ambient and mid-tempo electronica." + . "http://somafm.com/spacestation32.pls") + ("Suburbs of Goa: Desi-influenced Asian world beats and beyond." + . "http://somafm.com/suburbsofgoa32.pls") + ("The Trip: Progressive house / trance. Tip top tunes." + . "http://somafm.com/thetrip32.pls") + ("ThistleRadio: Exploring music from Celtic roots and branches" + . "http://somafm.com/thistle32.pls") + ("Underground 80s: Early 80s UK Synthpop and a bit of New Wave." + . "http://somafm.com/u80s32.pls") + ("Xmas in Frisko: SomaFM's wacky and eclectic holiday mix. Not for the easily offended." + . "http://somafm.com/xmasinfrisko32.pls")))) + (ivy-read "soma.fm " (mapcar 'car stations) + :re-builder #'regexp-quote + :action (lambda (x) (save-window-excursion + (async-shell-command (concat "mpv " (cdr (assoc x stations))) + "*soma.fm*")))))) + +(defun kill-soma () + (interactive) + (kill-process "*soma.fm*") + (sleep-for 2) + (kill-buffer "*soma.fm*")) +``` + +## u/primitiveinds [πŸ”—](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5oz3bp) +**Votes:** 10 + +This is one of the things that I'm sure exists somewhere but I can't find it so I wrote a few lines. I work in a big monorepo and depend on `projectile` for navigation by adding `.projectile` files here and there, in subdirectories that I consider "projects". However there are some directories that e.g. contain libraries. If I want to work on all of them for e.g. refactoring, going into a project then locks me in that (I mean `projectile-find-file`) and I have to manually go into another project. Also I flood my projectile cache with little things that I might not use a lot. What I did was add some logic to create temporary root directories for projects, where I can then use `counsel-file-jump` and `counsel-ag`. I have some keybindings and with a prefix argument I am prompted to change the temp root. Here's the code: +```elisp +(defvar my/temp-project-root nil) + +(defun my/get-or-set-temp-root (reset) + (let* ((reset-root (if reset my/temp-project-root nil)) + (root + (if (or reset + (null my/temp-project-root) + (not (file-directory-p my/temp-project-root))) + (read-directory-name "Temp root dir: " reset-root) + my/temp-project-root))) +(setq my/temp-project-root root))) + +(defun my/counsel-file-jump-temp-root (reset) + (interactive "P") + (my/get-or-set-temp-root reset) + (let ((current-prefix-arg nil)) +(counsel-file-jump nil my/temp-project-root))) + +(defun my/counsel-ag-temp-root (reset) + (interactive "P") + (my/get-or-set-temp-root reset) + (let ((current-prefix-arg nil)) +(counsel-ag "" my/temp-project-root))) +``` +Also `counsel-file-jump` is so good + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/1aky57w/comment/kpct4cp) +**Votes:** 9 + +Many of you probably know of this, but I found "indirect buffers" useful. + +When I'm in Vim, I've found it useful to sometimes split a buffer into two windows, and use code folding to view different parts of the same file in the two windows. But this doesn't work in Emacs, because the "folding" and "narrow" states of the buffer are synced between the windows in contrast to Vim. One concrete use case I had: I have a huge Org file, and wanted to narrow `C-x n s` into different headings of the file in different windows. + +Indirect buffers solve this. It makes two buffers for one file, and these buffers have separate settings for folding, narrowing, etc. But the buffer contents are still synced, so there's no risk of diverging file states. With default keybindings, I found that `C-x 4 c C-x n s` did what I wanted. + +## u/badmaxton [πŸ”—](https://www.reddit.com/r/emacs/comments/19ec8v5/comment/kjcu7vp) +**Votes:** 9 + +Just added this to the `:init` section of my embark configuration: + +```elisp +(define-key minibuffer-local-map [C-tab] 'embark-select) + +``` +This allows super-convenient marking of entries for later `embark-all` using control-tab, instead of having to go first through the `embark` menu. (By default, this key binding is mapped to `file-cache-minibuffer-complete`, which I never use.) + +## u/lesliesrussell [πŸ”—](https://www.reddit.com/r/emacs/comments/198rnkj/comment/kibmgv2) +**Votes:** 9 + +[transient map for movement](https://gist.github.com/lesliesrussell/46302d413fcf49e9717eeea57fdadcbf) + +Defines a transient keymap for movement controls and sets up a global key binding to activate this transient map. This transient map, \`my-movement-transient-map\`, includes bindings for various movement commands like moving forward or backward by a word or character and moving to the next or previous line. The \`activate-my-movement-map\` function is defined to activate this transient map, and it is globally bound to \`C-f\`. + +​ + +This setup allows you to press \`C-f\` followed by one of the specified keys (\`f\`, \`b\`, \`c\`, \`l\`, \`n\`, \`p\`) to perform the corresponding movement operation. The \`set-transient-map\` call with a second argument of \`t\` ensures that the transient map stays active until one of its keys is pressed. + +​ + +This is a neat way to create a custom, modal-like interface for movement within Emacs, leveraging your Emacs Lisp skills to tailor your editing environment to your preferences. If you have any specific modifications or additional features you'd like to implement, feel free to ask! + +I didn't want to drop code in the thread so i put it in a gist + +## u/Netherus [πŸ”—](https://www.reddit.com/r/emacs/comments/17qh1hn/comment/k8c4mz7) +**Votes:** 9 + +Just recently found out M-u makes the next word upper case, and the same for M-l for lower case. Maybe nothing fancy, but it's kinda handy for me. + +## u/BunnyLushington [πŸ”—](https://www.reddit.com/r/emacs/comments/12zaqju/comment/jhrzybp) +**Votes:** 9 + +I found myself debugging [JWTs](https://jwt.io) earlier this week and whomped up a little function to decode them from a region into a help buffer. + +```elisp +(defun ii/decode-jwt (start end &optional jwt) + "Decode JWT in region and print to help buffer." + (interactive "r") + (let* ((tok (if jwt jwt + (buffer-substring start end))) + (data (s-split "\\." tok)) + (header (car data)) + (claims (cadr data))) +(with-temp-buffer + (insert (format "%s\n\n%s" + (base64-decode-string header t) + (base64-decode-string claims t))) + (json-pretty-print-buffer) + (with-output-to-temp-buffer "*JWT*" + (princ (buffer-string))))) + t) +``` + +I'd forgotten about `with-output-to-temp-buffer` which is pretty handy. The `t` at the end is there just to suppress an overly large echo area message. + +(This should be obvious but note that the JWT is not validated or verified. This is intended for debugging only and the JWT should not be trusted.) + +## u/sauntcartas [πŸ”—](https://www.reddit.com/r/emacs/comments/12cd23k/comment/jf3ohpv) +**Votes:** 9 + +I work with multiple Git repositories in my day job, but one in particular occupies 95% of my time. I've often wished I could set up Projectile so that if I run one of its commands while not in any repo, it will behave as if I'd changed to that main repo first. I couldn't find a built-in way to do that, but got the effect I wanted with some advice: + +```elisp +(defun default-to-main-project (dir) + (or dir *main-project-dir*)) + +(advice-add 'projectile-ensure-project :override #'default-to-main-project) + +``` +I lose some of the functionality of `projectile-ensure-project`, but I never used it anyway. + +## u/slinchisl [πŸ”—](https://www.reddit.com/r/emacs/comments/11rq2gl/comment/jca66k0) +**Votes:** 9 + +I'm once again reminded of the utility of `read-key` for small functions where one wants a nicer interface for choosing an alternative than universal arguments; taking an optional prompt, it simply reads a key from the keyboard and returns it. + +For example, I recently wanted a function that prints a set of predefined dates for me into the current buffer, and it was as easy as + +```elisp +(defun slot/insert-time () + (interactive) + (let* ((formats '((?i "ISO 8601" "%Y-%m-%d") + (?l "DDmmmYYYY" "%d%b%Y") + (?t "Time" "%H:%M"))) + (key (read-key + (cl-loop for (key label _) in formats + concat (format "[%s] %s " + (propertize (single-key-description key) 'face 'bold) + label))))) + (->> (alist-get key formats) + cl-second + format-time-string + downcase ; Jan -> jan + insert))) +``` + +## u/noi-gai [πŸ”—](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8mo1bz) +**Votes:** 9 + +Put the control keys next to space, mimicking mac's command key (which is effectively used as the equivalent of ctrl yet next to the space it's easier to press) + +Win - Alt - Ctrl - Space - Ctrl - Alt - Win + +## u/Nondv [πŸ”—](https://www.reddit.com/r/emacs/comments/108zin2/comment/j4ct1y1) +**Votes:** 9 + +Maybe not new for anyone but I only recently found out that `C-c ` is conventionally reserved for user bindings. I was constantly afraid to define my own bindings bc of a potential clash so tended to use M-x instead. Now I finally bind my most used commands. + +With the above in mind, Im also afraid to forget my bindings. I use which-key package so I wrote a function "define-my-keybinding letter fn" which binds the letter to `C-c ` and to "my-bindings" keyset (prefix) which itself is bound to `C-c m`. Basically, if i forget what bindings I use, I just press C-c m and which-key shows me all of MY bindings (yes, it shows them with C-c too but it's mixed with mode bindings so not helpful) + +## u/andyjda [πŸ”—](https://www.reddit.com/r/emacs/comments/yqciht/comment/iw00xhx) +**Votes:** 9 + +I started using `god-mode`, but I found it hard to get used to it at first: there was no easy way to check what command would be triggered by what key-sequence. + +I wrote up a `god-mode`\-specific `describe-key`, which translates `god-mode` key-sequences into commands and shows their usual description. I think it's a great way to get familiar with how the package handles keys, and it allows users to invoke `describe-key` without leaving god-mode (previously, most keys would just show information about the generic `god-mode-self-insert-command`) + +I also reached out to the package's maintainers, and this feature (after some tweaking) [just got added to the master branch](https://github.com/emacsorphanage/god-mode). It was a great way to get familiar with `god-mode` code and its behavior, and I'm happy to have made my first contribution to an Emacs package. + +## u/attento_redaz [πŸ”—](https://www.reddit.com/r/emacs/comments/wqjare/comment/iku77h0) +**Votes:** 9 + +Using [zotra](https://github.com/mpedramfar/zotra), [citar](https://github.com/emacs-citar/citar) and some parts of the Org-cite ecosystem I hacked together a highly experimental but pretty comfortable environment for working with "org-biblatex bibliographies" which are basically like [org-bibtex](http://gewhere.github.io/org-bibtex) but with biblatex entries represented as headings with suitable properties instead of bibtex. I have a function which retrieves a biblatex entry corresponding to an url using zotra and adds a corresponding Org heading with the biblatex fields as properties, and the entry becomes available in Citar as soon as I save the document. Citing these entries then works anywhere, even in the same document with a suitable `#+bibliography: my-org-biblatex-file.org` declaration. Exporting the citations also works with the CSL exporter, no conversion is necessary to a proper biblatex bibliography file (but can be easily done if one needs biblatex-based export). Since the bibliography is an Org document, tagging, agenda commands, column view etc. can all be used with the bibliography entries. In a way it's frightening how much can be achieved building on already existing stuff and with a few lines of Emacs Lisp. + +## u/agumonkey [πŸ”—](https://www.reddit.com/r/emacs/comments/w3gx6o/comment/ih3s9fl) +**Votes:** 9 + +you can have an org-mode file in source block in an org file + +## u/diamondnbond [πŸ”—](https://www.reddit.com/r/emacs/comments/us7zae/comment/i928gaj) +**Votes:** 9 + +[I Recently discovered engine-mode.](https://github.com/DiamondBond/emacs/blob/master/config.org#initialize-engine-mode) + +## u/blankspruce [πŸ”—](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnrdt9x) +**Votes:** 9 + +Is there a package similar to wdired or wgrep that would work on magit diffs? + +Particular use cases I have in mind are: + +1. You've prepared a commit for pull request and during review someone spotted a mistake that's present in multiple files of that commit. Usually I grep the mistake and edit only affected files with wgrep (there might be some arbitrary reason to not fix similar issue in files not present in the commit). +2. In C++ it happens sometimes that you want to separate declaration and definition and in your commit you forgot to move some definitions to .cpp. +Usually I switch to `foobar.hpp`, kill the necessary part, switch to `foobar.cpp`, yank that part. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/q76kok/comment/hghp1e4) +**Votes:** 9 + +Checkout [Topsy Mode](https://github.com/alphapapa/topsy.el), it creates a header at the top of your buffer to show the name of the first function outside of your visual range. It makes scrolling through code much easier because you get an additional visual queue of your location in the buffer. It's one of those things that you never knew you wanted. It takes about 15 seconds to setup. + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/pb6w2z/comment/haddtq6) +**Votes:** 9 + +This one is probably pretty niche but it was a noticeable improvement in my workflow, so I thought I'd share. I sometimes have to fill out forms I get in PDF but that aren't fillable PDFs, merely scans of paper forms. I guess a reasonable person would install The Gimp or something like that, but I fill them out in LaTeX, using `\includegraphics` for the PDF form, and the `textpos` package to place text on top of it. + +This is requires giving the coordinates you want the text placed at, which I used to do by trial and error. And as much as I normally dislike the mouse, I had to admit that for specifying a point in an image it is a much better input device than the keyboard. So I decided to write a function that would let me click on a point in a PDF and insert the coordinates in centimeters at point in the current buffer. Writing it was fairly easy and I think really illustrates the power of a system like Emacs, a Lisp Machine or Smalltalk, where you can instantly find the source code implementing any given functionality. I knew that `pdf-tools` must contain some code to translate mouse clicks into PDF document coordinates, because it lets you place annotations by clicking. I have the text annotation function bound to `a t`, and quick `C-h k` later I was reading the source code. And after that writing the following function was pretty easy: + +```elisp +(defun insert-coordinates () + "Insert coordinates (in centimeters) of mouse click." + (interactive) + (let ((pos (event-start (pdf-util-read-click-event "Click on PDF")))) + (insert + (with-selected-window (posn-window pos) + (let ((pt (pdf-util-scale-pixel-to-points (posn-object-x-y pos)))) + (cl-flet ((f (x) (* 2.54 (/ x 72.0)))) + (format "(%.1fcm,%.1fcm)" (f (car pt)) (f (cdr pt))))))))) +``` + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/p28rl5/comment/h8utmh2) +**Votes:** 9 + +Imenu is pretty adictive and it's disappointing when some major mode doesn't support it. Luckily, it's fairly easy to cook up some regexps to provide imenu support in a new major mode. For example I recently noticed that customize buffers didn't have imenu support add I wrote this: + +```elisp +(defun configure-imenu-Custom () + (setq imenu-generic-expression + '(("Faces" "^\\(?:Show\\|Hide\\) \\(.*\\) face: \\[sample\\]" 1) + ("Variables" "^\\(?:Show Value\\|Hide\\) \\([^:\n]*\\)" 1)))) + +(add-hook 'Custom-mode-hook #'configure-imenu-Custom) + +``` +One subtlety with writing this is that the customize buffers show little triangles instead of the words "Show", "Hide" or "Show Value". To figure out what text is really in the buffer you can use `C-u C-x =` which tells you about any overlays at point. + +## u/Bodertz [πŸ”—](https://www.reddit.com/r/emacs/comments/p28rl5/comment/h8iin6r) +**Votes:** 9 + +Meta: + +Apparently, the `&c.` in the title is an abbreviation of the abbreviation `etc.`, which is fine except that the sidebar's link to past threads of this kind is in fact a link to a reddit search which includes as a search term `etc.` but not `&c.`, so this thread will not show up. + +## u/globalcandyamnesia [πŸ”—](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h31xz50) +**Votes:** 9 + +If you're using the mark setting commands to expand a selection like `M-@` (mark next word) or `C-M-@` (mark next sexp), you can swap the point and mark (`C-x C-x`) and the selection will be expanded to the left rather than the right. + +So if you're in the middle of a sentence, you can press `M-@` a few times to select some words to the right, press `C-xx`, and press `M-@` a few more times to add words before the selection. + +## u/11fdriver [πŸ”—](https://www.reddit.com/r/emacs/comments/mpwapo/comment/gufsfeu) +**Votes:** 9 + +Sometimes I'm working on programs with functions a few pages long, and `follow-mode` means that I can open two windows of the same buffer side-by-side and have the text flow like a book between them. I can double or even triple the amount of lines I can view at one time. + +This has largely superseded what I might have used those code-overview map things for, which is difficult anyway, since I like to use Emacs from the terminal. + +It will keep the text aligned as you move through the file, and pairs well with binding `` and `` to the `scroll-up/down-line` commands in `xterm-mouse-mode`. + +If I'm studying/notetaking, I often end up with a few Emacs-windows arranged in a vertical stack. `winner-mode` or `window-configuration-to-register` are great, but if I want to quickly regain some vertical screen-real-estate without messing up the layout, then it's pretty intuitive to use `follow-mode` and just switch multiple windows to the same buffer, now they behave like one. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/mpwapo/comment/gudoljm) +**Votes:** 9 + +**Create Rectangular Selection with Meta+Click+Drag** + +By default, when you click and drag with the Meta key Emacs creates what it calls a "secondary selection" which is super interesting and useful, but not what this tip is about. In most editors (on the Mac anyway) option+click+drag is used to create a rectangular selection. Emacs, of course, supports this, you just need to remap it. + +```elisp +(global-set-key [M-down-mouse-1] #'mouse-drag-region-rectangle) +(global-set-key [M-drag-mouse-1] #'ignore) +(global-set-key [M-mouse-1] #'mouse-set-point) + +``` +You can also create a rectangular selection with the command `rectangle-mark-mode`. + +Don't forget to bind `replace-rectangle` to something convenient for super easy editing. + +## u/a-k-n [πŸ”—](https://www.reddit.com/r/emacs/comments/mg98ki/comment/gsvlfku) +**Votes:** 9 + +I just discovered that installing the Emacs macport homebrew formula with \`--with-mac-metal\` will significantly increase the performance of Emacs. It's buttery smooth! + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/mb8u1m/comment/gry6bfs) +**Votes:** 9 + +If you want helpful mode to completely take over all help functions, and be able to use it with helm-apropos, then add this to your config: + +```elisp +(advice-add 'describe-function :override #'helpful-function) +(advice-add 'describe-variable :override #'helpful-variable) +(advice-add 'describe-command :override #'helpful-callable) +(advice-add 'describe-key :override #'helpful-key) +(advice-add 'describe-symbol :override #'helpful-symbol) +``` + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj9ioly) +**Votes:** 9 + +Just a cool concept: if you have a keypad on your keyboard which you rarely use, bind its nums to something useful. The results are numlock-sensitive and are NOT the same keycodes as regular numbers, so they're just free keys. For example, `(define-key map (kbd "") 'winum-select-window-1)` + +## u/geza42 [πŸ”—](https://www.reddit.com/r/emacs/comments/kqsw1k/comment/gi66krb) +**Votes:** 9 + +I created a "smart" enter function for C/C++ mode. Here's what it does: + +* if you press it on a `for`/`if`/`else`/`switch` (no matter where the cursor is on the line) it will put `{`, an empty line and `}`, and will move the cursor into the body +* if you press it on a `struct`/`class`, it's similar to the previous case, but it puts a closing semicolon too. +* otherwise it will put a `;`, and a newline +* if the `{`, `;` or an empty line is already there, it won't put them again +* In comments, it will put an indented line, without continuing the comment (I configured my RET to continue commenting, so I use M-RET when I want to close the comment) + +It is useful with smartparens, because you don't have to skip the closing `)` all the time. For example, if you start writing an `if` (cursor is `|`, the closing `)` was put by smartparens): + +```elisp +if (expr|) + +``` +Then press M-RET, this will be the result: + +```elisp +if (expr) { + | +} + +``` +Since I created this function I use it all the time, I almost never press `{` `}` or `;`. + +At function signatures, it cannot figure out whether you want to create a declaration (closed by `;`) or definition (closed by `{ }`), so it puts a `;`. And the function has a parameter (`force-curly`) with which you can force putting a`{` (I mapped this to M-S-return). + +Here's the code, maybe there can be a lot of improvements: + +```elisp +(defun my-cc-mode-M-RET-context (force-curly) + (let ((c + (if force-curly 'curly + (let ((s (syntax-ppss))) + (cond + ((nth 4 s) 'comment) + ((and (eolp) (looking-back "[{;]")) 'nop) + ((save-excursion + (skip-syntax-forward " ") + (looking-at "\\(for\\|if\\|switch\\|else\\|do\\)\s?")) 'curly) + ((save-excursion + (skip-syntax-backward " ") + (skip-syntax-backward "w") + (looking-at "\\(for\\|if\\|switch\\|else\\|do\\)\s?")) 'curly) + ((save-excursion + (when (nth 3 s) (skip-syntax-backward "^\"") (backward-char)) + (skip-syntax-backward " ") + (if (looking-back ")") + (backward-sexp) + (ignore-errors (backward-up-list))) + (skip-syntax-backward "(") + (skip-syntax-backward " ") + (looking-back "for\\|if\\|switch")) 'curly) + ((save-excursion + (skip-syntax-forward " ") + (looking-at "struct\\|class")) 'curly+semicolon) + ((save-excursion + (skip-syntax-backward " ") + (skip-syntax-backward "w") + (if (looking-at "struct\\|class") t + (skip-syntax-backward "w") + (skip-syntax-backward " ") + (looking-back "struct\\|class"))) 'curly+semicolon) + (t 'semicolon)))))) + (cond + ((or (eq c 'curly) (eq c 'curly+semicolon)) + (save-excursion + (end-of-line) + (if (looking-back "{") + 'nop + c))) + ((eq c 'semicolon) + (save-excursion + (end-of-line) + (if (looking-back ";") + 'nop + c))) + (t c)))) + +(defun my-cc-mode-M-RET (force-curly) + (let ((c (my-cc-mode-M-RET-context force-curly))) + (cond + ((eq c 'nop) + (if (save-excursion + (forward-line) + (beginning-of-line) + (looking-at-p "[[:space:]]*$")) + (progn + (forward-line) + (c-indent-line)) + (end-of-line) (newline-and-indent))) + ((eq c 'comment) (newline-and-indent)) + ((eq c 'semicolon) + (end-of-line) + (self-insert-command 1 ?\;) + (newline-and-indent)) + ((eq c 'curly) + (save-excursion (end-of-line) (unless (looking-back "\s") (insert " ")) (insert "{") (newline-and-indent) (insert "}") (c-indent-line)) + (end-of-line) + (newline-and-indent)) + ((eq c 'curly+semicolon) + (save-excursion (end-of-line) (unless (looking-back "\s") (insert " ")) (insert "{") (newline-and-indent) (insert "};") (c-indent-line)) + (end-of-line) + (newline-and-indent))))) + +(define-key c-mode-base-map (kbd "M-RET") (lambda () (interactive) (my-cc-mode-M-RET nil))) +(define-key c-mode-base-map (kbd "") (lambda () (interactive) (my-cc-mode-M-RET t))) +``` + +## u/adt7799 [πŸ”—](https://www.reddit.com/r/emacs/comments/ja97xs/comment/g8op875) +**Votes:** 9 + +I find this very useful. + +When I have multiple buffers opened and I switch from another program to emacs I always get confused about which buffer the cursor is in. So I created a mapping to + +`(global-set-key (kbd "M-l") 'beacon-blink)` + +## u/Amonwilde [πŸ”—](https://www.reddit.com/r/emacs/comments/j61aoh/comment/g7wd5gj) +**Votes:** 9 + +For some this will be obvious, but I'm sure there will be at least one person who will find this useful. One of the most amazing features of Emacs to me is dabbrev-expand, by default bound to M-/. + +> Expand previous word "dynamically". + +> Expands to the most recent, preceding word for which this is a prefix. +I> ifno suitable preceding word is found, words following point are +considered. If still no suitable word is found, then look in the +> buffers accepted by the function pointed out by variable + +This command is essentially omni-autocomplete. Chances are, the term you're trying to complete is in the buffer you're using or another buffer, and you can hit multiple times to cycle through different completions. I find the expander to be quicker and more deterministic than language autocomplete about 70% of the time. It's especially useful in writing, if you use Emacs for things other than programming, as you can complete proper names and specalized vocabulary quickly. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/ixjcau/comment/g69no38) +**Votes:** 9 + +org-variable-pitch.el users might want to give [`valign`](https://github.com/casouri/valign) a look. It aligns your tables nicely, even with pictures (e.g. LaTeX previews) and links. The significance in context of OVP specifically is that you don't need to add `org-link` to `org-variable-pitch-fixed-faces` because valign-mode handles variable pitch links neatly in tables. + +If you don't use OVP but use e.g. latex fragments in tables or just pictures, this one is still very helpful. + +Kudos to the author, great little package. + +## u/kastauyra [πŸ”—](https://www.reddit.com/r/emacs/comments/ibwzcu/comment/g1zlh2t) +**Votes:** 9 + +# 27.1 do GC if no frame has focus + +I am porting my [config](https://github.com/laurynas-biveinis/dotfiles) from 26.3 to 27.1, which had the tweak to do GC whenever a frame loses focus, originally from [MatthewZMD's config](https://github.com/MatthewZMD/.emacs.d) I think: +```elisp +(add-hook 'focus-out-hook #'garbage-collect) +```elisp +27.1 NEWS say more generic (and more correct) `after-focus-change-function` should be used instead. Which pointed out that I do not want to GC on just any frame going out of focus, if another frame is being focused instead. It might be a better idea to GC if no frames at all are focused. Somewhat surprisingly I was not able to find any public dotfiles repo implementing this to copy paste from, so I tried to write my own: +```elisp +(defun dotfiles--gc-on-last-frame-out-of-focus () + "GC if all frames are inactive." + (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list))) + (garbage-collect))) + +(add-function :after after-focus-change-function + #'dotfiles--gc-on-last-frame-out-of-focus) +``` + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/hqxm5v/comment/fy0xduj) +**Votes:** 9 + +Hippie-expand google search suggestions. Completely inspired from [shell-parse.el](https://github.com/malloc47/shell-parse.el/blob/master/shell-parse.el). + +I've added `try-expand-google-completion` to the bottom of my `hippie-expand-try-functions-list` + +```elisp +(defun google-suggest--request (query) + (with-current-buffer + (url-retrieve-synchronously + (format "http://suggestqueries.google.com/complete/search?client=firefox&q=%s" query) t t 1) + (goto-char (point-min)) + (re-search-forward "^$") + (delete-region (point)(point-min))(buffer-string))) + +(defun google-suggest--list (result) + (let* ((q (progn + (string-match ",\\[\\(.*?\\)\\]" result) + (match-string 1 result))) + (r (replace-regexp-in-string "\\\"" "" q)) + (l (split-string r "," t))) + (when (> (length (car (cdr l))) 0) + (remove + (car l) + (cdr l))))) + +(defun try-expand-google-completion (old) + (unless old + (he-init-string (hippie-word-bg) (point)) + (setq he-expand-list (sort + (all-completions + he-search-string + (lambda (s y n) (google-suggest--list (google-suggest--request s)))) + 'string-lessp))) + (if (null he-expand-list) + (progn + (when old (he-reset-string)) + ()) + (he-substitute-string (car he-expand-list) t) + (setq he-tried-table (cons (car he-expand-list) (cdr he-tried-table))) + (setq he-expand-list (cdr he-expand-list)) + t)) +``` + +## u/xu-chunyang [πŸ”—](https://www.reddit.com/r/emacs/comments/fwgpkd/comment/fmochkh) +**Votes:** 9 + +Prettify the minibuffer prompt on the default value + +```elisp +(setq minibuffer-eldef-shorten-default t) +(minibuffer-electric-default-mode) + +``` +Then try eval + +```elisp +(read-string "Year (default 2019): " nil nil "2019") + +``` +You will notice "Year (default 2019): " is shorten to "Year [2019]: ", and when +you enter anything, the prompt is shorten further to "Year: ". Next time, you +use the minibuffer api, if you provide the default value, don't forget to format +the prompt using that specfic format. + +## u/kastauyra [πŸ”—](https://www.reddit.com/r/emacs/comments/ev2q9q/comment/fftpfj0) +**Votes:** 9 + +I use Emacs on my laptop either undocked, either with external screens connected. It used to be manual work of dragging and resizing frames around, and then setting up windows, but no more, thanks to the great [dispwatch](https://github.com/mnp/dispwatch) package, which handles the screen changes after Emacs has been started. I [wrote some code](https://github.com/laurynas-biveinis/dotfiles/blob/master/emacs/emacs/setup.el#L154) for the initial frame setup, and now have this, which makes the docking/undocking fully seamless: + +```elisp +;;; Window and frame geometry +(defun two-windows () + "Make frame contain two vertical windows." + (interactive) + (delete-other-windows) + (split-window-right)) + +(defun six-windows () + "Make frame contain 2x3 windows." + (interactive) + (delete-other-windows) + (split-window-below) + (split-window-right) + (split-window-right) + (windmove-down) + (split-window-right) + (split-window-right) + (balance-windows)) + +(cl-defstruct dotfiles--frame-geometry top left height width) + +(defun dotfiles--add-frame-geometry-to-initial-alist (geometry) + "Add frame GEOMETRY to `initial-frame-alist'." + (add-to-list 'initial-frame-alist + `(top . ,(dotfiles--frame-geometry-top geometry))) + (add-to-list 'initial-frame-alist + `(left . ,(dotfiles--frame-geometry-left geometry))) + (add-to-list 'initial-frame-alist + `(height . ,(dotfiles--frame-geometry-height geometry))) + (add-to-list 'initial-frame-alist + `(width . ,(dotfiles--frame-geometry-width geometry)))) + +(defun dotfiles--move-to-frame-geometry (geometry) + "Resize and repositon frame to GEOMETRY." + (set-frame-position nil (dotfiles--frame-geometry-left + geometry) + (dotfiles--frame-geometry-top geometry)) + (set-frame-size nil (dotfiles--frame-geometry-width geometry) + (dotfiles--frame-geometry-height geometry))) + +(defconst darkstar-laptop-screen '(1680 . 1050)) +(defconst darkstar-laptop-geometry + (make-dotfiles--frame-geometry :top 1 :left 1 :height 65 :width 237)) + +(defconst darkstar-external-screen '(7696 . 1692)) +(defconst darkstar-external-geometry + (make-dotfiles--frame-geometry :top 4 :left 3011 :height 117 :width 426)) + +;; Possible interim states while docking/undocking - ignore +(defconst frame-geometries-to-ignore [(3600 . 1080) (5520 . 1080) (4688 . 1692) + (3600 . 1692) (3008 . 1692)]) + +(defun diagnose-unknown-display-geometry (display-geometry) + "Diagnose unknown DISPLAY-GEOMETRY." + (message "Unknown display size %sx%s" + (car display-geometry) (cdr display-geometry))) + +(require 'seq) +(let ((display-geometry (cons (display-pixel-width) (display-pixel-height)))) + (cond ((equal display-geometry darkstar-laptop-screen) + ;; darkstar without external screens: initial frame positioned in the + ;; top left corner + (dotfiles--add-frame-geometry-to-initial-alist + darkstar-laptop-geometry) + (two-windows)) + ((equal display-geometry darkstar-external-screen) + ;; darkstar with external screens: initial frame maximized in the + ;; middle screen + (dotfiles--add-frame-geometry-to-initial-alist + darkstar-external-geometry) + (add-to-list 'initial-frame-alist '(fullscreen . fullboth)) + (add-to-list 'initial-frame-alist '(fullscreen-restore . maximized)) + (six-windows)) + ((seq-position frame-geometries-to-ignore display-geometry) ()) + (t (diagnose-unknown-display-geometry display-geometry)))) + +;;; dispwatch +(require 'dispwatch) +(defun dotfiles--display-changed-hook (new-display-geometry) + "Reconfigure frame windows on display geometry change to NEW-DISPLAY-GEOMETRY." + (message "Resizing for %s" new-display-geometry) + (cond ((equal new-display-geometry darkstar-laptop-screen) + (dotfiles--move-to-frame-geometry darkstar-laptop-geometry) + (set-frame-parameter nil 'fullscreen 'maximized) + (two-windows)) + ((equal new-display-geometry darkstar-external-screen) + (dotfiles--move-to-frame-geometry darkstar-external-geometry) + (set-frame-parameter nil 'fullscreen 'fullboth) + (six-windows)) + ((seq-position frame-geometries-to-ignore new-display-geometry) ()) + (t (diagnose-unknown-display-geometry new-display-geometry)))) + +(add-hook 'dispwatch-display-change-hooks #'dotfiles--display-changed-hook) +(dispwatch-mode 1) + +``` +Some things here might be overkill (cl-defstruct, seq?), but this was also an Emacs lisp exercise. + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fbxf389) +**Votes:** 9 + +Update your hosts file to block internet ads with this function: + +```elisp +(defun update-hosts-file () + (interactive) + ;; make a backup in case something goes wrong + (copy-file "/etc/hosts" "/tmp/" t) + (let ((coding-system-for-write 'raw-text-unix)) + (with-temp-file "/sudo:root@localhost:/etc/hosts" + (insert-file-contents "/etc/hosts") + (goto-char (point-min)) + ;; This "if block" allows you to keep your custom entries untouched + (if (re-search-forward "^# This hosts file is" nil t) + (progn + (goto-char (line-beginning-position)) + (delete-region (point)(point-max))) + (goto-char (point-max))) + ;; get the updated list + (insert + (with-current-buffer + (url-retrieve-synchronously "https://someonewhocares.org/hosts/hosts" t t) + (goto-char (point-min)) + (re-search-forward "^$") + (delete-region (point) (point-min)) + (buffer-string)))))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5qf3jw) +**Votes:** 9 + +[deleted] + +## u/c17g [πŸ”—](https://www.reddit.com/r/emacs/comments/domrl6/comment/f65iky4) +**Votes:** 9 + +I just found out the great variable `org-extend-today-until`. Basically it defines when your day really ends. If you sleep late, check it out. + +Goodbye to the days using `M-x org-todo-yesterday` at midnight, clocking off items before sleep.. + +## u/LionyxML [πŸ”—](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/kslwb72) +**Votes:** 8 + +A blog post regarding my own Emacs config aiming to get the same user experience on both TUI and GUI. +[https://www.rahuljuliato.com/posts/lemacs](https://www.rahuljuliato.com/posts/lemacs) + +## u/demosthenex [πŸ”—](https://www.reddit.com/r/emacs/comments/1b7uj43/comment/ktogga6) +**Votes:** 8 + +M-x ielm Use the repl while learning elisp coding. I had no idea! + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/18mplfa/comment/ke5xr5j) +**Votes:** 8 + +This makes stack-outputs of debug-buffers much more readable: + +```elisp +(setopt debugger-stack-frame-as-list t) +``` + +## u/hunajakettu [πŸ”—](https://www.reddit.com/r/emacs/comments/16tes2a/comment/k2f683f) +**Votes:** 8 + +It is the only thing that keeps me sane in a Windows shop. + +## u/frosch03 [πŸ”—](https://www.reddit.com/r/emacs/comments/15yxdz3/comment/jxekm3a) +**Votes:** 8 + +Very useful, but I keep forgetting it: + +If you have two buffers open in one frame, where one contains just a few lines and otherwise just uses up a lot of space, you can shrink that buffer down just right by using: `C-x -` + +And if you want to balance these two buffers again just use `C-x +` + +## u/w0ntfix [πŸ”—](https://www.reddit.com/r/emacs/comments/11ey9ft/comment/jajfxc9) +**Votes:** 8 + +turning off org-elements cache speeds up input latency for me (found from profiling): + +```elisp +(setq org-element-use-cache nil) + + +``` +it seems (at least on my org 9.6.1) to update the cache after calls to `org-self-insert-command` (so, a lot!) + +## u/snippins1987 [πŸ”—](https://www.reddit.com/r/emacs/comments/10ktqj0/comment/j67y1pt) +**Votes:** 8 + +Context: after finally getting into org-mode (org-roam specifically) and writing a bunch of elisp, I still dot not at all satisfy dealing with *org-table* or *table.el*, it just felt so out-of-place and clunky compare to the otherwise slick experiences that org-mode bring. So I basically gave up and have been linking spreadsheet files into my org files instead. + +Obviously, this isn't ideal, as I need to view tables in separated libreoffice calc windows. And the notes is not viewable on GitLab or GitHub, etc. + +So I decided to leverage org-babel to render spreadsheets inside my org notes. + +For that, I created a bash script called emacs_excel_to_png that utilize ssconvert, ImageMagick, and Firefox. The script converts the spreadsheet into HTML, then the HTML is rendered by Firefox and finally ImageMagick will be used to crop the rendered image. The script will then print an org-link so that the image is showed the result section. + +With that, in an org file, we can do something as follows: + +```elisp +#+begin_src bash :dir ./ :results raw :var ZOOM=1.3 +export ZOOM; emacs_excel_to_png \ + "note_files/emacs_excel_to_png.xlsx" \ + "note_files/emacs_excel_to_png.png" +#+end_src + +``` +The content of the emacs_excel_to_png script can be found below: + +```elisp +#!/usr/bin/env bash + +excel_file="$1" +output_file="$2" + +if [[ "$#" -lt 2 ]]; then + notify-send "Not enough parameters" + exit +fi + +tmp_dir="/dev/shm" +mkdir -p $tmp_dir/emacs_excel_to_png + +if ! [[ "$excel_file" = /* ]]; then + excel_file="${PWD}/${excel_file}" +fi + +if ! [[ "$output_file" = /* ]]; then + output_file="${PWD}/${output_file}" +fi + +if [[ -z "$ZOOM" ]]; then + ZOOM="1.3" +fi + +cd $tmp_dir/emacs_excel_to_png || exit + +# convert xlsx to html +ssconvert --export-type=Gnumeric_html:html40 --import-type=Gnumeric_Excel:xlsx "$excel_file" "$tmp_dir/emacs_excel_to_png/output.html" 2> /dev/null + +# remove captions for sheets in the output html if there is only one sheet +n_sheets=$(grep -c "" $tmp_dir/emacs_excel_to_png/output.html) +if [[ "$n_sheets" -eq "1" ]]; then + sed -i '//d' $tmp_dir/emacs_excel_to_png/output.html +fi + +# scaling the table using the ZOOM environment variable +sed -i "s/<\/style>/body { transform-origin: top left; transform: scale(${ZOOM}, ${ZOOM}); }<\/style>/g" $tmp_dir/emacs_excel_to_png/output.html + +# using firefox screenshot feature to convert from html to png +# Note: -P screenshot, we need created a seperated profile for taking screenshot so firefox won't complain about already running +/usr/bin/firefox -P screenshot --headless --window-size 3840 --screenshot file://$tmp_dir/emacs_excel_to_png/output.html > /dev/null 2>&1 + +# trim the picture to leave only the data area and invert the colors +convert -trim -negate screenshot.png screenshot.trimmed.png 2> /dev/null + +# move the resulting pictures into the appropirate place +mv screenshot.trimmed.png "$output_file" + +# print the output as org-mod pictures link +echo "[[file:${output_file}]]" + +# cleanup +rm -rf $tmp_dir/emacs_excel_to_png +``` + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/z8ltei/comment/izxi6ie) +**Votes:** 8 + +A great functionality for calculating some schedule events is `org-evaluate-time-range` (`C-c C-y`). When I need to propose an event of a particular length, I use this to get my length right between two dates. + +## u/konrad1977 [πŸ”—](https://www.reddit.com/r/emacs/comments/z2jgt5/comment/ixpdxvf) +**Votes:** 8 + +I found this one-liner yesterday, added it it to the `:config` section of **Evil**. + + `(define-key evil-visual-state-map (kbd "u") 'undo)` +Now I can undo in selected region. Like magic. + +## u/gusbrs [πŸ”—](https://www.reddit.com/r/emacs/comments/ywnt6p/comment/ix0a6ui) +**Votes:** 8 + +Some weeks ago, u/paretoOptimalDev made an interesting post about using more `next-buffer` and `previous-buffer` instead of `switch-to-buffer` (https://redd.it/ybqp3m). I liked the post and had captured it for later and only now could process it properly. + +The reasoning for using `next-buffer` and `previous-buffer` is good, but pretty much everyone complained about their default bindings. + +It is worth noting that Emacs 28 has included `repeat-mode` and Emacs 29 has added `next-buffer` and `previous-buffer` to the repeat maps. So, if you're in Emacs 29, just enabling `repeat-mode` gets you a better behavior for this. You can start with `C-x ` and, after that, just the arrow keys get you to the next or previous buffer. + +If you're still on Emacs 28, you can use: + +```elisp +(defvar buffer-navigation-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "") 'next-buffer) + (define-key map (kbd "") 'previous-buffer) + map) + "Keymap to repeat `next-buffer' and `previous-buffer'. Used in `repeat-mode'.") +(put 'next-buffer 'repeat-map 'buffer-navigation-repeat-map) +(put 'previous-buffer 'repeat-map 'buffer-navigation-repeat-map) +``` + +## u/pedzsanReddit [πŸ”—](https://www.reddit.com/r/emacs/comments/ydsjfy/comment/itw7yp2) +**Votes:** 8 + +I spent the past week cleaning up my Emacs init files and I bumped into this little gem. I call it "ZSH man page search mode" because it was the place that I first needed it. + +I do `M-x man zshall(1)` fairly frequently (and don't forget to `widen` so you can see all of the pages). Then I would start searching for what I was looking for. The man page is nicely structured so if I wanted to find "foo", search for "foo" had too many hits. What I wanted to find was the place where "foo" is described. + +This little search does the trick. It is probably useful for other man pages and perhaps even other places but for now... I call it "ZSH man page search" + +Enjoy! + +```lisp + (defun zsh-manpage-search-regexp (string &optional lax) +"Returns a string to search for entries in the zshall man page" +(format "\n[A-Z ]*\n \\{7\\}%s%s" string (if lax "" "\\_>"))) + + (isearch-define-mode-toggle zsh-manpage "z" zsh-manpage-search-regexp "\ + Searching zshall man page for where a concept is described") +``` + +## u/hairlesscaveman [πŸ”—](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikwhvfs) +**Votes:** 8 + +Question: I generally work with 3 vertical panes, with my preferred layout as left for code, middle for related test file, and right for test output or magit. However, keeping this layout is tricky; sometimes magit will open in the first pane, or the current pane when I'm focused in the middle, and deadgrep will open just anywhere… well, it's quite hectic and feels random. + +Is there any way I can get files to open in panes 1 or 2, and always have things like magit/test-output/deadgrep/etc on pane 3? I've tried "shackle" but I've had no success with it; everything seems to open in a horizontal pane at the bottom of my screen regardless of config. + +Any suggestions would be appreciated! + +## u/isamert [πŸ”—](https://www.reddit.com/r/emacs/comments/vskthv/comment/if1ua6o) +**Votes:** 8 + +I sometimes clone stuff with https instead of ssh, so this fixes that: + +```elisp +(defun isamert/git-origin-switch-to-ssh () + (interactive) + (when-let* ((https-origin (s-trim (shell-command-to-string "git config --get remote.origin.url"))) + (it (s-match "https://\\(.*\\)\\.\\(com\\|net\\|org\\)/\\(.*\\)" https-origin)) + (ssh-origin (format "git@%s.%s:%s" (nth 1 it) (nth 2 it) (nth 3 it)))) + (shell-command-to-string (format "git remote set-url origin %s" ssh-origin)))) + + +``` +It works for github/gitlab etc. You need to extend the regexp for making it work for more obscure addresses. + +## u/mmarshall540 [πŸ”—](https://www.reddit.com/r/emacs/comments/un4wf8/comment/i88sp07) +**Votes:** 8 + +Here's a little solution to a minor complaint about `isearch` that I think is fairly common. + +# The Problem + +TLDR: See [this old StackExchange question](https://emacs.stackexchange.com/questions/32373/go-to-start-of-search-string-after-ret) + +Often, I'll want to go to a precise location in a buffer to correct a typo. If that location is behind point (as it usually is if I notice the typo shortly after entering it), then `isearch-backward` works great. You press "C-r" and type some characters starting with your target until the location becomes the current result. As soon as the cursor jumps to your target location, you can use an editing command like "C-t", which exits isearch automatically for you. Or you can press "C-m" to exit isearch-mode and then start inserting text at that location. Wonderful! + +But it's a little less perfect when your target is *after* point. This is because with `isearch-forward`, point lands at the end of your search result, instead of the beginning as it does with `isearch-backward`. + +You could type your search starting with some arbitrary number of characters in front of the target. But then you have to decide in advance how many characters to use, and if you don't use enough, there might be too many results. And then if you have to keep typing past your target character to sufficiently narrow the results, point won't land where you want it. + +Another strategy would be to do the same thing as when searching backwards, start with the target character and just type characters until your target location is selected. But now point is at the other end of the result, instead of where you want it. "M-b" would exit and move point to the beginning of the word, but that assumes there are no word boundaries in your search result, and besides, your actual target won't always be the beginning of a word. Often it will be somewhere in the middle of a word. + +Or you could use C-r to move point to the beginning of the result. But then you still have to press C-m to exit the search and start inserting text at that location. And that's 2 key-presses just to finish your search, not to mention all the key-presses you did to start. + +So we can fix this. + +# My Solution + +```elisp +(defun my/isearch-bor-exit () + "Ensure point is at beginning of isearch result, then exit." + (interactive) + (when (< isearch-other-end (point)) + (goto-char isearch-other-end)) + (call-interactively 'isearch-exit)) + +(define-key isearch-mode-map ?\M-m 'my/isearch-bor-exit) + +``` +So now if I'm using isearch to get to a precise location (as opposed to just searching for a word), I can type beginning with the character at the target location, stop typing after it becomes part of the result, and press "M-m" to exit the search and make my correction. No more having to stop and think about whether I'm going backwards or forwards and whether I'll have to move point back before exiting isearch. + +# The Conclusion + +A minor problem with a fairly simple solution, but it made me happy to stop and solve it. + +I think I'll be using isearch now for a lot of things that I used to use Avy for. But Avy is still great for a bunch of reasons. Not the least of which is the `avy-isearch` command which comes in handy when there are a lot of isearch results that would require too much typing to narrow down. (And it always puts point at the beginning of the result, never at the end). + +## u/PriorOutcome [πŸ”—](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3mghuf) +**Votes:** 8 + +I wanted to be able to expand yasnippets within other yasnippets (so here tab would jump to the next position instead of trying to expand snippet), surprisingly all I had to do was: + +`:bind ("C-" . yas-expand)` + +So C- expands a snippet within a snippet, and everything just worked as I'd hoped. Once I'm done with the nested expansion just moves on to the outer one. \*shrug\* + +## u/jimm [πŸ”—](https://www.reddit.com/r/emacs/comments/tfcmcx/comment/i0vtxte) +**Votes:** 8 + +The `git grep` git command is great for finding a regex (or a simple string) everywhere in a git repo. I define the following functions and bind the `git-grep` function to `F2`. It will prompt for a regex and search for that in the repo or, if you give it a numeric prefix like `C-u` it will read the current symbol at point (the word under the cursor) and search for that. Results appear in a grep buffer, so you can use `C-g C-n` and `C-g C-p` to navigate from one result to the next. + +```elisp +(defun git-root-dir () + "Returns the current directory's root Git repo directory, or +NIL if the current directory is not in a Git repo." + (let ((dir (locate-dominating-file default-directory ".git"))) + (when dir + (file-name-directory dir)))) + +(defun git-grep (arg) + "Runs 'git grep', starting the search in the current +directory's root git repo directory. + +By default, reads the regex from the minibuffer. With a prefix +argument, initializes the search string with the current symbol +at point." + (interactive "P") + (let* ((symbol-at-point (thing-at-point 'symbol)) + (regexp (if (and arg (symbol-at-point)) + (regexp-quote symbol-at-point) + (read-from-minibuffer + "Search regexp: " nil nil nil 'grep-find-history))) + + (default-directory (git-root-dir)) + (case-ignore-flag (and (isearch-no-upper-case-p regexp t) "-i")) + (cmd (concat "git grep --extended-regexp --line-number --full-name" + " --untracked " case-ignore-flag " -- \"" regexp "\"" + " | cut -c -240"))) + (while (equal "" regexp) + (setq regexp (read-from-minibuffer + "Search regexp (must not be the empty string): " nil nil nil 'grep-find-history))) + (grep-find cmd))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/rgu8dp/comment/hoqrg9e) +**Votes:** 8 + +`bs-show` is an interesting command, it shows a pop-up-like buffer that you can use to quickly act on open buffers. There are a ton of customizations you can make and a bunch of convenient bindings. I've been trying it out instead of `list-buffers` and `ibuffer` and I like it so far, very fast. + +## u/rberaldo [πŸ”—](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnvaab8) +**Votes:** 8 + +A tiny thing I just noticed: in `tex-mode`, you can create a new environment with `C-c C-e`. With the universal argument (`C-u C-c C-e`), however, you can easily change any environment into another. + +I created an `enumerate` environment and immediately changed my mind. By chance, I intuitively tried the aforementioned command and I was instantly able to change the environment into `itemize`. + +EDIT: markdown + +## u/tryptych [πŸ”—](https://www.reddit.com/r/emacs/comments/qgrpte/comment/hicheof) +**Votes:** 8 + +A colleague just showed me Intellij's "[compare with clipboard](https://www.jetbrains.com/help/idea/comparing-files-and-folders.html#clipboard)" feature: it's fairly neat, you select a region, invoke compare-with-clipboard and get a diff of the two selections. + +It didn't take me long to implement something similar: + +```elisp +(defun ediff-compare-region-clipboard (begin end) + (interactive "r") + (save-excursion + (let ((selected-region (buffer-substring begin end)) + (clipboard-buffer (get-buffer-create "*ediff-clipboard*")) + (region-buffer (get-buffer-create "*ediff-region*"))) + (with-current-buffer clipboard-buffer + (insert (car kill-ring))) + (with-current-buffer region-buffer + (insert selected-region)) + (ediff-buffers clipboard-buffer region-buffer)))) + +``` +It's not ideal though. In particular, is there a better way to insert the "clipboard"? One thing I quickly found was that you might copy the region to compare but then so many editing commands will add to the kill-ring, so I might want to make that part of the process interactive. + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/pg69k8/comment/hbc84y3) +**Votes:** 8 + +[deleted] + +## u/b3n [πŸ”—](https://www.reddit.com/r/emacs/comments/oxo1xh/comment/h85cv7f) +**Votes:** 8 + +Little quality of life improvement if you work with multiple eshell buffers: + +```elisp +(defun eshell-buffer-name () + (rename-buffer (concat "*eshell*<" (eshell/pwd) ">") t)) + +(add-hook 'eshell-directory-change-hook #'eshell-buffer-name) +(add-hook 'eshell-prompt-load-hook #'eshell-buffer-name) +``` + +## u/oantolin [πŸ”—](https://www.reddit.com/r/emacs/comments/oxo1xh/comment/h88ph29) +**Votes:** 8 + +This isn't a tip or trick, so I guess it is covered by &c. The Init File section of the manual has this example of setting a user email address: + +```elisp +(setq user-mail-address "cheney@torture.gov") +``` + +## u/w0ntfix [πŸ”—](https://www.reddit.com/r/emacs/comments/l0ei0t/comment/gknr3hp) +**Votes:** 8 + +my first package is now on melpa! https://melpa.org/#/ct + +## u/zackallison [πŸ”—](https://www.reddit.com/r/emacs/comments/ki09cm/comment/ggoehoo) +**Votes:** 8 + +I posted this in the emacsclient thread, but I think it deserves to live here as well: + + +The emacsclient / server system is great. If you have it listening on tcp and port forward that when connecting to remote machine it adds another level of power. + +I use [emacs-vterm](https://github.com/akermu/emacs-libvterm) for a terminal inside emacs, so I've got a lot of commands remapped. Like `man` runs `emacsclient ... man ..`, which opens the man page in the "other" buffer, so it doesn't interrupt my flow. I use "scroll-other-window" to navigate the man page while I still have my prompt. `magit`, `dired`, and others map to their `emacsclient` equivalents. + +I've written wrapper script for e/emacs client that I've come to call `e`, because it saves keystrokes + +#### [The full repo is here e-emacs.sh](https://gitlab.com/zackallison/e-emacs/) + +It does the standard things you would expect, starts emacs if it's not already started, open a file in a new buffer / window / terminal and optionally wait for you to finish or have the shell continue. + +Then I added some functions that I found useful, starting with piping results from a command into an emacs buffer, such as `find . -name foo\* | e`. Naturally after that was piping from a buffer to a command: `e [file] | rot13` super secure encryption. And of course piping into and out of a buffer works as well `find . -name incriminating-evidence\* | e | xargs rm`, so you can verify / tweak the results before passing them through. Maybe you want to leave the evidence on Two Time Tommy. Who knows. + +The other nice feature is the ability to use templates. For example to edit a HTTP request and then send it to a server you can do that: `e -t header_template.txt | nc www.example.com 80` The template file is copied to a temp file which is the one that is edited. + +Or the poor man's blog system: `e -t header_template.html body_template.html footer.html > new_page.html` + +See the repo for more examples and to download. The notes of getting it working on remote machines aren't the cleanest. If you have any suggestions or features that would make your life easier let me know; submit an issue or comment here. + +#### [The full repo is here e-emacs.sh](https://gitlab.com/zackallison/e-emacs/) + +~~I really should post this on one of the share your stuff posts. But I get distracted.~~ There, I did it. + +In case you can't tell I *really* like emacs and it's client server model. + +## u/martinslot [πŸ”—](https://www.reddit.com/r/emacs/comments/kdgv43/comment/gfwlm9q) +**Votes:** 8 + +I need to try to do something custom to eshell so it feels more like home: http://www.modernemacs.com/post/custom-eshell/. Also set som aliases up. + +How does your eshell look like? + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/k8zjx5/comment/gf1msbr) +**Votes:** 8 + +[deleted] + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/k4gv0x/comment/ge8si78) +**Votes:** 8 + +Here's all I need for completions: + +```elisp +(use-package icomplete + :bind + (:map icomplete-minibuffer-map + ([C-return] . exit-minibuffer) + ([return] . minibuffer-try-complete-and-exit)) + :config + (defun minibuffer-try-complete-and-exit () + (interactive) + (minibuffer-force-complete) + (setq-local deactivate-mark nil) + (throw 'exit nil)) + :hook (after-init . icomplete-mode)) + +(use-package orderless + :ensure t + :custom + (completion-styles '(orderless)) + (orderless-matching-styles 'orderless-literal)) +``` + +## u/andrmuel [πŸ”—](https://www.reddit.com/r/emacs/comments/jn6m14/comment/gb502ps) +**Votes:** 8 + +This is something I'm not actively using anymore, but it was one of my I-love-emacs moments, so I wanted to share this for a while. + +At work, I used to have an org-mode journal where I would take meeting notes. After the meeting, I exported the subtree for the current meeting to a PDF (via ODT) and sent it to the participants via mail. + +After a while I extended org-export to get a shortcut (`C-e C-s o M`) to automatically + +* export to PDF via ODT + * using a proper corporate design & logo via ODT\_STYLES\_FILE header +* rename the file to include the current date +* open thunderbird, starting a new message with + * subject taken from document title (if exporting all) or subtree heading (if exporting subtree + * pre-filled text + * the exported PDF already attached + +​ + +```elisp +;; +;; export and send to mail +;; +(defun org-foo-export-to-foo-and-sendto-mail (org-export-function &optional async subtreep visible-only ext-plist) + (interactive) + (when (or (string-equal (file-name-extension (buffer-file-name)) "gpg") + (string-equal (file-name-extension (buffer-file-name)) "asc")) + (unless (yes-or-no-p "Really export GPG encrypted file and send via mail? ") + (throw 'abort-export-mail-gpg "export aborted by user"))) + (unless subtreep + (unless (yes-or-no-p "Really export everything and send via mail? ") + (throw 'abort-export-mail-everything "export aborted by user"))) + (let* ((title (if subtreep + ;; subtree -> use subtree heading as title + (nth 4 (org-heading-components)) + ;; whole document -> use document title + (org-element-map + (org-element-parse-buffer) + 'keyword + (lambda (e) + (when (string= "TITLE" (org-element-property :key e)) + (org-element-property :value e))) + nil + t))) + (file (file-name-nondirectory (funcall org-export-function async subtreep visible-only ext-plist))) ; note: odt export includes directory in output file name, html export includes no directory + (newfile (format "%s_%s" (format-time-string "%Y%m%d") file)) + (directory (file-name-directory (buffer-file-name)))) + (rename-file (concat directory file) (concat directory newfile) 1) + (my/thunderbird-compose-mail + "" + (format "Notes: %s" title) + "Please find attached my notes ...\n\nBest regards, Andreas" + (format "file://%s%s" + directory newfile)))) + +(defun org-odt-export-to-odt-and-sendto-mail (&optional async subtreep visible-only ext-plist) + (interactive) + (org-foo-export-to-foo-and-sendto-mail 'org-odt-export-to-odt async subtreep visible-only ext-plist)) + +(defun org-odt-export-to-pdf-and-sendto-mail (&optional async subtreep visible-only ext-plist) + (interactive) + (let ((org-odt-preferred-output-format "pdf")) + (org-odt-export-to-odt-and-sendto-mail async subtreep visible-only ext-plist))) + +(defun org-html-export-to-html-and-sendto-mail (&optional async subtreep visible-only ext-plist) + (interactive) + (org-foo-export-to-foo-and-sendto-mail 'org-html-export-to-html async subtreep visible-only ext-plist)) + +(eval-after-load 'org + '(progn + (org-export-define-derived-backend 'odt-mail 'odt + :menu-entry + '(?o "Export to ODT" + ((?m "As ODT file and send mail" org-odt-export-to-odt-and-sendto-mail) + (?M "As PDF file and send mail" org-odt-export-to-pdf-and-sendto-mail)))) + + (org-export-define-derived-backend 'html-mail 'html + :menu-entry + '(?h "Export to HTML" + ((?m "As HTML file and send mail" org-html-export-to-html-and-sendto-mail)))))) + +(defun my/thunderbird-compose-mail (&optional recipient subject body attachment) + (interactive) + (call-process "thunderbird" nil 0 nil "-compose" (format "to='%s',subject='%s',body='%s',attachment='%s'" recipient subject body attachment))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/hv3kzf/comment/fyrgnk7) +**Votes:** 8 + +[deleted] + +## u/WorldsEndless [πŸ”—](https://www.reddit.com/r/emacs/comments/hij4ga/comment/fwt1k27) +**Votes:** 8 + +Registers: in Emacs from the beginning, so simple you forget how insanely useful they can be. I use them to save text, windows, and locations. https://orys.us/tv + +## u/aartist111 [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvrw4cu) +**Votes:** 8 + +Found / c for M-x ibuffer. It filters buffers by content. +It looks like 'grep -c' . Very helpful to locate a file quickly for which you remember any word from content +Until now I had only used filters for filenames or modes only. . + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvy3geb) +**Votes:** 8 + +`(setq visual-order-cursor-movement t)` + +> If non-nil, moving cursor with arrow keys follows the visual order. +> +> When this is non-nil, will move to the character that is +to the right of point on display, and will move to the left, +disregarding the surrounding bidirectional context. Depending on the +bidirectional context of the surrounding characters, this can move point +many buffer positions away. +> +> When the text is entirely left-to-right, logical-order and visual-order +cursor movements produce identical results." + +I write in Arabic. + +## u/hairlesscaveman [πŸ”—](https://www.reddit.com/r/emacs/comments/gmkg4g/comment/fr4gdm6) +**Votes:** 8 + +I follow the format of `{ticketnumber}-{short-description}` when creating branches using Magit, but when typing the descriptive name for the branch I often type `SPC` between words instead of dash due to muscle memory when writing sentences. This causes a warning to be shown, because "Whitespace isn't allowed here", and breaks "flow" for me. + +The advice below quiets this warning, and inserts a dash whenever space is pressed. + +```elisp +(advice-add 'magit-whitespace-disallowed :around (lambda (orig-fun &rest args) (interactive) (insert "-"))) +``` + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/gmkg4g/comment/fr65b4d) +**Votes:** 8 + +TIL that I can disable ``company`` for some modes, I needed to do it because completion was really slow for the shell and eshell which have vanilla shell completion anyway. Thus + +```elisp +(use-package company + :after ispell + :diminish + :config + . + . + . + (setq company-global-modes '(not eshell-mode shell-mode)) + (global company-mode 1)) + +``` +works as intended + +## u/??? [πŸ”—](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqczes1) +**Votes:** 8 + +[A beginers guide to emacs 24 or later by sasha chua](https://sachachua.com/blog/wp-content/uploads/2013/05/How-to-Learn-Emacs-v2-Large.png) this helped me tremendously to get started with emacs. + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqcycvb) +**Votes:** 8 + +A rudimentary interface for the fabulous [Links web browser](http://links.twibright.com/user_en.html): + +```elisp +(defun links-browser (&optional link new-window) + (interactive) + (unless link + (setq link (read-from-minibuffer "url: "))) + (make-process + :name "links-browser" + :connection-type 'pipe + :command (list "links" "-g" link))) + +(defun links-search (&optional query) + (interactive) + (unless query + (setq query (read-from-minibuffer "search query: "))) + (pcase query + ((pred (string-match "\\`d .*")) + (links-search--launch "dict" (substring query 2 nil))) + ((pred (string-match "\\`b .*")) + (links-search--launch "book" (substring query 2 nil))) + ((pred (string-match "\\`w .*")) + (links-search--launch "wiki" (substring query 2 nil))) + ((pred (string-match "\\`m .*")) + (links-search--launch "imdb" (substring query 2 nil))) + ((pred (string-match "\\`y .*")) + (links-search--launch "yout" (substring query 2 nil))) + ((pred (string-match "\\`t .*")) + (links-search--launch "thes" (substring query 2 nil))) + ((pred (string-match "\\`s .*")) + (links-search--launch "syno" (substring query 2 nil))) + (_ (links-search--launch "seax" query)))) + +(defun links-search--launch (engine query) + (pcase engine + ("dict" (links-browser (format "https://en.wiktionary.org/wiki/Special:Search?search=%s" query))) + ("wiki" (links-browser (format "https://en.wikipedia.org/w/index.php?title=Special:Search&search=%s&go=Go" query))) + ("imdb" (links-browser (format "https://www.imdb.com/find?s=all&q=%s" query))) + ("yout" (links-browser (format "https://www.youtube.com/results?search_query=%s" query))) + ("book" (links-browser (format "http://gen.lib.rus.ec/search.php?req=%s&res=100&sort=id&sortmode=DESC" query))) + ("thes" (links-browser (format "https://www.powerthesaurus.org/%s" query))) + ("syno" (links-browser (format "https://duckduckgo.com/lite/?q=%s site:macmillandictionary.com" query))) + ("seax" (links-browser (format "https://search.snopyta.org/?q=%s" query))))) +``` + +## u/karthink [πŸ”—](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqfc1wi) +**Votes:** 8 + +AucTex users: You're missing out if you don't use [CDLatex](https://github.com/cdominik/cdlatex). It's primarily a fast input tool for LaTeX, sort of like snippet templates. The difference between setting up Yasnippet templates for LaTeX and CDLatex is that CDLaTeX's TAB key to jump past stuff is _always available_, not just during snippet entry. It's difficult to explain, so here are some demos: + +1. [Fast input with cdlatex and preview.el](https://gfycat.com/heavenlynegligiblehoiho) +2. [Fast input with keys displayed](https://gfycat.com/safeidolizedlangur) + +I wrote a longer post explaining [how I set up AucTex](https://www.reddit.com/r/emacs/comments/g8ecpj/advice_for_auclatex_what_keybinds_do_you_find/foo64ge/) recently. + +CDLaTeX was written by Carsten Dominik, the author of Org-mode and reftex. Thus Org ships with an `org-cdlatex` minor-mode that makes these features available in org-mode. + +## u/b3n [πŸ”—](https://www.reddit.com/r/emacs/comments/gdtqov/comment/fq9186h) +**Votes:** 8 + +If you want to switch between two themes, depending on time of day (e.g. a light and dark theme), it's as simple as this: + +```elisp +;; Light +(load-theme 'modus-operandi t t) +(run-at-time "05:00" (* 60 60 24) (lambda () (enable-theme 'modus-operandi)))) + +;; Dark +(load-theme 'modus-vivendi t t) +(run-at-time "21:00" (* 60 60 24) (lambda () (enable-theme 'modus-vivendi)))) + +``` +This selects the correct theme when starting Emacs and automatically switch when the times come. + +## u/shiroghost [πŸ”—](https://www.reddit.com/r/emacs/comments/g11mp9/comment/fnd2p6p) +**Votes:** 8 + +I use `mu4e` as email client. I guess that it is common to send some email to later discover that you forgot the attachment. + +This routines check if a mail **likely** needs an attachment by matching a simple regexp. If this is the case and there is no attach, we are asked to confirm that this is what we want to do. + +```elisp + ;; + ;; Auto-detect if there is a missing attachment in the + ;; mail and warn before sending. + ;; + ;; See https://notmuchmail.org/pipermail/notmuch/2018/026414.html + ;; + (defcustom message-likely-needs-attach-regex "attach\\|file\\|adjunto\\|fichero" + "regex that matches if a mail likely needs an attach. In + most cases this just matches a few keywords" + :type '(regexp)) + + (defun message-narrow-to-body() + "Narrow the compose buffer to the body of the mail" + (interactive) + (widen) + (goto-char (point-min)) + (narrow-to-region + (re-search-forward "--text follows this line--" nil t 1) + (point-max))) + + (defun mail-needs-attach-p () + "Count number of attach keywords in buffer and return t + if there is any" + (interactive) + (save-excursion + (message-narrow-to-body) + (let ( + (res (count-matches message-likely-needs-attach-regex))) + (widen) + (> res 0)))) + + (defun mail-number-of-attach () + "Count number of attach in buffer." + (interactive) + (save-excursion + (goto-char (point-min)) + (count-matches "<#part [^>]*filename=[^>]*>"))) + + (defun check-mail-and-send () + "Check if mail will likely have a missing attachment. + If yes ask for confirmation, if no send it." + (interactive) + (if (mail-needs-attach-p) + (if (> (mail-number-of-attach) 0) + (message-send-and-exit) + (if (y-or-n-p "Mail has NO attach. Send it anyway? ") + (message-send-and-exit))) + (message-send-and-exit))) + + (define-key mu4e-compose-mode-map (kbd "C-c C-c") 'check-mail-and-send) +``` + +## u/Desmesura [πŸ”—](https://www.reddit.com/r/emacs/comments/fgahb2/comment/fki3lrc) +**Votes:** 8 + +Any Emacs Mode for dealing with Coronavirus? + +## u/fabiopapa [πŸ”—](https://www.reddit.com/r/emacs/comments/f972tf/comment/firc94m) +**Votes:** 8 + +This may be common knowledge, but I’m always surprised at how few people know about this. + +If you have an `ALTERNATE_EDITOR=''`environment variable, and start emacsclient with no emacs server running, it will start an emacs server and try starting emacsclient again. Also works with a `-a` flag on emacsclient command. + +## u/github-alphapapa [πŸ”—](https://www.reddit.com/r/emacs/comments/f972tf/comment/fipuizk) +**Votes:** 8 + +An early WIP of a perspective-like buffer grouper/switcher based on automatically grouping buffers by recursive grouping rules written by the user: https://github.com/alphapapa/buffer-groups.el Defining the grouping rules looks like this: + +```elisp +(setf buffer-groups-groups + (buffer-groups-defgroups + (group (dir "~/org") + (auto-indirect)) + (group (dir buffer-groups-emacs-source-directory)) + (group (auto-special)) + (group (mode-match "*Helm*" (rx bos "helm-"))) + (auto-project))) + +``` +It's based on code from https://github.com/alphapapa/sbuffer.el, which should hit MELPA soon. + +## u/nv-elisp [πŸ”—](https://www.reddit.com/r/emacs/comments/eymwl9/comment/fgjj6i8) +**Votes:** 8 + +I use a number of Emacs servers daily: terminal $EDITOR, GUI Emacs, elfeed updater, and one to summon a dedicated org-capture client. +This macro allows running code on a group of servers by name. + +```elisp +;;;###autoload +(defmacro my/with-servers (servers &rest body) + "Evaluate BODY on each server in SERVERS. +If SERVERS is the symbol \all\:, evaluate BODY on all servers." + (declare (indent defun)) + (let* ((files (directory-files server-socket-dir nil nil t)) + (sockets (cond + ((eq 'all servers) + (seq-filter (lambda (file) + (not (member file '("." "..")))) + files)) + ((and (listp servers) + (seq-every-p #'stringp servers)) + servers) + (t (signal 'wrong-type-error `(((stringp), all) ,servers)))))) + `(let (current-server) + (condition-case err + (let ((servers (mapc (lambda (socket) + (setq current-server socket) + (server-eval-at socket '(progn ,@body nil))) + ',sockets))) + (format "evaled on %d servers: %s" (length servers) servers)) + (error (message "%s on server %s" err current-server)))))) + +``` +A couple of examples: + +```elisp +(defun my/kill-server (name) + "Kill emacs server named NAME." + (eval `(my/with-servers (,name) + (kill-emacs)))) + +(defun my/kill-other-servers () + "Kill other Emacs servers." + (interactive) + (eval `(my/with-servers all + (when (not (equal server-name ,server-name)) + (kill-emacs))))) + +(defun my/reload-init-on-all-servers () + "Reload init file on all Emacs servers." + (interactive) + (my/with-servers all + (load-file "~/.emacs.d/init.el"))) +``` + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/el8oq7/comment/fdggv7n) +**Votes:** 8 + +```elisp +(defun repeat-last-shell-command () + (interactive) + (let ((last-cmd (cadr (assoc 'shell-command command-history)))) + (when (y-or-n-p (concat "execute " last-cmd)) + (async-shell-command last-cmd)))) +``` + +## u/itistheblurstoftimes [πŸ”—](https://www.reddit.com/r/emacs/comments/el8oq7/comment/fdh3fyn) +**Votes:** 8 + +I had previously written a function to replace org-beginning-of-line to behave this way, but later found `org-special-ctrl-a/e` which does exactly what I wanted for C-a (and C-e). The default behavior drove me crazy and I didn't know there was a built-in fix. + +```elisp + "Non-nil means `C-a' and `C-e' behave specially in headlines and items. When t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line.`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses.When set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions.This may also be a cons cell where the behavior for `C-a' and`C-e' is set separately. + +"When t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line.`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses.When set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions. This may also be a cons cell where the behavior for `C-a' and `C-e' is set separately." + +When t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line. + +`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses. + +When set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions. This may also be a cons cell where the behavior for `C-a' and `C-e' is set separately." +``` + +## u/ji99 [πŸ”—](https://www.reddit.com/r/emacs/comments/e8nv40/comment/fadilfw) +**Votes:** 8 + +I switched to exwm two days ago (even though I was satisfied with dwm) and I'm liking it so far because it's so good to have a consistent workflow environment. + +Initially I started with using workspaces and managing X applications to automatically start in different workspaces but now I'm using a single workspace with winner mode and save window configuration (when the view I want is a few undos away). + +I had to convert a few bash scripts I regularly used to elisp but that was easy and fun. + +Here's one I wrote for youtube-dl, which I can be run from qutebrowser with a keybinding in config.py. You can choose your desired format using ivy (best format by default, or a combination of formats can be specified with "video+audio" numbers manually). You have to supply it a link from qutebrowser or another script, otherwise it uses the link in your clipboard. + +In qutebrowser: + + config.bind(',y', 'hint links spawn emacsclient -n -e "(ivy-youtube-dl \\"{hint-url}\\")"') + config.bind(',Y', 'spawn emacsclient -n -e "(ivy-youtube-dl \\"{url}\\")"') + +In emacs: + + (defun ivy-youtube-dl (&optional link) + (interactive) + (let ((link (or link (current-kill 0))) + (buffer (generate-new-buffer "*ytd-formats*"))) + (make-process :name "ytd-formats" + :buffer buffer + :command (list "youtube-dl" "--list-formats" link) + :connection-type 'pipe + :sentinel `(lambda (p e) + (set-buffer ',buffer) + (goto-char (point-min)) + (unless (search-forward "format code" nil t) + (kill-buffer) + (error "url not supported")) + (forward-line 1) + (let (list) + (while (not (eobp)) + (setq list (cons + (split-string + (buffer-substring-no-properties + (point) + (point-at-eol)) "\n" t nil) + list)) + (forward-line 1)) + (setq list (nreverse list)) + (kill-buffer "*ytd-formats*") + (ivy-read "youtube-dl formats (vid+aud): " list + :action (lambda (x) + (youtube-dl + (substring-no-properties + (format "%s" x) + (if (string-match "(" (format "%s" x)) + (match-end 0) + nil) + (string-match "[[:space:]]" (format "%s" x))) ',link)) + :sort nil + :re-builder #'regexp-quote + :preselect "best")))))) + + (defun youtube-dl (fmt link) + (let ((buffer (generate-new-buffer "*youtube-dl*"))) + (with-current-buffer buffer + (ansi-color-for-comint-mode-on) + (comint-mode)) + (make-process :name "youtube-dl" + :buffer buffer + :command (list "youtube-dl" "--flat-playlist" "--format" fmt link) + :connection-type 'pty + :filter 'comint-output-filter + :sentinal (lambda (p e) (message "Process %s %s" p (replace-regexp-in-string "\n\\'" "" e)))))) + + +And this one for downloading files with aria2c (which can download torrents and magnet links in addition to regular files). This function takes a link from another function otherwise uses your clipboard. Can be easily bound with qutebrowser like the above function. + + (defun download-with-aria2c (&optional link) + (interactive) + (let ((link (or link (current-kill 0))) + (buffer (generate-new-buffer "*aria2c*"))) + (with-current-buffer buffer + (ansi-color-for-comint-mode-on) + (comint-mode)) + (make-process :name "aria2c" + :connection-type 'pty + :buffer buffer + :command (list "aria2c" link) + :filter 'comint-output-filter + :sentinel (lambda (p e) + (make-process :name "notify" + :connection-type 'pipe + :command (list "notify-send" (format "%s %s" p e) "download complete")) + (message "Process %s %s" p (replace-regexp-in-string "\n\\'" "" e)))))) + +## u/clemera [πŸ”—](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6ys5ae) +**Votes:** 8 + +My fav org-bullets config, looks nice and you immediately know which headline level you have: + +```elisp + (setq org-bullets-bullet-list + '("β“ͺ" "β‘ " "β‘‘" "β‘’" "β‘£" "β‘€" "β‘₯" "⑦" "⑧" "⑨")) +``` + +## u/jalihal [πŸ”—](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6mm087) **Votes:** 8 -M-x ielm Use the repl while learning elisp coding. I had no idea! \ No newline at end of file +TIL about `indent-rigidly` bound to `C-x TAB`. Very useful when indenting copy-pasted python code at different levels! \ No newline at end of file diff --git a/posts.json b/posts.json index 3a6c52a..1b70b2e 100644 --- a/posts.json +++ b/posts.json @@ -1 +1 @@ -{"kuo1f9y": {"author": "vkazanov", "upvotes": 17, "body": "## u/vkazanov [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1bdm6mc/comment/kuo1f9y) \n**Votes:** 17\n\nA dump of my Emacs-related principles after 18 years of tinkering:\n\n1. Don't try to replicate a static IDE setup, Emacs is fluid. \n2. Emacs Lisp is inevitable for Emacser to make this fluidity possible.\n3. Language-agnostic is better than language-specific. \n4. Embrace display-alist, fast window manipulation, winner-mode. \n5. .emacs.el reset every couple of years to accomodate innovation. \n6. Org-mode/org-roam for all documentation, projects, tips. The agenda is not set in stone. Use queries, filters, tweak, evolve things. \n7. A contextual dwim is always better than many keybindings. \n8. Use completion everywhere on everything (vertico is magic). \n9. Contribute to the core and favourite packages.\n\nI am a beginner though, things might change."}, "ksifwh1": {"author": "geza42", "upvotes": 12, "body": "## u/geza42 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/ksifwh1) \n**Votes:** 12\n\nIf you use an LSP server with semantic highlighting, it's worth checking out the value of `font-lock-maximum-decoration`. For example, I use `c++-mode` with `lsp-mode` (with clangd), I decreased `font-lock-maximum-decoration` to `2`, and I didn't notice any highlighting difference (because the lost highlighting by `c++-mode` gets highlighted by `lsp-mode`), while `c++-mode` font-locking become faster (`c++-mode` 's font-locking works well 99.9% of the time, but sometimes it can become slow in some circumstances, these slowdowns seems to be gone).\n\nI use:`(setq font-lock-maximum-decoration '((c-mode . 2) (c++-mode . 2) (t . t)))`"}, "kslwb72": {"author": "LionyxML", "upvotes": 8, "body": "## u/LionyxML [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/kslwb72) \n**Votes:** 8\n\nA blog post regarding my own Emacs config aiming to get the same user experience on both TUI and GUI. \n[https://www.rahuljuliato.com/posts/lemacs](https://www.rahuljuliato.com/posts/lemacs)"}, "ktogga6": {"author": "demosthenex", "upvotes": 8, "body": "## u/demosthenex [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b7uj43/comment/ktogga6) \n**Votes:** 8\n\nM-x ielm Use the repl while learning elisp coding. I had no idea!"}} \ No newline at end of file +{"kuo1f9y": {"author": "vkazanov", "upvotes": 16, "body": "## u/vkazanov [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1bdm6mc/comment/kuo1f9y) \n**Votes:** 16\n\nA dump of my Emacs-related principles after 18 years of tinkering:\n\n1. Don't try to replicate a static IDE setup, Emacs is fluid. \n2. Emacs Lisp is inevitable for Emacser to make this fluidity possible.\n3. Language-agnostic is better than language-specific. \n4. Embrace display-alist, fast window manipulation, winner-mode. \n5. .emacs.el reset every couple of years to accomodate innovation. \n6. Org-mode/org-roam for all documentation, projects, tips. The agenda is not set in stone. Use queries, filters, tweak, evolve things. \n7. A contextual dwim is always better than many keybindings. \n8. Use completion everywhere on everything (vertico is magic). \n9. Contribute to the core and favourite packages.\n\nI am a beginner though, things might change."}, "ksifwh1": {"author": "geza42", "upvotes": 12, "body": "## u/geza42 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/ksifwh1) \n**Votes:** 12\n\nIf you use an LSP server with semantic highlighting, it's worth checking out the value of `font-lock-maximum-decoration`. For example, I use `c++-mode` with `lsp-mode` (with clangd), I decreased `font-lock-maximum-decoration` to `2`, and I didn't notice any highlighting difference (because the lost highlighting by `c++-mode` gets highlighted by `lsp-mode`), while `c++-mode` font-locking become faster (`c++-mode` 's font-locking works well 99.9% of the time, but sometimes it can become slow in some circumstances, these slowdowns seems to be gone).\n\nI use:`(setq font-lock-maximum-decoration '((c-mode . 2) (c++-mode . 2) (t . t)))`"}, "kslwb72": {"author": "LionyxML", "upvotes": 8, "body": "## u/LionyxML [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b20xgn/comment/kslwb72) \n**Votes:** 8\n\nA blog post regarding my own Emacs config aiming to get the same user experience on both TUI and GUI. \n[https://www.rahuljuliato.com/posts/lemacs](https://www.rahuljuliato.com/posts/lemacs)"}, "ktogga6": {"author": "demosthenex", "upvotes": 8, "body": "## u/demosthenex [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1b7uj43/comment/ktogga6) \n**Votes:** 8\n\nM-x ielm Use the repl while learning elisp coding. I had no idea!"}, "kpct4cp": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1aky57w/comment/kpct4cp) \n**Votes:** 9\n\nMany of you probably know of this, but I found \"indirect buffers\" useful.\n\nWhen I'm in Vim, I've found it useful to sometimes split a buffer into two windows, and use code folding to view different parts of the same file in the two windows. But this doesn't work in Emacs, because the \"folding\" and \"narrow\" states of the buffer are synced between the windows in contrast to Vim. One concrete use case I had: I have a huge Org file, and wanted to narrow `C-x n s` into different headings of the file in different windows.\n\nIndirect buffers solve this. It makes two buffers for one file, and these buffers have separate settings for folding, narrowing, etc. But the buffer contents are still synced, so there's no risk of diverging file states. With default keybindings, I found that `C-x 4 c C-x n s` did what I wanted."}, "kphrvz3": {"author": "bopboa", "upvotes": 10, "body": "## u/bopboa [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1aky57w/comment/kphrvz3) \n**Votes:** 10\n\nThis is how to have a beacon without installing any packages.\n\n```elisp\n (defun pulse-line (_)\n (pulse-momentary-highlight-one-line (point)))\n (setq window-selection-change-functions '(pulse-line))\n```"}, "kjcu7vp": {"author": "badmaxton", "upvotes": 9, "body": "## u/badmaxton [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/19ec8v5/comment/kjcu7vp) \n**Votes:** 9\n\nJust added this to the `:init` section of my embark configuration:\n\n```elisp\n(define-key minibuffer-local-map [C-tab] 'embark-select)\n\n```\nThis allows super-convenient marking of entries for later `embark-all` using control-tab, instead of having to go first through the `embark` menu. (By default, this key binding is mapped to `file-cache-minibuffer-complete`, which I never use.)"}, "kibmgv2": {"author": "lesliesrussell", "upvotes": 9, "body": "## u/lesliesrussell [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/198rnkj/comment/kibmgv2) \n**Votes:** 9\n\n[transient map for movement](https://gist.github.com/lesliesrussell/46302d413fcf49e9717eeea57fdadcbf)\n\nDefines a transient keymap for movement controls and sets up a global key binding to activate this transient map. This transient map, \\`my-movement-transient-map\\`, includes bindings for various movement commands like moving forward or backward by a word or character and moving to the next or previous line. The \\`activate-my-movement-map\\` function is defined to activate this transient map, and it is globally bound to \\`C-f\\`.\n\n​\n\nThis setup allows you to press \\`C-f\\` followed by one of the specified keys (\\`f\\`, \\`b\\`, \\`c\\`, \\`l\\`, \\`n\\`, \\`p\\`) to perform the corresponding movement operation. The \\`set-transient-map\\` call with a second argument of \\`t\\` ensures that the transient map stays active until one of its keys is pressed.\n\n​\n\nThis is a neat way to create a custom, modal-like interface for movement within Emacs, leveraging your Emacs Lisp skills to tailor your editing environment to your preferences. If you have any specific modifications or additional features you'd like to implement, feel free to ask!\n\nI didn't want to drop code in the thread so i put it in a gist"}, "khe4dq6": {"author": "JDRiverRun", "upvotes": 10, "body": "## u/JDRiverRun [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1933co6/comment/khe4dq6) \n**Votes:** 10\n\nI have long had convenience bindings for `org-emphasize` like `super-i` for /italic/, that match system bindings. But I always wanted these to *be smarter*, i.e. do something useful when there is no text selected. Something like intelligently toggling emphasis depending on whether you were already in the right kind of emphasized text, or just emphasize the word at point if not.\n\n[Check out my solution](https://gist.github.com/jdtsmith/55e6a660dd4c0779a600ac81bf9bfc23) (scroll down to see how it acts). Will miss this behavior in other apps!"}, "kg4ni5d": {"author": "algor512", "upvotes": 11, "body": "## u/algor512 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/18xebux/comment/kg4ni5d) \n**Votes:** 11\n\nRecently I discovered that `C-h C-q` (or `M-x help-quick`) opens a small window showing \\*Quick Help\\* buffer with a nice overview of some basic keybindings. It seems that the content of this buffer is configurable via the variable `help-quick-sections`.\n\nI intend to use it as a cheatsheet, reminding me about rare keybindings I always forget; I believe it is easy to make it context-dependent, just by changing the value of `help-quick-sections`."}, "kgce54q": {"author": "camel_case_t", "upvotes": 10, "body": "## u/camel_case_t [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/18xebux/comment/kgce54q) \n**Votes:** 10\n\nThis is maybe more a macOS tip than an Emacs tip, but it always bothered me that `C-f`, `C-b`, etc worked in any text box, but not `M-f`, etc -- turns out that you can easily change that throughout the OS!\n\nI created this file and now Emacs keybindings work everywhere:\n\n```elisp\n/* ~/Library/KeyBindings/DefaultKeyBinding.dict */\n{\n /* Additional Emacs bindings */\n \"~f\" = \"moveWordForward:\";\n \"~b\" = \"moveWordBackward:\";\n \"~<\" = \"moveToBeginningOfDocument:\";\n \"~>\" = \"moveToEndOfDocument:\";\n \"~v\" = \"pageUp:\";\n \"~d\" = \"deleteWordForward:\";\n \"~^h\" = \"deleteWordBackward:\";\n \"~\\010\" = \"deleteWordBackward:\"; /* Option-backspace */\n \"~\\177\" = \"deleteWordBackward:\"; /* Option-delete */\n}\n\n```\nYou can read more here: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/TextDefaultsBindings/TextDefaultsBindings.html"}, "ke5xr5j": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/18mplfa/comment/ke5xr5j) \n**Votes:** 8\n\nThis makes stack-outputs of debug-buffers much more readable:\n\n```elisp\n(setopt debugger-stack-frame-as-list t)\n```"}, "kdobd72": {"author": "ayy_ess", "upvotes": 11, "body": "## u/ayy_ess [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/18hc301/comment/kdobd72) \n**Votes:** 11\n\nI recently discovered `(setq read-minibuffer-restore-windows nil)` which resolves my frustration that quitting the minibuffer would discard any changes to the window layout while the minibuffer was open. For example, by default, `M-x C-h k k C-g` quits the just opened help buffer. I'm sure to have missed many more QOL improvements from NEWS."}, "k8dlt4c": {"author": "leothrix", "upvotes": 11, "body": "## u/leothrix [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/17qh1hn/comment/k8dlt4c) \n**Votes:** 11\n\nNeed to remove an element from a list when you're tinkering with elisp?\n\nSometimes when I'm adding and removing elements from hooks or variables like `completion-at-point-functions` I'll often need to tinker with the symbols I've added. You could evaluate some form somewhere, but I like to be lazy and just:\n\n```elisp\nM-x remove-hook\n\n```\nAnd you've got an interactive interface (using `completing-read`) for removing arbitrary elements from any list-like variable. It's _technically_ for altering hooks, but you can abuse it to fool around with lists, too."}, "k8c4mz7": {"author": "Netherus", "upvotes": 9, "body": "## u/Netherus [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/17qh1hn/comment/k8c4mz7) \n**Votes:** 9\n\nJust recently found out M-u makes the next word upper case, and the same for M-l for lower case. Maybe nothing fancy, but it's kinda handy for me."}, "k4g09iw": {"author": "WorldsEndless", "upvotes": 16, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/1758wua/comment/k4g09iw) \n**Votes:** 16\n\n`(delete-blank-lines)` `(C-x C-o)` is massively useful; I use it every day for text cleanup. Press it once and it deletes all but one blank line. Press it twice and it deletes that one, too."}, "k2gb81l": {"author": "alvarogonzalezs", "upvotes": 13, "body": "## u/alvarogonzalezs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/16tes2a/comment/k2gb81l) \n**Votes:** 13\n\nIf you need to find all the occurrences of a string in the project files, but only **on some specific type of files**, you can use `consult-ripgrep` with `-- -t` in the search pattern.\n\nFor example, If you need occurrences of `fancystr` in files of type `html`, the search pattern should be `fancystr -- -t html`\n\nFrom `consult-grep` documentation, command line options can be passed to grep, specified behind `--.` The overall prompt input has the form:\n\n```elisp\n#async-input -- rg-opts#filter-string\n\n```\nI have just discovered this, and it made my day."}, "k2f683f": {"author": "hunajakettu", "upvotes": 8, "body": "## u/hunajakettu [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/16tes2a/comment/k2f683f) \n**Votes:** 8\n\nIt is the only thing that keeps me sane in a Windows shop."}, "jxekm3a": {"author": "frosch03", "upvotes": 8, "body": "## u/frosch03 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/15yxdz3/comment/jxekm3a) \n**Votes:** 8\n\nVery useful, but I keep forgetting it:\n\nIf you have two buffers open in one frame, where one contains just a few lines and otherwise just uses up a lot of space, you can shrink that buffer down just right by using: `C-x -`\n\nAnd if you want to balance these two buffers again just use `C-x +`"}, "jwff8bw": {"author": "PriorOutcome", "upvotes": 10, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/15sjm3k/comment/jwff8bw) \n**Votes:** 10\n\nI've been slowly accumulating cases for \"flexing\" the thing at point as a more general `capitalize-word` replacement:\n\n```elisp\n;; Stolen from the wiki somewhere\n(defun increment-number-at-point ()\n \"Increment the number at point.\"\n (interactive)\n (skip-chars-backward \"0-9\")\n (or (looking-at \"[0-9]+\")\n (error \"No number at point\"))\n (replace-match (number-to-string (1+ (string-to-number (match-string 0))))))\n \n(defun lw-flex ()\n \"Perform smart flexing at point.\n \nE.g. capitalize or decapitalize the next word, increment number at point.\"\n (interactive)\n (let ((case-fold-search nil))\n (call-interactively\n (cond ((looking-at \"[0-9]+\") #'increment-number-at-point)\n ((looking-at \"[[:lower:]]\") #'capitalize-word)\n ((looking-at \"==\") (delete-char 1) (insert \"!\") (forward-char 2))\n ((looking-at \"!=\") (delete-char 1) (insert \"=\") (forward-char 2))\n ((looking-at \"+\") (delete-char 1) (insert \"-\") (forward-char 1))\n ((looking-at \"-\") (delete-char 1) (insert \"+\") (forward-char 1))\n ((looking-at \"<=\") (delete-char 2) (insert \">=\") (forward-char 2))\n ((looking-at \">=\") (delete-char 2) (insert \"<=\") (forward-char 2))\n ((looking-at \"<\") (delete-char 1) (insert \">\") (forward-char 1))\n ((looking-at \">\") (delete-char 1) (insert \"<\") (forward-char 1))\n (t #'downcase-word)))))\n\n```\nI bind it to `M-c`."}, "jpwn2ts": {"author": "gusbrs", "upvotes": 10, "body": "## u/gusbrs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/14l3jn8/comment/jpwn2ts) \n**Votes:** 10\n\nI was converting some old `.odt` notes files to `.org` today, and one of the things I wanted to do was to add two spaces after end of sentence periods for proper sentence navigation. So there I was figuring out a general enough regexp for the nth time and, of course, I regretted not having taken note of this the last time. So I decided to do some searching for a good regexp and write it down this time, since this was obviously shared by someone somewhere. And it turns out Emacs has us covered, and I never knew: `repunctuate-sentences`. I have no idea if this is new or has always been there. It is new to me. It uses `query-replace-regexp`, so it's the same experience. And also can be configured for exclusions with `repunctuate-sentences-filter`. Neat!"}, "jl5zu6z": {"author": "leothrix", "upvotes": 12, "body": "## u/leothrix [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/13jvhp7/comment/jl5zu6z) \n**Votes:** 12\n\nFor `use-package` users (which I assume is many of us), did you know that profiling is easy to do? I'm not talking about `esup`, but a built-in capability that makes it very straightforward to find places to optimize your `init.el` for significantly faster start times.\n\nEnable `use-package-compute-statistics` right after you load `use-package`:\n\n```elisp\n(setq use-package-compute-statistics t)\n\n```\nRestart emacs, and then invoke `use-package-report`. You'll get a table of the load times for each package that `use-package` manages. I discovered this and found an immediate way to cut my startup time in half by fixing a few packages that weren't deferred properly by adding the right `:hook` keyword."}, "jhrzybp": {"author": "BunnyLushington", "upvotes": 9, "body": "## u/BunnyLushington [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/12zaqju/comment/jhrzybp) \n**Votes:** 9\n\nI found myself debugging [JWTs](https://jwt.io) earlier this week and whomped up a little function to decode them from a region into a help buffer.\n\n```elisp\n(defun ii/decode-jwt (start end &optional jwt)\n \"Decode JWT in region and print to help buffer.\"\n (interactive \"r\")\n (let* ((tok (if jwt jwt\n (buffer-substring start end)))\n (data (s-split \"\\\\.\" tok))\n (header (car data))\n (claims (cadr data)))\n(with-temp-buffer\n (insert (format \"%s\\n\\n%s\"\n (base64-decode-string header t)\n (base64-decode-string claims t)))\n (json-pretty-print-buffer)\n (with-output-to-temp-buffer \"*JWT*\"\n (princ (buffer-string)))))\n t)\n```\n\nI'd forgotten about `with-output-to-temp-buffer` which is pretty handy. The `t` at the end is there just to suppress an overly large echo area message.\n\n(This should be obvious but note that the JWT is not validated or verified. This is intended for debugging only and the JWT should not be trusted.)"}, "jgwlxuw": {"author": "WorldsEndless", "upvotes": 17, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/12rlq4a/comment/jgwlxuw) \n**Votes:** 17\n\nOften when literate programming I want to split up a code block, maybe copy-pasted with multiple functions in it, into separate blocks so I can put some text in between them. The command, with cursor within a `BEGIN_SRC` block, is `org-babel-demarcate-block` `(C-c C-v d)`."}, "jg34ody": {"author": "alvarogonzalezs", "upvotes": 17, "body": "## u/alvarogonzalezs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/12jexep/comment/jg34ody) \n**Votes:** 17\n\nI'm a big user of `ffap`. I use this function with `M-x` each time I want to open a file whose name is under the cursor.\n\nBut this week I discovered `ffap-bindings`. This function replaces some key bindings to use `ffap` when it makes sense. For example, it replaces `find-file` with `find-file-at-point`, so the usual keybindings are enriched at no cost."}, "jf167qh": {"author": "AndreaSomePostfix", "upvotes": 19, "body": "## u/AndreaSomePostfix [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/12cd23k/comment/jf167qh) \n**Votes:** 19\n\norg-mode is amazing!\n\nI discovered \\`org-copy-visible\\` the other day, when I wanted to send somebody only the outline of my notes.\n\nThat function (which is bound to C-c C-x v by default) let you copy just the outline for the selected region: very useful!"}, "jf3ohpv": {"author": "sauntcartas", "upvotes": 9, "body": "## u/sauntcartas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/12cd23k/comment/jf3ohpv) \n**Votes:** 9\n\nI work with multiple Git repositories in my day job, but one in particular occupies 95% of my time. I've often wished I could set up Projectile so that if I run one of its commands while not in any repo, it will behave as if I'd changed to that main repo first. I couldn't find a built-in way to do that, but got the effect I wanted with some advice:\n\n```elisp\n(defun default-to-main-project (dir)\n (or dir *main-project-dir*))\n\n(advice-add 'projectile-ensure-project :override #'default-to-main-project)\n\n```\nI lose some of the functionality of `projectile-ensure-project`, but I never used it anyway."}, "jc9t4tc": {"author": "PriorOutcome", "upvotes": 13, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/11rq2gl/comment/jc9t4tc) \n**Votes:** 13\n\nPlain old `query-replace` has many cool features, first of all it respects the active region (if it's active it will only query for replacements in the active region). There are many useful keys in addition to plain `y`/`n`:\n\n`!`: replaces all remaning matches\n\n`u`: undo last replacement\n\n`E`: changes replacement string on the fly\n\nAnd many more you can see using `?`."}, "jca66k0": {"author": "slinchisl", "upvotes": 9, "body": "## u/slinchisl [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/11rq2gl/comment/jca66k0) \n**Votes:** 9\n\nI'm once again reminded of the utility of `read-key` for small functions where one wants a nicer interface for choosing an alternative than universal arguments; taking an optional prompt, it simply reads a key from the keyboard and returns it.\n\nFor example, I recently wanted a function that prints a set of predefined dates for me into the current buffer, and it was as easy as\n\n```elisp\n(defun slot/insert-time ()\n (interactive)\n (let* ((formats '((?i \"ISO 8601\" \"%Y-%m-%d\")\n (?l \"DDmmmYYYY\" \"%d%b%Y\")\n (?t \"Time\" \"%H:%M\")))\n (key (read-key\n (cl-loop for (key label _) in formats\n concat (format \"[%s] %s \"\n (propertize (single-key-description key) 'face 'bold)\n label)))))\n (->> (alist-get key formats)\n cl-second\n format-time-string\n downcase ; Jan -> jan\n insert)))\n```"}, "jbe06qv": {"author": "geza42", "upvotes": 14, "body": "## u/geza42 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/11lqkbo/comment/jbe06qv) \n**Votes:** 14\n\nYou can toggle vertico's height between 15 and \"almost full frame\" with this. When vertico is invoked, it will always have a height of 15. But if you have a lot of matches, and like to have a better overview, press the binding, and vertico will show a full frame of matches. This is useful for example when `consult-buffer` presents a lot of buffers.\n\n```elisp\n(advice-add 'vertico--setup :before (lambda () (setq vertico-count 15)))\n(define-key minibuffer-local-map (kbd \"s-'\") (lambda ()\n (interactive)\n (let ((vertico-resize t))\n (setq vertico-count (if (= vertico-count 15) (- (frame-height) 5) 15))\n (vertico--exhibit))))\n\n```\nAnother useful feature is to kill buffers in `consult-buffer` without manually invoking `embark-act`. I miss this feature from Helm, where you can do actions using only one binding (no need to press an intermediate binding which invokes `embark-act`). Note, I just blindly copied some of the logic from `embark`, maybe there are some unnecessary things here.\n\n```elisp\n(defun my-embark-M-k (&optional arg)\n (interactive \"P\")\n (require 'embark)\n (if-let ((targets (embark--targets)))\n (let* ((target\n (or (nth\n (if (or (null arg) (minibufferp))\n 0\n (mod (prefix-numeric-value arg) (length targets)))\n targets)))\n (type (plist-get target :type)))\n (cond\n ((eq type 'buffer)\n (let ((embark-pre-action-hooks))\n (embark--act 'kill-buffer target)))))))\n\n(define-key minibuffer-local-map (kbd \"M-k\") 'my-embark-M-k)\n\n```\nI'm not sure whether these two can be achieved out-of-the box, but I didn't find these functionalities, so I created them."}, "jajfxc9": {"author": "w0ntfix", "upvotes": 8, "body": "## u/w0ntfix [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/11ey9ft/comment/jajfxc9) \n**Votes:** 8\n\nturning off org-elements cache speeds up input latency for me (found from profiling):\n\n```elisp\n(setq org-element-use-cache nil)\n\n\n```\nit seems (at least on my org 9.6.1) to update the cache after calls to `org-self-insert-command` (so, a lot!)"}, "j8m9rlj": {"author": "PriorOutcome", "upvotes": 20, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8m9rlj) \n**Votes:** 20\n\nWith an active region, you can freely toggle between rectangle mark mode and normal, you don't need to get rid of your active region to switch between the two."}, "j8mo1bz": {"author": "noi-gai", "upvotes": 9, "body": "## u/noi-gai [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8mo1bz) \n**Votes:** 9\n\nPut the control keys next to space, mimicking mac's command key (which is effectively used as the equivalent of ctrl yet next to the space it's easier to press)\n\nWin - Alt - Ctrl - Space - Ctrl - Alt - Win"}, "j8mpo5y": {"author": "pathemata", "upvotes": 10, "body": "## u/pathemata [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/112t0uo/comment/j8mpo5y) \n**Votes:** 10\n\nDoes anyone have an `aspell` setup with multiple dictionaries?\n\nWhen I try `--extra-dict` option I get an error: `Expected language \"en\" but got \"de\"`."}, "ja41lso": {"author": "AnugNef4", "upvotes": 11, "body": "## u/AnugNef4 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/112t0uo/comment/ja41lso) \n**Votes:** 11\n\nHow I got my Info Directory node `C-h i` to display all my installed .info files living under `/opt/homebrew` on an M1 Mac. I run emacs-plus@29 from [d12frosted on github](https://github.com/d12frosted/homebrew-emacs-plus).\n\ninit.el snippet\n\n```elisp\n(require 'info)\n(info-initialize)\n(push \"/opt/homebrew/share/info\" Info-directory-list)\n\n```\nrun this shell script to update the Directory node.\n\n```elisp\n#!/usr/bin/env bash\n \nINFO_DIR=\"/opt/homebrew/share/info\"\nwhile read -r f; do\n install-info --debug --keep-old \"$f\" \"$INFO_DIR\"/dir\ndone <<< $(find /opt/homebrew/Cellar -name \\*.info)\n```"}, "j6rmvvf": {"author": "PriorOutcome", "upvotes": 33, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/10qo7vb/comment/j6rmvvf) \n**Votes:** 33\n\nWhen you have an active region, `undo` will only undo changes in that region instead of the whole file."}, "j5umed8": {"author": "eleven_cupfuls", "upvotes": 12, "body": "## u/eleven_cupfuls [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/10ktqj0/comment/j5umed8) \n**Votes:** 12\n\nI jump into the built-in Elisp files a lot to see how things work. The indentation there is GNU standard, which uses a mix of tabs and spaces for alignment. The tabs have to be rendered as 8 spaces wide for the alignment to work, and I don't actually want that setting anywhere else. Since the files on Mac are inside the application bundle, I don't want to just add a .dir-locals.el file next to them, either.\n\n[Directory classes](https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html) to the rescue! My config makes a new directory variable class, `builtin-elisp`, with a list saying that `emacs-lisp-mode` should use a `tab-width` of 8. Then it applies that class to the Elisp files in the application bundle:\n\n```elisp\n(use-package elisp-mode\n :config\n (dir-locals-set-class-variables\n 'builtin-elisp\n '((emacs-lisp-mode . ((tab-width . 8)))))\n (dir-locals-set-directory-class\n (file-name-directory (directory-file-name (invocation-directory)))\n 'builtin-elisp))\n\n```\nAnd now when I visit one of those files, the alignment is always correct."}, "j67y1pt": {"author": "snippins1987", "upvotes": 8, "body": "## u/snippins1987 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/10ktqj0/comment/j67y1pt) \n**Votes:** 8\n\nContext: after finally getting into org-mode (org-roam specifically) and writing a bunch of elisp, I still dot not at all satisfy dealing with *org-table* or *table.el*, it just felt so out-of-place and clunky compare to the otherwise slick experiences that org-mode bring. So I basically gave up and have been linking spreadsheet files into my org files instead.\n\nObviously, this isn't ideal, as I need to view tables in separated libreoffice calc windows. And the notes is not viewable on GitLab or GitHub, etc.\n\nSo I decided to leverage org-babel to render spreadsheets inside my org notes.\n\nFor that, I created a bash script called emacs_excel_to_png that utilize ssconvert, ImageMagick, and Firefox. The script converts the spreadsheet into HTML, then the HTML is rendered by Firefox and finally ImageMagick will be used to crop the rendered image. The script will then print an org-link so that the image is showed the result section.\n\nWith that, in an org file, we can do something as follows:\n\n```elisp\n#+begin_src bash :dir ./ :results raw :var ZOOM=1.3\nexport ZOOM; emacs_excel_to_png \\\n \"note_files/emacs_excel_to_png.xlsx\" \\\n \"note_files/emacs_excel_to_png.png\"\n#+end_src\n\n```\nThe content of the emacs_excel_to_png script can be found below:\n\n```elisp\n#!/usr/bin/env bash\n \nexcel_file=\"$1\"\noutput_file=\"$2\"\n \nif [[ \"$#\" -lt 2 ]]; then\n notify-send \"Not enough parameters\"\n exit\nfi\n \ntmp_dir=\"/dev/shm\"\nmkdir -p $tmp_dir/emacs_excel_to_png\n \nif ! [[ \"$excel_file\" = /* ]]; then\n excel_file=\"${PWD}/${excel_file}\"\nfi\n \nif ! [[ \"$output_file\" = /* ]]; then\n output_file=\"${PWD}/${output_file}\"\nfi\n \nif [[ -z \"$ZOOM\" ]]; then\n ZOOM=\"1.3\"\nfi\n \ncd $tmp_dir/emacs_excel_to_png || exit\n \n# convert xlsx to html\nssconvert --export-type=Gnumeric_html:html40 --import-type=Gnumeric_Excel:xlsx \"$excel_file\" \"$tmp_dir/emacs_excel_to_png/output.html\" 2> /dev/null\n \n# remove captions for sheets in the output html if there is only one sheet\nn_sheets=$(grep -c \"\" $tmp_dir/emacs_excel_to_png/output.html)\nif [[ \"$n_sheets\" -eq \"1\" ]]; then\n sed -i '//d' $tmp_dir/emacs_excel_to_png/output.html\nfi\n \n# scaling the table using the ZOOM environment variable \nsed -i \"s/<\\/style>/body { transform-origin: top left; transform: scale(${ZOOM}, ${ZOOM}); }<\\/style>/g\" $tmp_dir/emacs_excel_to_png/output.html\n \n# using firefox screenshot feature to convert from html to png\n# Note: -P screenshot, we need created a seperated profile for taking screenshot so firefox won't complain about already running\n/usr/bin/firefox -P screenshot --headless --window-size 3840 --screenshot file://$tmp_dir/emacs_excel_to_png/output.html > /dev/null 2>&1\n \n# trim the picture to leave only the data area and invert the colors\nconvert -trim -negate screenshot.png screenshot.trimmed.png 2> /dev/null\n \n# move the resulting pictures into the appropirate place\nmv screenshot.trimmed.png \"$output_file\"\n \n# print the output as org-mod pictures link\necho \"[[file:${output_file}]]\"\n \n# cleanup\nrm -rf $tmp_dir/emacs_excel_to_png\n```"}, "j420ea0": {"author": "oantolin", "upvotes": 10, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/108zin2/comment/j420ea0) \n**Votes:** 10\n\nDo you want a key binding to wrap the selection in some kind of delimiter? Here's a built-in solution:\n\n```elisp\n(defvar insert-pair-map\n (let ((map (make-sparse-keymap)))\n (define-key map [t] #'insert-pair)\n map))\n\n(global-set-key (kbd \"C-S-w\") insert-pair-map)\n\n```\nThis setups up `C-S-w` to be a prefix map, `insert-pair-map`. The only key binding in `insert-pair-map` is for `[t]`, which means it is the default key binding and any key after the prefix will run the same command: `insert-pair`. Now, `insert-pair` looks at which key was used to invoke it and if it is an opening delimiter it inserts both it and the corresponding closing delimiter (and if the region is active it insert the opening delimiter at the start and the closing delimiter at the end, wrapping the region)."}, "j4ct1y1": {"author": "Nondv", "upvotes": 9, "body": "## u/Nondv [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/108zin2/comment/j4ct1y1) \n**Votes:** 9\n\nMaybe not new for anyone but I only recently found out that `C-c ` is conventionally reserved for user bindings. I was constantly afraid to define my own bindings bc of a potential clash so tended to use M-x instead. Now I finally bind my most used commands.\n\nWith the above in mind, Im also afraid to forget my bindings. I use which-key package so I wrote a function \"define-my-keybinding letter fn\" which binds the letter to `C-c ` and to \"my-bindings\" keyset (prefix) which itself is bound to `C-c m`. Basically, if i forget what bindings I use, I just press C-c m and which-key shows me all of MY bindings (yes, it shows them with C-c too but it's mixed with mode bindings so not helpful)"}, "j14grej": {"author": "luiggi_oasis", "upvotes": 10, "body": "## u/luiggi_oasis [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/zred55/comment/j14grej) \n**Votes:** 10\n\nWhat's the deal with all these completion framework I keep hearing about? Vertical elm ivy company and whatnot.\n\nI think I have company in my init.el but I'm not even sure I'm actually using it (maybe I am and I'm just unaware). But why are they everywhere? I see them mentioned in at least every any two emacs threads."}, "izxi6ie": {"author": "WorldsEndless", "upvotes": 8, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/z8ltei/comment/izxi6ie) \n**Votes:** 8\n\nA great functionality for calculating some schedule events is `org-evaluate-time-range` (`C-c C-y`). When I need to propose an event of a particular length, I use this to get my length right between two dates."}, "ixpdxvf": {"author": "konrad1977", "upvotes": 8, "body": "## u/konrad1977 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/z2jgt5/comment/ixpdxvf) \n**Votes:** 8\n\nI found this one-liner yesterday, added it it to the `:config` section of **Evil**.\n\n `(define-key evil-visual-state-map (kbd \"u\") 'undo)` \nNow I can undo in selected region. Like magic."}, "ix0a6ui": {"author": "gusbrs", "upvotes": 8, "body": "## u/gusbrs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ywnt6p/comment/ix0a6ui) \n**Votes:** 8\n\nSome weeks ago, u/paretoOptimalDev made an interesting post about using more `next-buffer` and `previous-buffer` instead of `switch-to-buffer` (https://redd.it/ybqp3m). I liked the post and had captured it for later and only now could process it properly.\n\nThe reasoning for using `next-buffer` and `previous-buffer` is good, but pretty much everyone complained about their default bindings.\n\nIt is worth noting that Emacs 28 has included `repeat-mode` and Emacs 29 has added `next-buffer` and `previous-buffer` to the repeat maps. So, if you're in Emacs 29, just enabling `repeat-mode` gets you a better behavior for this. You can start with `C-x ` and, after that, just the arrow keys get you to the next or previous buffer.\n\nIf you're still on Emacs 28, you can use:\n\n```elisp\n(defvar buffer-navigation-repeat-map\n (let ((map (make-sparse-keymap)))\n (define-key map (kbd \"\") 'next-buffer)\n (define-key map (kbd \"\") 'previous-buffer)\n map)\n \"Keymap to repeat `next-buffer' and `previous-buffer'. Used in `repeat-mode'.\")\n(put 'next-buffer 'repeat-map 'buffer-navigation-repeat-map)\n(put 'previous-buffer 'repeat-map 'buffer-navigation-repeat-map)\n```"}, "iw00xhx": {"author": "andyjda", "upvotes": 9, "body": "## u/andyjda [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/yqciht/comment/iw00xhx) \n**Votes:** 9\n\nI started using `god-mode`, but I found it hard to get used to it at first: there was no easy way to check what command would be triggered by what key-sequence. \n\nI wrote up a `god-mode`\\-specific `describe-key`, which translates `god-mode` key-sequences into commands and shows their usual description. I think it's a great way to get familiar with how the package handles keys, and it allows users to invoke `describe-key` without leaving god-mode (previously, most keys would just show information about the generic `god-mode-self-insert-command`)\n\nI also reached out to the package's maintainers, and this feature (after some tweaking) [just got added to the master branch](https://github.com/emacsorphanage/god-mode). It was a great way to get familiar with `god-mode` code and its behavior, and I'm happy to have made my first contribution to an Emacs package."}, "itw7yp2": {"author": "pedzsanReddit", "upvotes": 8, "body": "## u/pedzsanReddit [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ydsjfy/comment/itw7yp2) \n**Votes:** 8\n\nI spent the past week cleaning up my Emacs init files and I bumped into this little gem. I call it \"ZSH man page search mode\" because it was the place that I first needed it.\n\nI do `M-x man zshall(1)` fairly frequently (and don't forget to `widen` so you can see all of the pages). Then I would start searching for what I was looking for. The man page is nicely structured so if I wanted to find \"foo\", search for \"foo\" had too many hits. What I wanted to find was the place where \"foo\" is described.\n\nThis little search does the trick. It is probably useful for other man pages and perhaps even other places but for now... I call it \"ZSH man page search\"\n\nEnjoy!\n\n```lisp\n (defun zsh-manpage-search-regexp (string &optional lax)\n\"Returns a string to search for entries in the zshall man page\"\n(format \"\\n[A-Z ]*\\n \\\\{7\\\\}%s%s\" string (if lax \"\" \"\\\\_>\")))\n\n (isearch-define-mode-toggle zsh-manpage \"z\" zsh-manpage-search-regexp \"\\\n Searching zshall man page for where a concept is described\")\n```"}, "isze25m": {"author": "agumonkey", "upvotes": 16, "body": "## u/agumonkey [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/y7wrdn/comment/isze25m) \n**Votes:** 16\n\nnot emacs per se, but jack rusher did a talk about programming 'ux / ergonomics / pragmatics' with a lot of fun ideas about coding, past (lisp machines, smalltalk ... ) or more recent clojure based tools\n\nhttps://www.youtube.com/watch?v=8Ab3ArE8W3s\n\nhope you enjoy it\n\nwarning: poop emoji"}, "is1ygyw": {"author": "gusbrs", "upvotes": 14, "body": "## u/gusbrs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/y1y0kq/comment/is1ygyw) \n**Votes:** 14\n\nI've been using `mu4e` for some years now, and I really love it. However, I'm also a Gmail user, don't love it, but consider myself stuck with it (given budget constraints and it being my email for several years already). This makes me always weary of \"the next Google shenanigan\" which might break my workflow. One of the things I have learned to cherish about using `mu4e` is its integration with Org, with it's `org-capture` support, which enables me not to confuse my Inbox with my todo list, thus keeping my Inbox clean. So I came up with a preventive function, leveraging `org-protocol` to be able to capture a Gmail message from a bookmarklet on the browser. Not particularly pretty code, but functional.\n\n```elisp\n(with-eval-after-load 'org\n ;; Add org-protocol to capture email in Gmail.\n (add-to-list 'org-protocol-protocol-alist\n '(\"org-gmail-capture\" :protocol \"gmail-capture\"\n :function gb/org-protocol-gmail-capture))\n\n ;; Bookmarklet:\n ;; javascript:location.href = 'org-protocol://gmail-capture?' +\n ;; new URLSearchParams({\n ;; msg: document.getElementById(\"raw_message_text\").innerHTML});\n ;; Must be called from the \"Original message\" page.\n (defun gb/org-protocol-gmail-capture (info)\n \"Process an org-protocol://gmail-capture style url with INFO.\n\nThis function detects the raw message text element from the \\\"Original\nmessage\\\" page of a Gmail message. It then parses relevant message\nfields and calls the \\\"email\\\" org-capture template.\n\nThe location for a browser's bookmark looks like this:\n\n javascript:location.href = \\\\='org-protocol://gmail-capture?\\\\=' +\n new URLSearchParams({\n msg: document.getElementById(\\\"raw_message_text\\\").innerHTML});\n\nThe sub-protocol used to reach this function is set in\n`org-protocol-protocol-alist'.\"\n (when-let* ((parts (org-protocol-parse-parameters info))\n (msg (plist-get parts ':msg)))\n ;; FIXME I'm not sure why this is needed, but the protocol fails on a\n ;; fresh session (before 'org-capture' is loaded), and the new frame\n ;; just flashes on the screen.\n (require 'org-capture)\n (let (subj id to from date\n from-name from-email to-name to-email from-to-name)\n (with-temp-buffer\n (insert msg)\n ;; 'mu4e~view-render-buffer' is responsible in mu4e to view /\n ;; display a new message, it handles decoding, fontification\n ;; etc. However, the message we get from org-protocol is not\n ;; really the \"original\" it is rather a html rendered version of\n ;; it. A \"Download original\" button exists, but we wouldn't be\n ;; able to retrieve it, since only the browser is logged into\n ;; the Gmail account, so we have to do with whatever the page\n ;; displays. That given, prettifying the buffer is of little\n ;; use for the fields we are interested in.\n (goto-char (point-min))\n (let ((case-fold-search))\n (while (re-search-forward\n (rx\n line-start\n (group\n (or\n \"From:\"\n \"To:\"\n \"Subject:\"\n \"Date:\"\n \"Message-ID:\"))\n \" \"\n (group (zero-or-more not-newline))\n line-end)\n nil t)\n (pcase (match-string 1)\n (\"From:\" (setq from (match-string 2)))\n (\"To:\" (setq to (match-string 2)))\n (\"Subject:\" (setq subj (match-string 2)))\n (\"Date:\" (setq date (match-string 2)))\n (\"Message-ID:\" (setq id (match-string 2)))))))\n\n ;; Ensure values\n (when (or (not from) (string-blank-p from))\n (setq from \"\"))\n (when (or (not to) (string-blank-p to))\n (setq to \"\"))\n (when (or (not subj) (string-blank-p subj))\n (setq subj \"No subject\"))\n (unless date (setq date \"\"))\n (unless id (setq id \"\"))\n ;; Clean fields\n (setq from (replace-regexp-in-string \"<\" \"<\" from t t))\n (setq from (replace-regexp-in-string \">\" \">\" from t t))\n (setq to (replace-regexp-in-string \"<\" \"<\" to t t))\n (setq to (replace-regexp-in-string \">\" \">\" to t t))\n (setq id (replace-regexp-in-string \"<\" \"\" id t t))\n (setq id (replace-regexp-in-string \">\" \"\" id t t))\n\n (let ((addr (mail-extract-address-components from)))\n (if (car addr)\n (progn\n (setq from-name (car addr))\n (setq from (format \"%s <%s>\" (car addr) (cadr addr))))\n (setq from-name (cadr addr))\n (setq from (format \"<%s>\" (cadr addr))))\n (setq from-email (cadr addr)))\n (let ((addr (mail-extract-address-components to)))\n (if (car addr)\n (progn\n (setq to-name (car addr))\n (setq to (format \"%s <%s>\" (car addr) (cadr addr))))\n (setq to-name (cadr addr))\n (setq to (format \"<%s>\" (cadr addr))))\n (setq to-email (cadr addr)))\n (setq from-to-name\n (if (member from-email\n '(\"myemail1@domain.com\"\n \"myemail2@domain.com\"\n \"myemail3@domain.com\"\n \"myemail4@domain.com\"))\n to-name\n from-name))\n\n (let ((props `(:type \"gmail\"\n :date ,date\n :from ,from\n :fromname ,from-name\n :message-id ,id\n :subject ,subj\n :to ,to\n :toname ,to-name\n :annotation ,(org-link-make-string\n (concat \"gmail:\" id) subj)\n :link ,(org-link-make-string (concat \"gmail:\" id))\n :description ,(format \"%s (%s)\" subj from-to-name)\n :annotation ,(concat \"gmail:\" id)))\n ;; Avoid call to `org-store-link', see 'org-protocol-capture'.\n (org-capture-link-is-already-stored t))\n (apply #'org-link-store-props props)\n\n (raise-frame)\n ;; Hard-coding the \"e\" capture template, since this function is very\n ;; much tailor made for it.\n (org-capture nil \"e\")))\n ;; Make sure we do not return a string, see 'org-protocol-capture'.\n nil))\n\n (org-link-set-parameters \"gmail\" :follow #'gb/org-link-gmail-open)\n (defun gb/org-link-gmail-open (link _)\n (kill-new (concat \"rfc822msgid:\" link))\n (message \"Message id copied to clipboard.\")))\n\n```\nThe corresponding bookmarklet is:\n\n```elisp\njavascript:location.href = 'org-protocol://gmail-capture?' + new URLSearchParams({msg: document.getElementById(\"raw_message_text\").innerHTML});\n\n```\nThis must be called from the \"Original message\" page (which you can get with the \"Show original\" menu item). It won't work elsewhere.\n\nThe link created is a `gmail:` type link which essentially just copies `rfc822msgid:` to the kill-ring/clipboard, which you can paste in Gmail's search bar to go to the message of interest.\n\nNot that it matters much, but the corresponding capture template is:\n\n\n```elisp\n (\"e\" \"email\" entry\n (file+headline (lambda ()\n (expand-file-name gb/email-capture-file\n gb/org-files-directory))\n \"Email\")\n \"* TODO %?%:description %(org-set-tags \\\":email:\\\")\n:PROPERTIES:\n:Message: %a\n:From: %:from\n:To: %:to\n:Date: %:date\n:END:\n:LOGBOOK:\n- Created on %U\n:END:\"\n :empty-lines 1)\n```"}, "ir96qmu": {"author": "slinchisl", "upvotes": 16, "body": "## u/slinchisl [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/xw4muy/comment/ir96qmu) \n**Votes:** 16\n\nI finally got around to writing a small README for my Emacs config, highlighting some homegrown parts that I really like. I reckon most of these things are pretty standard, but maybe some people here still find it useful: \n\n https://gitlab.com/slotThe/dotfiles/-/tree/master/emacs/.config/emacs"}, "iqb2fci": {"author": "com4", "upvotes": 15, "body": "## u/com4 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/xq6rpa/comment/iqb2fci) \n**Votes:** 15\n\nIn preparation for the inclusion of eglot into Emacs core I've switched away from lsp-mode. As a result I've also switched from flycheck and to flymake. One nice thing about flycheck is that it allowed for stacking checkers. When coding Python I liked to stack flake8 for styles and mypy for types (plus the LSP's since it's already there).\n\nFlymake allows for stacking checkers but it turns out eglot clobbers these checkers when \"adding\" the LSP's checker. To get stacked Flymake checkers with Eglot you can simply add them back after Eglot has done it's thing.\n\nFor example, here is a simple setup for Python which includes Pyright's type checking and flake8 style checking\n\n```elisp\n;; Use flake8 as the python style checker by default\n(setq python-flymake-command '(\"flake8\" \"-\"))\n \n(use-package eglot\n :hook ((python-mode . eglot-ensure)\n (eglot-managed-mode\n\t . (lambda ()\n\t ;; re-enable flymake checkers because eglot clobbers\n\t ;; them when starting\n\t (when (derived-mode-p 'python-mode)\n\t\t(add-hook 'flymake-diagnostic-functions \n 'python-flymake nil t)))))\n \n :custom\n ;; shutdown server after killing last managed buffer\n (eglot-autoshutdown t)\n :bind\n ((\"C-c l r\" . eglot-rename))\n :config\n (add-to-list 'eglot-server-programs\n `(python-mode \"pyright-langserver\" \"-w\" \"--stdio\")))\n\n```\nNow all that's left is mypy. Flymake originally used a [\"Proc\"](https://www.gnu.org/software/emacs/manual/html_mono/flymake.html#The-legacy-Proc-backend) method for creating checkers which existing mypy ones use. So for a bonus tip & trick [I've written a mypy checker in the new style](http://github.com/com4/flymake-mypy). It can be enabled when using eglot like this:\n\n```elisp\n(use-package flymake-mypy\n :straight (flymake-mypy\n :type git\n :host github\n :repo \"com4/flymake-mypy\")\n :hook ((eglot-managed-mode . (lambda ()\n\t\t\t\t (when (derived-mode-p 'python-mode)\n\t\t\t\t (flymake-mypy-enable))))))\n\n```\nAfter opening a Python buffer and executing `M-x flymake-running-backends` we are greeted with a list of stacked checkers: `Running backends: eglot-flymake-backend, flymake-mypy--run, python-flymake`."}, "ioeh1ly": {"author": "howardthegeek", "upvotes": 21, "body": "## u/howardthegeek [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/xdw6ok/comment/ioeh1ly) \n**Votes:** 21\n\nI just learned that in eshell, $$ is replaced with the output from the last command."}, "iodig8c": {"author": "zupatol", "upvotes": 29, "body": "## u/zupatol [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/xdw6ok/comment/iodig8c) \n**Votes:** 29\n\nAfter years of using emacs, I wrote my second ever elisp function to open on github the code I'm browsing in emacs.\n\n```elisp\n(defun open-on-github ()\n (interactive)\n (let\n ((repo-url (magit-git-string \"remote\" \"get-url\" \"--push\" \"origin\"))\n (commit-hash (magit-git-string \"rev-parse\" \"HEAD\"))\n (start-line (if (use-region-p)\n (line-number-at-pos (region-beginning))\n (line-number-at-pos)))\n (end-line (if (use-region-p) (line-number-at-pos (region-end)))))\n (unless repo-url (error \"not in a git repo\"))\n (browse-url\n (concat\n (substring repo-url 0 -4)\n \"/blob/\"\n commit-hash\n \"/\"\n (substring buffer-file-name (length (projectile-project-root)))\n \"#L\" (number-to-string start-line)\n (if (and (use-region-p) (< 0 (- end-line start-line)))\n (concat \"..L\" (number-to-string end-line)))\n ))))\n```"}, "innk62a": {"author": "kickingvegas1", "upvotes": 10, "body": "## u/kickingvegas1 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/x7zfs2/comment/innk62a) \n**Votes:** 10\n\nTIL when working with an Org table that `S-RET` will fill the current cell value with the value above it. "}, "inqralq": {"author": "WorldsEndless", "upvotes": 10, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/x7zfs2/comment/inqralq) \n**Votes:** 10\n\nI use follow-mode (built-in to #emacs) to split reading buffers across modern wide screens to use all the real estate. The mode keeps the panes in sync with eachother. http://images.toryanderson.com/follow-mode.gif"}, "imi3kzz": {"author": "PriorOutcome", "upvotes": 17, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/x27yc9/comment/imi3kzz) \n**Votes:** 17\n\nUpdate from a couple of weeks ago: after some grinding, I've set the parsing of past comments from this thread to auto update on a weekly basis here: [https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md](https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md)\n\nI've also fixed the broken highlighting of some code snippets, and hopefully parsed all past threads. There's 200+ comments there (sorted by upvotes), so ctrl-f ing e.g. \\`magit\\` may help you if you're looking for something specific"}, "ilotsc5": {"author": "meain", "upvotes": 15, "body": "## u/meain [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wwdpju/comment/ilotsc5) \n**Votes:** 15\n\nI use the following snippet to change background color of compilation buffer to a light red if the compilation failed. I use compilation buffer to run tests on a second monitor and this is pretty useful.\n\n```elisp\n(defun meain/compilation-colorcode (_buffer string)\n \"Change background color of compilation `_BUFFER' to red on failure.\"\n (unless (string-prefix-p \"finished\" string) ; Having color for success was distracting\n (face-remap-add-relative 'default 'diff-hl-delete)))\n(add-to-list 'compilation-finish-functions 'meain/compilation-colorcode)\n```"}, "ikwhvfs": {"author": "hairlesscaveman", "upvotes": 8, "body": "## u/hairlesscaveman [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikwhvfs) \n**Votes:** 8\n\nQuestion: I generally work with 3 vertical panes, with my preferred layout as left for code, middle for related test file, and right for test output or magit. However, keeping this layout is tricky; sometimes magit will open in the first pane, or the current pane when I'm focused in the middle, and deadgrep will open just anywhere\u2026 well, it's quite hectic and feels random.\n\nIs there any way I can get files to open in panes 1 or 2, and always have things like magit/test-output/deadgrep/etc on pane 3? I've tried \"shackle\" but I've had no success with it; everything seems to open in a horizontal pane at the bottom of my screen regardless of config.\n\nAny suggestions would be appreciated!"}, "iku77h0": {"author": "attento_redaz", "upvotes": 9, "body": "## u/attento_redaz [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wqjare/comment/iku77h0) \n**Votes:** 9\n\nUsing [zotra](https://github.com/mpedramfar/zotra), [citar](https://github.com/emacs-citar/citar) and some parts of the Org-cite ecosystem I hacked together a highly experimental but pretty comfortable environment for working with \"org-biblatex bibliographies\" which are basically like [org-bibtex](http://gewhere.github.io/org-bibtex) but with biblatex entries represented as headings with suitable properties instead of bibtex. I have a function which retrieves a biblatex entry corresponding to an url using zotra and adds a corresponding Org heading with the biblatex fields as properties, and the entry becomes available in Citar as soon as I save the document. Citing these entries then works anywhere, even in the same document with a suitable `#+bibliography: my-org-biblatex-file.org` declaration. Exporting the citations also works with the CSL exporter, no conversion is necessary to a proper biblatex bibliography file (but can be easily done if one needs biblatex-based export). Since the bibliography is an Org document, tagging, agenda commands, column view etc. can all be used with the bibliography entries. In a way it's frightening how much can be achieved building on already existing stuff and with a few lines of Emacs Lisp."}, "ikqxn0r": {"author": "thr33body", "upvotes": 14, "body": "## u/thr33body [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikqxn0r) \n**Votes:** 14\n\nI don\u2019t have any specific tip but I just want to throw it out there that if you are tired of using spacemacs or doom it was much easier to set up my own install than I thought. It only took me a couple of days of active work and now diagnosing problems is so much simpler. Not to say that you should not use either one but I wanted to learn more about emacs and I\u2019ve been really happy with the results."}, "ikrx30z": {"author": "PriorOutcome", "upvotes": 10, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wqjare/comment/ikrx30z) \n**Votes:** 10\n\nI've parsed and prettified some of the comments (I think I'm missing some, but hopefully should be fixed soonish) from past weekly tips and tricks thread here: [https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md](https://github.com/LaurenceWarne/reddit-emacs-tips-n-tricks/blob/master/out.md)\n\nIf you fancy procrastinating for a bit today..."}, "iirl0ea": {"author": "???", "upvotes": 12, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/wf0t0d/comment/iirl0ea) \n**Votes:** 12\n\nOrg mode - insert a complete set of export options:\n\n`org-export-insert-default-template`\n\nThis inserts all export keywords with default values at beginning of line.\n\nThis command is not documented in `info emacs` (v27.1)."}, "ih6ievs": {"author": "tryptych", "upvotes": 10, "body": "## u/tryptych [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/w3gx6o/comment/ih6ievs) \n**Votes:** 10\n\nEmacs has better long-lines support now??\n\nI just noticed while looking at the latest additions in the NEWS:\n\n>\\*\\* Emacs is now capable of editing files with arbitrarily long lines. The display of long lines has been optimized, and Emacs no longer chokes when a buffer on display contains long lines. If you still experience slowdowns while editing files with long lines, this is either due to font locking, which you can turn off with M-x font-lock-mode or C-u C-x x f, or to the current major mode or one of the enabled minor modes, in which case you should open the the file with M-x find-file-literally instead of C-x C-f. The variable 'long-line-threshold' controls whether and when these display optimizations are used.\n\nThat sounds like great news! Does anyone know what went into it?\n\n(edit to add: this was added some time this week. I rebuild from master weekly, and check out the NEWS diff each time)"}, "ih3s9fl": {"author": "agumonkey", "upvotes": 9, "body": "## u/agumonkey [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/w3gx6o/comment/ih3s9fl) \n**Votes:** 9\n\nyou can have an org-mode file in source block in an org file"}, "if1ua6o": {"author": "isamert", "upvotes": 8, "body": "## u/isamert [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/vskthv/comment/if1ua6o) \n**Votes:** 8\n\nI sometimes clone stuff with https instead of ssh, so this fixes that:\n\n```elisp\n(defun isamert/git-origin-switch-to-ssh ()\n (interactive)\n (when-let* ((https-origin (s-trim (shell-command-to-string \"git config --get remote.origin.url\")))\n (it (s-match \"https://\\\\(.*\\\\)\\\\.\\\\(com\\\\|net\\\\|org\\\\)/\\\\(.*\\\\)\" https-origin))\n (ssh-origin (format \"git@%s.%s:%s\" (nth 1 it) (nth 2 it) (nth 3 it))))\n (shell-command-to-string (format \"git remote set-url origin %s\" ssh-origin))))\n\n\n```\nIt works for github/gitlab etc. You need to extend the regexp for making it work for more obscure addresses."}, "ie7p6ja": {"author": "sauntcartas", "upvotes": 18, "body": "## u/sauntcartas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/vnals8/comment/ie7p6ja) \n**Votes:** 18\n\nI recently discovered `thing-at-point-looking-at`, which seems much easier to use on its own than to fully define a new kind of \"thing.\"\n\nFor a while I've been wanting to conveniently identify a Jira ticket identifier at point so I can browse to it. Ticket IDs are basically a sequence of letters, a hyphen, and a sequence of digits. First I tried using `symbol-at-point`, but that can include extraneous neighboring characters, like `/` when the ticket ID is part of a URL. Eventually, while poring over the `thingatpt` source, I found `thing-at-point-looking-at`, which quickly led to:\n\n```elisp\n(defun browse-ticket-at-point ()\n (interactive)\n (if (thing-at-point-looking-at (rx (+ alpha) \"-\" (+ digit)))\n (browse-url (format \"https://jirahost/browse/%s\" (match-string 0)))\n (error \"No ticket at point\")))\n\n```\nEasy peasy!"}, "ichiccu": {"author": "ainstr", "upvotes": 12, "body": "## u/ainstr [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/vcpk6u/comment/ichiccu) \n**Votes:** 12\n\nThe other day I discovered that you can access Spotify through dbus. Most of my use-case for spotify is hitting shuffle on ~20 of my playlists; not much searching, discovering, charts, etc. So, I didn't need any of the existing packages that require an auth token or extra local server.\n\nThis basically wraps `completing-read` over the alist stored in spotify-playlists. You can probably translate the qdbus call to dbus-send or whatever.\n\n```elisp\n;; Inspired by sp.sh: https://gist.github.com/wandernauta/6800547\n;; Could use https://codeberg.org/jao/espotify, but don't need all the functionalities\n;; Potential Issues: https://community.spotify.com/t5/Desktop-Linux/DBus-OpenUri-issue/td-p/1376397\n \n;; Could just write a fn to extract the ID, and use that in spotify-playlists\n;; Current way with full uri allows for playlist vs artist, etc.\n;; but probably don't need flexiblity for my use case\n(defun spotify--clean-uri (raw-uri)\n \"Clean RAW-URI into a dbus-acceptable uri.\"\n (let* ((url-fields (split-string\n\t\t raw-uri\n\t\t (rx (or \"/\" \"?\"))))\n\t (type (nth 3 url-fields))\n\t (id (nth 4 url-fields)))\n (concat \"spotify:\" type \":\" id)))\n \n(defvar spotify-playlists\n '((\"Artist\" . \"https://open.spotify.com/playlist/1v4UqI9mEEB4ry3a3uaorO?si=bc675402c7384080\"))\n \"Alist of spotify playlists for spotify-playlists to select from.\n RAW-URI is from right-click on playlist > Share > Copy Link to Playlist.\")\n \n(defun spotify--open-uri (raw-uri)\n \"Open RAW-URI.\"\n (let ((prefix \"qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.OpenUri \")\n\t(uri (spotify--clean-uri raw-uri)))\n (shell-command (concat prefix uri))))\n \n(defun spotify--open-playlist ()\n \"Prompt to select and play a playlist from spotify-playlists.\"\n (let* ((key (completing-read \"Playlist: \" spotify-playlists))\n\t (raw-uri (cdr (assoc key spotify-playlists))))\n (spotify--open-uri raw-uri)\n (message (format \"Now Playing: %s\" key))))\n \n(defun spotify-open-playlist ()\n \"Wrapper around `spotify--open-playlist`, to check if spotify is running.\"\n (interactive)\n (pcase\n (shell-command \"pgrep spotify\")\n (1 (message \"Spotify not running.\"))\n (0 (spotify--open-playlist))))\n```"}, "iauyzbl": {"author": "tryptych", "upvotes": 18, "body": "## u/tryptych [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/v2by7z/comment/iauyzbl) \n**Votes:** 18\n\nIt's not worth a separate post, but after spending some pleasant yak-shaving time optimising my startup using use-package, I wrote a [post about it](https://blog.markhepburn.com/posts/understanding-use-package-optimisations/). There's a few posts around suggesting features of `use-package` to optimise startup, but none of them really explained how they tied back to `autoload`, `eval-after-load`, etc so I was trying to encourage people to dig out `macroexpand` and find out."}, "iarzi1s": {"author": "char1zard4", "upvotes": 11, "body": "## u/char1zard4 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/v2by7z/comment/iarzi1s) \n**Votes:** 11\n\nThis week I learned that:\n\n-\tYou can redefine all yes/no prompts to y/n:\n`(defalias \u2018yes-or-no-p \u2018y-or-n-p)`\n\n-\t`C-c C-c` in LaTeX-mode buffers will allow you to compile/view output (I\u2019ve used LaTeX-preview-pane for the last couple of years)\n\n-\tTab-stops in yas-snippet are very handy for filling out multiple parts of a template, didn\u2019t even know these existed:\nhttps://joaotavora.github.io/yasnippet/snippet-development.html#org41a4ac7"}, "i92mn8w": {"author": "???", "upvotes": 10, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/us7zae/comment/i92mn8w) \n**Votes:** 10\n\n[deleted]"}, "i928gaj": {"author": "diamondnbond", "upvotes": 9, "body": "## u/diamondnbond [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/us7zae/comment/i928gaj) \n**Votes:** 9\n\n[I Recently discovered engine-mode.](https://github.com/DiamondBond/emacs/blob/master/config.org#initialize-engine-mode)"}, "i86hwzi": {"author": "pathemata", "upvotes": 16, "body": "## u/pathemata [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/un4wf8/comment/i86hwzi) \n**Votes:** 16\n\nSomething amazin that I have been using recently is `ripgrep-all` as the `consult-ripgrep` command to search in pdfs. \n\nIt is amazing with the `orderless` dispatchers to control the search filtering.\nI use `!` to exclude a string and `=` to match exactly.\n\nAlso amazing with `embark-collect` which allows collapsing features.\nOr within the collect buffer use `consult-line` to further filter.\nAnd even open the pdf."}, "i88sp07": {"author": "mmarshall540", "upvotes": 8, "body": "## u/mmarshall540 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/un4wf8/comment/i88sp07) \n**Votes:** 8\n\nHere's a little solution to a minor complaint about `isearch` that I think is fairly common.\n\n# The Problem\n\nTLDR: See [this old StackExchange question](https://emacs.stackexchange.com/questions/32373/go-to-start-of-search-string-after-ret)\n\nOften, I'll want to go to a precise location in a buffer to correct a typo. If that location is behind point (as it usually is if I notice the typo shortly after entering it), then `isearch-backward` works great. You press \"C-r\" and type some characters starting with your target until the location becomes the current result. As soon as the cursor jumps to your target location, you can use an editing command like \"C-t\", which exits isearch automatically for you. Or you can press \"C-m\" to exit isearch-mode and then start inserting text at that location. Wonderful!\n\nBut it's a little less perfect when your target is *after* point. This is because with `isearch-forward`, point lands at the end of your search result, instead of the beginning as it does with `isearch-backward`.\n\nYou could type your search starting with some arbitrary number of characters in front of the target. But then you have to decide in advance how many characters to use, and if you don't use enough, there might be too many results. And then if you have to keep typing past your target character to sufficiently narrow the results, point won't land where you want it.\n\nAnother strategy would be to do the same thing as when searching backwards, start with the target character and just type characters until your target location is selected. But now point is at the other end of the result, instead of where you want it. \"M-b\" would exit and move point to the beginning of the word, but that assumes there are no word boundaries in your search result, and besides, your actual target won't always be the beginning of a word. Often it will be somewhere in the middle of a word.\n\nOr you could use C-r to move point to the beginning of the result. But then you still have to press C-m to exit the search and start inserting text at that location. And that's 2 key-presses just to finish your search, not to mention all the key-presses you did to start.\n\nSo we can fix this.\n\n# My Solution\n\n```elisp\n(defun my/isearch-bor-exit ()\n \"Ensure point is at beginning of isearch result, then exit.\"\n (interactive)\n (when (< isearch-other-end (point))\n (goto-char isearch-other-end))\n (call-interactively 'isearch-exit))\n \n(define-key isearch-mode-map ?\\M-m 'my/isearch-bor-exit)\n\n```\nSo now if I'm using isearch to get to a precise location (as opposed to just searching for a word), I can type beginning with the character at the target location, stop typing after it becomes part of the result, and press \"M-m\" to exit the search and make my correction. No more having to stop and think about whether I'm going backwards or forwards and whether I'll have to move point back before exiting isearch.\n\n# The Conclusion\n\nA minor problem with a fairly simple solution, but it made me happy to stop and solve it.\n\nI think I'll be using isearch now for a lot of things that I used to use Avy for. But Avy is still great for a bunch of reasons. Not the least of which is the `avy-isearch` command which comes in handy when there are a lot of isearch results that would require too much typing to narrow down. (And it always puts point at the beginning of the result, never at the end)."}, "i3m1liu": {"author": "???", "upvotes": 26, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3m1liu) \n**Votes:** 26\n\n[removed]"}, "i3ov7vq": {"author": "TeMPOraL_PL", "upvotes": 18, "body": "## u/TeMPOraL_PL [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3ov7vq) \n**Votes:** 18\n\n`shortdoc` - one of the new things in Emacs 28.1 - is great for maintaining your own \"cheat sheets\" of Elisp functions as you discover them. For example, eval this in your Emacs session:\n\n```elisp\n(define-short-documentation-group my-datetime\n \"Querying current time\"\n (current-time\n :eval (current-time))\n (float-time\n :eval (float-time))\n \n \"Time formats\"\n (time-convert\n :eval (time-convert (current-time))\n :eval (time-convert (current-time) 'list)\n :eval (time-convert (current-time) 100000)\n :eval (time-convert (current-time) 200000)\n :eval (time-convert (current-time) t)\n :eval (time-convert (current-time) 'integer))\n \n (float-time\n :eval (float-time (current-time))))\n\n```\nAfter this, the `my-datetime` group will show as an option in `M-x shortdoc-display-group`. Additionally, if you view help for any of the functions mentioned above, the Help buffer will refer back to the `my-datetime` shortdoc group!\n\nThe example used here is a cheatsheet I just started writing for myself, as I've been researching the built-in time functions. For additional instructions on use, see `define-short-documentation-group` macro. For use examples, jump to the source of `define-short-documentation-group` and scroll down a bit - the default shortdoc groups are defined there."}, "i3mghuf": {"author": "PriorOutcome", "upvotes": 8, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/txh85s/comment/i3mghuf) \n**Votes:** 8\n\nI wanted to be able to expand yasnippets within other yasnippets (so here tab would jump to the next position instead of trying to expand snippet), surprisingly all I had to do was:\n\n`:bind (\"C-\" . yas-expand)`\n\nSo C- expands a snippet within a snippet, and everything just worked as I'd hoped. Once I'm done with the nested expansion just moves on to the outer one. \\*shrug\\*"}, "i0vtxte": {"author": "jimm", "upvotes": 8, "body": "## u/jimm [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/tfcmcx/comment/i0vtxte) \n**Votes:** 8\n\nThe `git grep` git command is great for finding a regex (or a simple string) everywhere in a git repo. I define the following functions and bind the `git-grep` function to `F2`. It will prompt for a regex and search for that in the repo or, if you give it a numeric prefix like `C-u` it will read the current symbol at point (the word under the cursor) and search for that. Results appear in a grep buffer, so you can use `C-g C-n` and `C-g C-p` to navigate from one result to the next.\n\n```elisp\n(defun git-root-dir ()\n \"Returns the current directory's root Git repo directory, or\nNIL if the current directory is not in a Git repo.\"\n (let ((dir (locate-dominating-file default-directory \".git\")))\n (when dir\n (file-name-directory dir))))\n \n(defun git-grep (arg)\n \"Runs 'git grep', starting the search in the current\ndirectory's root git repo directory.\n \nBy default, reads the regex from the minibuffer. With a prefix\nargument, initializes the search string with the current symbol\nat point.\"\n (interactive \"P\")\n (let* ((symbol-at-point (thing-at-point 'symbol))\n (regexp (if (and arg (symbol-at-point))\n (regexp-quote symbol-at-point)\n (read-from-minibuffer\n \"Search regexp: \" nil nil nil 'grep-find-history)))\n \n (default-directory (git-root-dir))\n (case-ignore-flag (and (isearch-no-upper-case-p regexp t) \"-i\"))\n (cmd (concat \"git grep --extended-regexp --line-number --full-name\"\n \" --untracked \" case-ignore-flag \" -- \\\"\" regexp \"\\\"\"\n \" | cut -c -240\")))\n (while (equal \"\" regexp)\n (setq regexp (read-from-minibuffer\n \"Search regexp (must not be the empty string): \" nil nil nil 'grep-find-history)))\n (grep-find cmd)))\n```"}, "hvbbnjq": {"author": "SamTheComputerSlayer", "upvotes": 17, "body": "## u/SamTheComputerSlayer [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/sijcap/comment/hvbbnjq) \n**Votes:** 17\n\nJust figured this out, maybe a bit of a hack...\n\nIn flyspell, I was annoyed I had to use mouse-2 when I wanted to correct a word, and I didn't want to sacrifice a major-mode keybinding to do it from the keyboard. But flyspell actually creates an overlay for misspelled words and attaches a keymap to it, which you can do I just realized- very cool. So I just bound `flyspell-correct-at-point` to \"\" in the `flyspell-mouse-map`, and now return corrects words when my cursor is on a misspelled word!\n\nBut the fact you can attach keymaps to overlays just seems so useful, will definitely use in the future."}, "hu9xfed": {"author": "AffectionateAd8985", "upvotes": 16, "body": "## u/AffectionateAd8985 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/sd10q9/comment/hu9xfed) \n**Votes:** 16\n\n`(add-hook 'org-mode-hook (lambda () (org-next-visible-heading 1)))`\n\nMove to first heading when open org files, with `org-use-speed-commands`, I can quick browse org file with only `n/p` keys."}, "hubjy3j": {"author": "???", "upvotes": 13, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/sd10q9/comment/hubjy3j) \n**Votes:** 13\n\nI was reading through the org manual, and learnt about two variables `org-agenda-category-icon-alist` and `org-agenda-prefix-format`, the first allows you to set icons for categories (`CATEGORY` property), icons can be images or symbols, this is the code I came up with and the agenda already looks more colorful and clear\n\n\n```elisp\n(setq org-agenda-category-icon-alist nil)\n(setq agenda-categories-alist\n'((\"WORK\" \"\ud83d\udcbc\") (\"SOFTWARE\" \"\ud83d\udcbb\") (\"SETUP\" \"\ud83d\udc27\") (\"EMAIL\" \"\u2709\ufe0f\")\n(\"HOME\" \"\ud83c\udfe0\") (\"WOOD\" \"\ud83e\udeb5\") (\"FAMILY\" \"\ud83d\udc6a\") (\"REPORTS\" \"\ud83d\udcda\")\n(\"INCOME\" \"\ud83d\udcb0\")))\n(dolist (icon agenda-categories-alist) (add-to-list 'org-agenda-category-icon-alist\n`(,(car icon) ,(cdr icon) nil nil :width (16.) :ascent center)))\n(defun format-agenda-prefix () (interactive)\n(setcar org-agenda-prefix-format '(agenda . \" %-2i %?-12t% s\")))\n(add-hook 'org-agenda-mode-hook 'format-agenda-prefix)\n\n```\nOf course for the emojis to show up correctly I use this:\n\n```elisp\n(set-fontset-font \"fontset-default\" 'symbol (font-spec :family \"Noto Color Emoji\"))\n\n```\nI am sure a lot of you know about these, please share your customization"}, "htnz373": {"author": "shitterwithaclitter", "upvotes": 10, "body": "## u/shitterwithaclitter [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/s7lac1/comment/htnz373) \n**Votes:** 10\n\nI recently had the idea to start emacs in org-mode but have a src block at the top so I can still write elisp snippets easily. Here's the code for anyone interested:\n\n```elisp\n;; start in org-mode with a source block for lisp evaluation\n(setq initial-major-mode #'org-mode\n initial-scratch-message \"#+begin_src emacs-lisp\\n;; This block is for text that is not saved, and for Lisp evaluation.\\n;; To create a file, visit it with \\\\[find-file] and enter text in its buffer.\\n\\n#+end_src\\n\\n\")\n```"}, "hsgj7a6": {"author": "???", "upvotes": 11, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/s21457/comment/hsgj7a6) \n**Votes:** 11\n\nPrevent horizontal scrolling from going too far left.\n\nI use Emacs on a laptop and quite often scroll with a touchpad. I also don't use line wrapping, as in code it usually looks misleading, so lines can sometimes exceed window width, either because of some long names or because the current window configuration is too narrow.\n\nHowever, when scrolling text sideways, there's a small annoyance that the scroll can go way too far to the left. E.g. if this is your window, and your text exceeds it:\n\n\n```elisp\n|Short line |\n|Some really long line o|\n|Another short line |\n\n```\nWhat I'd like to is to prevent scrolling any further than that:\n\n```elisp\n|line |\n|eally long line of text|\n|r short line |\n\n```\nBut Emacs actually allows to scroll as far as one would want to, like here:\n\n```elisp\n| |\n|t |\n| |\n\n```\nThis doesn't make sense to me, as you can't see anything at all.\nProbably handy, when you write in really long lines, and you wish to have some buffer for adding more text without triggering scrolling, but I never needed that. So I wrote such predicate:\n\n```elisp\n(defun truncated-lines-p ()\n \"Non-nil if any line is longer than `window-width' + `window-hscroll'.\n\nReturns t if any line exceeds the right border of the window.\nUsed for stopping scroll from going beyond the longest line.\nBased on `so-long-detected-long-line-p'.\"\n (save-excursion\n (goto-char (point-min))\n (let* ((window-width\n ;; this computes a more accurate width rather than `window-width', and respects\n ;; `text-scale-mode' font width.\n (/ (window-body-width nil t) (window-font-width)))\n (hscroll-offset\n ;; `window-hscroll' returns columns that are not affected by\n ;; `text-scale-mode'. Because of that, we have to recompute the correct\n ;; `window-hscroll' by multiplying it with a non-scaled value and\n ;; dividing it with a scaled width value, rounding it to the upper\n ;; boundary. Since there's no way to get unscaled value, we have to get\n ;; a width of a face that is not scaled by `text-scale-mode', such as\n ;; `window-divider' face.\n (ceiling (/ (* (window-hscroll) (window-font-width nil 'window-divider))\n (float (window-font-width)))))\n (line-number-width\n ;; compensate line numbers width\n (if (bound-and-true-p display-line-numbers-mode)\n (- display-line-numbers-width)\n 0))\n ;; subtracting 2 for extra space in case some calculations were imprecise\n (threshold (+ window-width hscroll-offset line-number-width -2)))\n (catch 'excessive\n (while (not (eobp))\n (let ((start (point)))\n (save-restriction\n (narrow-to-region start (min (+ start 1 threshold)\n (point-max)))\n (forward-line 1))\n (unless (or (bolp)\n (and (eobp) (<= (- (point) start)\n threshold)))\n (throw 'excessive t))))))))\n\n```\nThis function can calculate window width, and line width, and check if any line in the buffer exceeds the window width screen-wise. By screen-wise I mean that if you've scrolled text to the left, it will begin to return `nil` once all lines don't exceed the right border of the window, thus achieving the described behavior in the diagrams. I then define advice around the `scroll-left` function, and it works pretty good:\n\n```elisp\n(define-advice scroll-left (:around (foo &optional arg set-minimum))\n (when (and truncate-lines\n (not (memq major-mode '(vterm-mode term-mode)))\n (truncated-lines-p))\n (funcall foo arg set-minimum)))\n\n```\nThough it's not very accurate when using `text-scale-adjust`, as line width is not the same as before, the function, that reports how much the window was scrolled to the left still returns unscaled values. You can see my thoughts in the function's comments. Any suggestions on how to make it more accurate?"}, "hr4bbl5": {"author": "hxlr666", "upvotes": 16, "body": "## u/hxlr666 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rvagin/comment/hr4bbl5) \n**Votes:** 16\n\nUse org capture"}, "hoqrg9e": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rgu8dp/comment/hoqrg9e) \n**Votes:** 8\n\n`bs-show` is an interesting command, it shows a pop-up-like buffer that you can use to quickly act on open buffers. There are a ton of customizations you can make and a bunch of convenient bindings. I've been trying it out instead of `list-buffers` and `ibuffer` and I like it so far, very fast."}, "hnx4z28": {"author": "TeMPOraL_PL", "upvotes": 16, "body": "## u/TeMPOraL_PL [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnx4z28) \n**Votes:** 16\n\nIf you're like me, and your day ends way past midnight, handling those last few tasks in your Org Mode agenda gets tricky. Fortunately, it turns out Org Mode has what I call \"25th hour mode\".\n\n```elisp\n;; consider the current day to end at 3AM\n(setq org-extend-today-until 3) \n \n;; make timestamp processing functions aware of this\n(setq org-use-effective-time t) \n\n```\nCombined, this allows to extend the day past midnight, with things like agenda views, scheduling commands, repeaters, etc. thinking the current time is 23:59 up until the `org-extend-today-until` limit. With this enabled, if I have a task that has a repeater of and complete it at 01:00, I no longer have to then manually reschedule the task back one day."}, "hnp5rhn": {"author": "el_tuxo", "upvotes": 15, "body": "## u/el_tuxo [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnp5rhn) \n**Votes:** 15\n\nWorking on a remote server with Tramp in eshell it's so easy that I'm always worried that I could run by mistake a command on the wrong machine.\n\nSo I implemented a small function that makes me aware that I'm in a Tramp session by changing the prompt color.\n\n```elisp\n(require 'subr-x) \n(defun tuxo/prompt-color-tramp () \n\"Change prompt color if a tramp session is open\" \n (if (file-remote-p default-directory) \n (set-face-foreground 'eshell-prompt \"red\") \n (set-face-foreground 'eshell-prompt \"green\")))\n \n(use-package eshell\n :hook (eshell-post-command . tuxo/prompt-color-tramp))\n\n```\nDo you have any suggestions on how I could improve this issue?"}, "hnrdt9x": {"author": "blankspruce", "upvotes": 9, "body": "## u/blankspruce [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnrdt9x) \n**Votes:** 9\n\nIs there a package similar to wdired or wgrep that would work on magit diffs? \n\nParticular use cases I have in mind are:\n\n1. You've prepared a commit for pull request and during review someone spotted a mistake that's present in multiple files of that commit. Usually I grep the mistake and edit only affected files with wgrep (there might be some arbitrary reason to not fix similar issue in files not present in the commit).\n2. In C++ it happens sometimes that you want to separate declaration and definition and in your commit you forgot to move some definitions to .cpp.\nUsually I switch to `foobar.hpp`, kill the necessary part, switch to `foobar.cpp`, yank that part."}, "hnvaab8": {"author": "rberaldo", "upvotes": 8, "body": "## u/rberaldo [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/rbmfwk/comment/hnvaab8) \n**Votes:** 8\n\nA tiny thing I just noticed: in `tex-mode`, you can create a new environment with `C-c C-e`. With the universal argument (`C-u C-c C-e`), however, you can easily change any environment into another.\n\nI created an `enumerate` environment and immediately changed my mind. By chance, I intuitively tried the aforementioned command and I was instantly able to change the environment into `itemize`.\n\nEDIT: markdown"}, "hmryv5o": {"author": "rucci99", "upvotes": 14, "body": "## u/rucci99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/r69w7i/comment/hmryv5o) \n**Votes:** 14\n\nI just found out that Magit can backup changes of uncommitted files automatically. Here's the link to online manual:\n[Magit Wip Modes](https://magit.vc/manual/magit/Wip-Modes.html#Wip-Modes)."}, "hmst3ih": {"author": "WorldsEndless", "upvotes": 11, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/r69w7i/comment/hmst3ih) \n**Votes:** 11\n\nmacros in emacs are like a secret, forgotten art, but I use them with regexp search, orgmode commands to tweak repeating events (or any number of other uses). Learn macros; they gave emacs its name! One usage here: https://orys.us/ug"}, "hicheof": {"author": "tryptych", "upvotes": 8, "body": "## u/tryptych [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/qgrpte/comment/hicheof) \n**Votes:** 8\n\nA colleague just showed me Intellij's \"[compare with clipboard](https://www.jetbrains.com/help/idea/comparing-files-and-folders.html#clipboard)\" feature: it's fairly neat, you select a region, invoke compare-with-clipboard and get a diff of the two selections.\n\nIt didn't take me long to implement something similar:\n\n```elisp\n(defun ediff-compare-region-clipboard (begin end)\n (interactive \"r\")\n (save-excursion\n (let ((selected-region (buffer-substring begin end))\n (clipboard-buffer (get-buffer-create \"*ediff-clipboard*\"))\n (region-buffer (get-buffer-create \"*ediff-region*\")))\n (with-current-buffer clipboard-buffer\n (insert (car kill-ring)))\n (with-current-buffer region-buffer\n (insert selected-region))\n (ediff-buffers clipboard-buffer region-buffer))))\n\n```\nIt's not ideal though. In particular, is there a better way to insert the \"clipboard\"? One thing I quickly found was that you might copy the region to compare but then so many editing commands will add to the kill-ring, so I might want to make that part of the process interactive."}, "hi8crmc": {"author": "yogsototh", "upvotes": 10, "body": "## u/yogsototh [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/qgrpte/comment/hi8crmc) \n**Votes:** 10\n\nI just made this nice combination of emacs packages and personal theme to achieve the cool effect of iAWriter\n\nSee here: https://her.esy.fun/posts/0021-ia-writer-clone-within-doom-emacs/index.html"}, "hhinrm4": {"author": "SamTheComputerSlayer", "upvotes": 10, "body": "## u/SamTheComputerSlayer [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/qbvyza/comment/hhinrm4) \n**Votes:** 10\n\nI use a lot of toggles in my config. I used to do it ad-hoc every time, but the pattern ends up the same so I made this macro:\n```elisp\n(defun deftoggle-var-doc (name)\n (concat \"Non-nil if \" name \" is enabled.\\n\\n\"\n \"See \" name\n \" command for a description of this toggle.\"))\n(defun deftoggle-fun-doc (name doc)\n (concat \"Toggle \" name \" on or off.\\n\\n\" doc))\n(defmacro deftoggle (name doc enabler disabler)\n `(progn\n (defvar ,name nil ,(deftoggle-var-doc (symbol-name name)))\n (defun ,name (&optional enable)\n ,(deftoggle-fun-doc (symbol-name name) doc)\n (interactive)\n (if (called-interactively-p 'interactive)\n (progn\n (if ,name\n ,disabler\n ,enabler)\n (setq ,name (not ,name)))\n (progn\n (if enable\n ,enabler\n ,disabler)\n (setq ,name enable))))))\n```\n\nIt's very similar to define-minor-mode, but with all the hooks, keymaps, and lighters stripped out, so it's less verbose. Here I use it to toggle my theme for example:\n```elisp\n(deftoggle sam-toggle-theme\n \"Toggle theme between light and dark.\"\n (progn (disable-theme 'dracula)\n (load-theme 'spacemacs-light t))\n (progn (disable-theme 'spacemacs-light)\n (load-theme 'dracula t)))\n```"}, "hgk3wik": {"author": "Stefan-Kangas", "upvotes": 14, "body": "## u/Stefan-Kangas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/q76kok/comment/hgk3wik) \n**Votes:** 14\n\nThis is pretty neat: scrolling up/down one line at a time while keeping the position of point:\n\n`(setq scroll-preserve-screen-position 1)` \n`(global-set-key (kbd \"M-n\") (kbd \"C-u 1 C-v\"))` \n`(global-set-key (kbd \"M-p\") (kbd \"C-u 1 M-v\"))` \n\n\nFrom: http://pragmaticemacs.com/emacs/scrolling-and-moving-by-line/"}, "hghtyfo": {"author": "???", "upvotes": 10, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/q76kok/comment/hghtyfo) \n**Votes:** 10\n\nbefore you load evil `(setq evil-want-minibuffer t)` to use evil-mode in the minibuffer."}, "hghp1e4": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/q76kok/comment/hghp1e4) \n**Votes:** 9\n\nCheckout [Topsy Mode](https://github.com/alphapapa/topsy.el), it creates a header at the top of your buffer to show the name of the first function outside of your visual range. It makes scrolling through code much easier because you get an additional visual queue of your location in the buffer. It's one of those things that you never knew you wanted. It takes about 15 seconds to setup."}, "hfldw8n": {"author": "github-alphapapa", "upvotes": 10, "body": "## u/github-alphapapa [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/q2g1gq/comment/hfldw8n) \n**Votes:** 10\n\nOne of the most useful bindings for me:\n\n```elisp\n(use-package avy\n :bind* ((\"C-j\" . avy-goto-char-timer)))\n```"}, "hepqmq1": {"author": "Gangsir", "upvotes": 22, "body": "## u/Gangsir [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hepqmq1) \n**Votes:** 22\n\nback-to-indentation. Before I found this function I would always do some awkward triple key combo like C-a M-f M-b.\n\nIt's just bound to M-m. Jumps you right to the first non-white space character on the line. What's even spicier is that it works in reverse too - if you're at the front of the line it jumps you forward, if you're at the end or middle it jumps backward.\n\nIt still works even on lines that aren't indented, same as C-a in that case.\n\nSo useful, especially for resetting point during macros that need to start at the first char on the line."}, "hf1gzs2": {"author": "Stefan-Kangas", "upvotes": 11, "body": "## u/Stefan-Kangas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hf1gzs2) \n**Votes:** 11\n\nRead [SICP](https://mitpress.mit.edu/sites/default/files/sicp/index.html). Preferably in Info, installable through MELPA or: [https://github.com/webframp/sicp-info](https://github.com/webframp/sicp-info)"}, "hexdfiq": {"author": "Stefan-Kangas", "upvotes": 11, "body": "## u/Stefan-Kangas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/pxqvtm/comment/hexdfiq) \n**Votes:** 11\n\nReplace the binding for `count-words-region` with `count-words`. The latter has better semantics: it only shows words in region if the region is active.\n\n`(global-set-key (kbd \"M-=\") #'count-words)`"}, "hcxub77": {"author": "dmartincy", "upvotes": 11, "body": "## u/dmartincy [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/polxft/comment/hcxub77) \n**Votes:** 11\n\nIf you write Lisp, there's a couple of old Emacs commands to help you write code while keeping parenthesis balanced: `M-(` (`insert-parenthesis`), and `M-)` (`move-past-close-and-reindent`). They used to be documented in old Emacs manuals, but presumably their description was removed to make room for other content.\n\nWith a prefix argument, `M-(` wraps in parenthesis that number of sexps. For example with point represented as \"*\":\n\n*foo -> C-u 1 M-( -> (foo)\n\nThere's more information in EmacsWiki: https://www.emacswiki.org/emacs/InsertPair"}, "hbc84y3": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/pg69k8/comment/hbc84y3) \n**Votes:** 8\n\n[deleted]"}, "haddtq6": {"author": "oantolin", "upvotes": 9, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/pb6w2z/comment/haddtq6) \n**Votes:** 9\n\nThis one is probably pretty niche but it was a noticeable improvement in my workflow, so I thought I'd share. I sometimes have to fill out forms I get in PDF but that aren't fillable PDFs, merely scans of paper forms. I guess a reasonable person would install The Gimp or something like that, but I fill them out in LaTeX, using `\\includegraphics` for the PDF form, and the `textpos` package to place text on top of it. \n\nThis is requires giving the coordinates you want the text placed at, which I used to do by trial and error. And as much as I normally dislike the mouse, I had to admit that for specifying a point in an image it is a much better input device than the keyboard. So I decided to write a function that would let me click on a point in a PDF and insert the coordinates in centimeters at point in the current buffer. Writing it was fairly easy and I think really illustrates the power of a system like Emacs, a Lisp Machine or Smalltalk, where you can instantly find the source code implementing any given functionality. I knew that `pdf-tools` must contain some code to translate mouse clicks into PDF document coordinates, because it lets you place annotations by clicking. I have the text annotation function bound to `a t`, and quick `C-h k` later I was reading the source code. And after that writing the following function was pretty easy:\n\n```elisp\n(defun insert-coordinates ()\n \"Insert coordinates (in centimeters) of mouse click.\"\n (interactive)\n (let ((pos (event-start (pdf-util-read-click-event \"Click on PDF\"))))\n (insert\n (with-selected-window (posn-window pos)\n (let ((pt (pdf-util-scale-pixel-to-points (posn-object-x-y pos))))\n (cl-flet ((f (x) (* 2.54 (/ x 72.0))))\n (format \"(%.1fcm,%.1fcm)\" (f (car pt)) (f (cdr pt)))))))))\n```"}, "h9e6uqq": {"author": "github-alphapapa", "upvotes": 16, "body": "## u/github-alphapapa [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/p6mwx2/comment/h9e6uqq) \n**Votes:** 16\n\nHere's a popular Emacs config I just rediscovered. Some cool stuff here. https://github.com/angrybacon/dotemacs"}, "h8utmh2": {"author": "oantolin", "upvotes": 9, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/p28rl5/comment/h8utmh2) \n**Votes:** 9\n\nImenu is pretty adictive and it's disappointing when some major mode doesn't support it. Luckily, it's fairly easy to cook up some regexps to provide imenu support in a new major mode. For example I recently noticed that customize buffers didn't have imenu support add I wrote this:\n\n```elisp\n(defun configure-imenu-Custom ()\n (setq imenu-generic-expression\n '((\"Faces\" \"^\\\\(?:Show\\\\|Hide\\\\) \\\\(.*\\\\) face: \\\\[sample\\\\]\" 1)\n (\"Variables\" \"^\\\\(?:Show Value\\\\|Hide\\\\) \\\\([^:\\n]*\\\\)\" 1))))\n\n(add-hook 'Custom-mode-hook #'configure-imenu-Custom)\n\n```\nOne subtlety with writing this is that the customize buffers show little triangles instead of the words \"Show\", \"Hide\" or \"Show Value\". To figure out what text is really in the buffer you can use `C-u C-x =` which tells you about any overlays at point."}, "h8iin6r": {"author": "Bodertz", "upvotes": 9, "body": "## u/Bodertz [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/p28rl5/comment/h8iin6r) \n**Votes:** 9\n\nMeta:\n\nApparently, the `&c.` in the title is an abbreviation of the abbreviation `etc.`, which is fine except that the sidebar's link to past threads of this kind is in fact a link to a reddit search which includes as a search term `etc.` but not `&c.`, so this thread will not show up."}, "h85cv7f": {"author": "b3n", "upvotes": 8, "body": "## u/b3n [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/oxo1xh/comment/h85cv7f) \n**Votes:** 8\n\nLittle quality of life improvement if you work with multiple eshell buffers:\n\n```elisp\n(defun eshell-buffer-name ()\n (rename-buffer (concat \"*eshell*<\" (eshell/pwd) \">\") t))\n \n(add-hook 'eshell-directory-change-hook #'eshell-buffer-name)\n(add-hook 'eshell-prompt-load-hook #'eshell-buffer-name)\n```"}, "h88ph29": {"author": "oantolin", "upvotes": 8, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/oxo1xh/comment/h88ph29) \n**Votes:** 8\n\nThis isn't a tip or trick, so I guess it is covered by &c. The Init File section of the manual has this example of setting a user email address:\n\n```elisp\n(setq user-mail-address \"cheney@torture.gov\")\n```"}, "h67qge6": {"author": "globalcandyamnesia", "upvotes": 15, "body": "## u/globalcandyamnesia [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ooldn6/comment/h67qge6) \n**Votes:** 15\n\nI'm trying to feminize my voice and org mode has been invaluable.\n\n```elisp\n(org-babel-do-load-languages 'org-babel-load-lanuages\n '((shell . t)))\n \n(setq org-capture-templates\n `((\"v\" \"Voice\" entry\n (file+olp+datetree ,(concat my-org-directory \"voice/training.org\"))\n ,(concat\n \"* Record \\n\"\n \"\\n\"\n \" #+begin_src sh\\n\"\n \" rec %(format-time-string \\\"%Y-%m-%d-%H.%M.%S\\\").aiff\\n\"\n \" #+end\\_src\\n\"\n \"\\n\"\n \"* Play\\n\"\n \" #+begin_src sh\\n\"\n \" play %(format-time-string \\\"%Y-%m-%d-%H.%M.%S\\\").aiff\\n\"\n \" #+end_src\\n\")\n :immediate-finish t\n :jump-to-captured t)))\n\n```\nThis requires 'SoX' for linux. You can go into the record src block and press \\`C-c C-c\\` to start recording and \\`C-g\\` to end. To play back the recording, press \\`C-c C-c\\` within the play src block. I imagine this might be useful beyond the trans community for basic voice journaling."}, "h5584no": {"author": "vatai", "upvotes": 11, "body": "## u/vatai [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ojzv53/comment/h5584no) \n**Votes:** 11\n\nThe emacs lisp tutorial is the real tutorial for emacs ;)"}, "h55vkl6": {"author": "PriorOutcome", "upvotes": 10, "body": "## u/PriorOutcome [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ojzv53/comment/h55vkl6) \n**Votes:** 10\n\nI often find myself wanting to be able to switch between `master` and a feature branch in magit quickly:\n\n```elisp\n(defun lw-magit-checkout-last (&optional start-point)\n (interactive)\n (magit-branch-checkout \"-\" start-point))\n(transient-append-suffix 'magit-branch \"w\"\n '(\"-\" \"last branch\" lw-magit-checkout-last))\n\n```\nSo that `C-x g b -` switches to the last branch I was on, similar to `cd -`."}, "h4dxjbz": {"author": "oantolin", "upvotes": 13, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ofen99/comment/h4dxjbz) \n**Votes:** 13\n\nIf you want to search and replace but with preview for the matches, don't use `query-replace-regexp` directly. Instead start by searching for your regexp in `isearch-forward-regexp`, which highlights the matches interactively, and once you have the correct regexp, run `isearch-query-replace` (bound to `M-%` in `isearch-mode-map`).\n\nNote that there is also an `isearch-query-replace-regexp` command but you don't need it: `isearch-query-replace` will automatically detect if your isearch session was for regexps. The docstring for `isearch-query-replace` doesn't seem to mention this nice feature."}, "h2rizey": {"author": "oantolin", "upvotes": 18, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h2rizey) \n**Votes:** 18\n\nI have two org mode link tips:\n\n1. `(setq org-return-follows-link t)` lets you press RET to follow a\n link. Don't worry, the traditional behavior of RET, namely inserting\n a newline, is still easy: `C-q C-j`.\n\n2. I often want to see what the destination of a link is. I used to\n use one of these methods:\n \n - mouse hover,\n - running and canceling `org-insert-link` (`C-c C-l`, read the\n```elisp\n destination, `C-g`),\n```\n - `org-toggle-link-display`, which toggles between the neat formatting of \n```elisp\n links and the raw source and is pretty ugly.\n \n```\n But a better option is to use `display-local-help` (`C-h .`), which\n will show the tooltip in the echo area. And, you can even have the\n tooltip at point echoed automatically with `(setq\n help-at-pt-display-when-idle t)`. There is a delay controlled by\n the variable `help-at-pt-timer-delay` which I like to set to 0.\n Beware that just using `(setq help-at-pt-timer-delay 0)` has no effect,\n you need to use `customize-set-variable` or manually cancel the\n timer and set a new one (see below).\n \n Now, these `help-at-pt` variables aren't specifically for org\n links, they control the behavior of all tooltips, and I quickly\n realized I really only wanted to change the behavior in org mode\n buffers. You can do that as follows:\n \n```elisp\n (defun echo-area-tooltips ()\n \"Show tooltips in the echo area automatically for current buffer.\"\n (setq-local help-at-pt-display-when-idle t\n help-at-pt-timer-delay 0)\n (help-at-pt-cancel-timer)\n (help-at-pt-set-timer))\n\n (add-hook 'org-mode-hook #'echo-area-tooltips)\n```"}, "h2rdkkz": {"author": "TheDrownedKraken", "upvotes": 34, "body": "## u/TheDrownedKraken [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h2rdkkz) \n**Votes:** 34\n\nDo you think it might be good to make this a little less frequently refreshed? There are usually some great tips that get lost to Reddit\u2019s ephemerality pretty quickly.\n\nI think monthly would be better, given the modest size of this subreddit."}, "h31xz50": {"author": "globalcandyamnesia", "upvotes": 9, "body": "## u/globalcandyamnesia [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/o68i0v/comment/h31xz50) \n**Votes:** 9\n\nIf you're using the mark setting commands to expand a selection like `M-@` (mark next word) or `C-M-@` (mark next sexp), you can swap the point and mark (`C-x C-x`) and the selection will be expanded to the left rather than the right.\n\nSo if you're in the middle of a sentence, you can press `M-@` a few times to select some words to the right, press `C-xx`, and press `M-@` a few more times to add words before the selection."}, "h1znz1s": {"author": "sauntcartas", "upvotes": 10, "body": "## u/sauntcartas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/o0zvb5/comment/h1znz1s) \n**Votes:** 10\n\nI keep forgetting how useful the `pcase` macro is. Recently I wrote a command that expected to find a single jar file in a certain directory and operate on it. I started with a more \"traditional\" implementation:\n\n```elisp\n(let ((jars (directory-files some-dir t (rx \".jar\" eos))))\n (if (= 1 (length jars))\n (do-something-with (car jars))\n (error \"Didn't find exactly one jar file\")))\n\n```\nThen I remembered `pcase`:\n\n```elisp\n(pcase (directory-files some-dir t (rx \".jar\" eos))\n (`(,jar) (do-something-with jar))\n (_ (error \"Didn't find exactly one jar file\")))\n\n```\nMuch more readable!"}, "gxpeh9v": {"author": "Tatrics", "upvotes": 15, "body": "## u/Tatrics [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/n9q662/comment/gxpeh9v) \n**Votes:** 15\n\nI'm slowly working on an alternative shell: [https://github.com/TatriX/tshell](https://github.com/TatriX/tshell)\n\nInstead of using repl-like interface, all the commands go to one buffer (and file if you want) and output goes to another buffer. Like if you put your elisp code in \\*scratch\\* buffer and then evaluate it with \\`C-x C-e\\`.\n\nIt's in a very early stage, but it already allows me to solve most tasks I usually do with more traditional shells.\n\nLet me know what is your first impression, what can be improved and what do you think in general!"}, "gxx6frj": {"author": "PotentiallyAlice", "upvotes": 10, "body": "## u/PotentiallyAlice [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/n9q662/comment/gxx6frj) \n**Votes:** 10\n\nI thought it might be a fun project to make a package to expose org-capture templates as endpoints, so I can add reminders to my TODO list via any device on the network. Turns out, it was easy enough that a package would be kinda pointless:\n\n```elisp\n(defservlet* capture/:keys/:contents text/plain () (org-capture-string contents keys))\n\n```\nNow I can hit \"localhost:8080/capture/t/test reminder\" and it'll put a \"* TODO test reminder\" line into my todo.org. Neat!"}, "gv8jxz5": {"author": "???", "upvotes": 15, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mujxm7/comment/gv8jxz5) \n**Votes:** 15\n\nI use, and love, [transient](https://github.com/magit/transient). I have a ton of commands set up, but the below command is for window manipulation. Personally, I bind it to `s-w`. I use [buffer-move](https://github.com/lukhas/buffer-move) for rearranging windows in a frame.\n\n```elisp\n(define-transient-command transient-window ()\n \"Most commonly used window commands\"\n [[\"Splits\"\n (\"s\" \"Horizontal\" split-window-below)\n (\"v\" \"Vertical\" split-window-right)\n (\"b\" \"Balance\" balance-windows)\n (\"f\" \"Fit\" fit-window-to-buffer)\n [\"Window\"\n (\"c\" \"Clone Indirect\" clone-indirect-buffer)\n (\"t\" \"Tear Off\" tear-off-window)\n (\"k\" \"Kill\" delete-window)\n (\"K\" \"Kill Buffer+Win\" kill-buffer-and-window)\n (\"o\" \"Kill Others\" delete-other-windows)\n (\"m\" \"Maximize\" maximize-window)]\n [\"Navigate\"\n (\"\" \"\u2190\" windmove-left :transient t)\n (\"\" \"\u2192\" windmove-right :transient t)\n (\"\" \"\u2191\" windmove-up :transient t)\n (\"\" \"\u2193\" windmove-down :transient t)]\n [\"Move\"\n (\"S-\" \"S-\u2190\" buf-move-left :transient t)\n (\"S-\" \"S-\u2192\" buf-move-right :transient t)\n (\"S-\" \"S-\u2191\" buf-move-up :transient t)\n (\"S-\" \"S-\u2193\" buf-move-down :transient t)]\n [\"Undo/Redo\"\n (\"s-z\" \"Winner Undo\" winner-undo :transient t)\n (\"s-Z\" \"Winner Redo\" winner-redo :transient t)]])\n```"}, "gufsfeu": {"author": "11fdriver", "upvotes": 9, "body": "## u/11fdriver [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mpwapo/comment/gufsfeu) \n**Votes:** 9\n\nSometimes I'm working on programs with functions a few pages long, and `follow-mode` means that I can open two windows of the same buffer side-by-side and have the text flow like a book between them. I can double or even triple the amount of lines I can view at one time.\n\nThis has largely superseded what I might have used those code-overview map things for, which is difficult anyway, since I like to use Emacs from the terminal.\n\nIt will keep the text aligned as you move through the file, and pairs well with binding `` and `` to the `scroll-up/down-line` commands in `xterm-mouse-mode`.\n\nIf I'm studying/notetaking, I often end up with a few Emacs-windows arranged in a vertical stack. `winner-mode` or `window-configuration-to-register` are great, but if I want to quickly regain some vertical screen-real-estate without messing up the layout, then it's pretty intuitive to use `follow-mode` and just switch multiple windows to the same buffer, now they behave like one."}, "gudoljm": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mpwapo/comment/gudoljm) \n**Votes:** 9\n\n**Create Rectangular Selection with Meta+Click+Drag**\n\nBy default, when you click and drag with the Meta key Emacs creates what it calls a \"secondary selection\" which is super interesting and useful, but not what this tip is about. In most editors (on the Mac anyway) option+click+drag is used to create a rectangular selection. Emacs, of course, supports this, you just need to remap it.\n\n```elisp\n(global-set-key [M-down-mouse-1] #'mouse-drag-region-rectangle)\n(global-set-key [M-drag-mouse-1] #'ignore)\n(global-set-key [M-mouse-1] #'mouse-set-point)\n\n```\nYou can also create a rectangular selection with the command `rectangle-mark-mode`.\n\nDon't forget to bind `replace-rectangle` to something convenient for super easy editing."}, "gtkc524": {"author": "b3n", "upvotes": 10, "body": "## u/b3n [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ml4wql/comment/gtkc524) \n**Votes:** 10\n\nSkeletons are one of Emacs' killer features, especially when combined with `abbrev-mode`. Here's a macro I wrote to make them a little easier to handle:\n\n```elisp\n(defmacro snip (name &rest skeleton)\n (let* ((snip-name (symbol-name `,name))\n (func-name (intern (concat \"snip-\" snip-name))))\n `(progn\n (define-skeleton ,func-name\n ,(concat snip-name \" skeleton\")\n ,@skeleton)\n (define-abbrev global-abbrev-table ,snip-name\n \"\" ',func-name))))\n\n```\nHere's a simplistic example using the macro:\n\n```elisp\n(snip dd \"\" (format-time-string \"%Y-%m-%d\"))\n\n```\nNow (assuming you have `abbrev-mode` enabled), type `dd ` into your buffer (that's `d` `d` `SPC`) and it'll be replaced with the current date.\n\nThis is just scratching the surface, skeletons are extremely powerful. Once you start using them they become a superpower and can take your Emacs usage to the next level."}, "gstteeo": {"author": "???", "upvotes": 12, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mg98ki/comment/gstteeo) \n**Votes:** 12\n\nI just discovered the [selected](https://github.com/Kungsgeten/selected.el) package, which is brilliant. It creates a keymap that becomes active any time you have an active region. I have bindings for next-line, previous-line, rectangle-mark-mode, end-of-line, upcase-dwim, exchange-point-and-mark, etc. It makes editing and acting on the active region super easy. Sort of like god-mode or Vim's visual mode."}, "gsvlfku": {"author": "a-k-n", "upvotes": 9, "body": "## u/a-k-n [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mg98ki/comment/gsvlfku) \n**Votes:** 9\n\nI just discovered that installing the Emacs macport homebrew formula with \\`--with-mac-metal\\` will significantly increase the performance of Emacs. It's buttery smooth!"}, "gry6bfs": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/mb8u1m/comment/gry6bfs) \n**Votes:** 9\n\nIf you want helpful mode to completely take over all help functions, and be able to use it with helm-apropos, then add this to your config:\n\n```elisp\n(advice-add 'describe-function :override #'helpful-function)\n(advice-add 'describe-variable :override #'helpful-variable)\n(advice-add 'describe-command :override #'helpful-callable)\n(advice-add 'describe-key :override #'helpful-key)\n(advice-add 'describe-symbol :override #'helpful-symbol)\n```"}, "gpeb8n3": {"author": "b3n", "upvotes": 12, "body": "## u/b3n [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/lvw44q/comment/gpeb8n3) \n**Votes:** 12\n\nHere's a nice eshell command:\n\n```elisp\n(defun eshell/history ()\n (interactive)\n (insert\n (completing-read \"History: \" (delete-dups (ring-elements eshell-history-ring)))))\n\n```\nIt lets you use your normal completion framework to select an item from history. Suddenly fzf-like history!"}, "gmtk79e": {"author": "Bodertz", "upvotes": 11, "body": "## u/Bodertz [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/lfww57/comment/gmtk79e) \n**Votes:** 11\n\nFrom the mailing list, I've just learned of `generic-x.el`, which provides syntax highlighting for `/etc/fstab` or `/etc/passwd` and the like. I appreciated that vim provided that out of the box and I was surprised that emacs also does, but it's just disabled.\n\n`(require 'generic-x)` to enable it."}, "glr8pkr": {"author": "WorldsEndless", "upvotes": 14, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/lapujj/comment/glr8pkr) \n**Votes:** 14\n\nYou can use EWW to bypass pay-walls on news sites, and other Javascript-enabled nastiness. Plus, eww can copy from what it sees into equivalent orgmode syntax, and it's also compatible with SPRAY for speed-reading. In otherwords, EWW is great for when you just need to READ the internet."}, "gknr3hp": {"author": "w0ntfix", "upvotes": 8, "body": "## u/w0ntfix [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/l0ei0t/comment/gknr3hp) \n**Votes:** 8\n\nmy first package is now on melpa! https://melpa.org/#/ct"}, "gj1kn9i": {"author": "emacs-noob", "upvotes": 13, "body": "## u/emacs-noob [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj1kn9i) \n**Votes:** 13\n\nI use Emacs for React development and it's usually great (rjsx-mode). We recently introduced styled components into our app and while they're very handy, not having proper css support inside rjsx-mode was pretty annoying. I was looking for solutions, maybe extending rjsx-mode, but I wasn't up to that task. I then realized the built-in emacs commands and buffers themselves could solve my problem! What I want is for css inside a styled component, which always looks something like this:\n\n```elisp\nconst myDiv = styled.div` // notice the backtick\n Some css...\n ` // ending backtick\n\n```\nto *actually* use scss-mode when editing, and then return to rjsx-mode when finished. The elisp is very simple and leads to a trivial workflow:\n\n```elisp\n;; The following 2 functions allow editing styled components with all scss mode features.\n(defun edit-styled-component ()\n (interactive)\n (progn\n (save-excursion\n (let ((start (search-backward \"`\"))\n (end (search-forward \"`\" nil nil 2))) ; second occurrence, since first is `start'\n (narrow-to-region start end)))\n (scss-mode)))\n\n(spacemacs/set-leader-keys-for-major-mode 'rjsx-mode\n \"ms\" 'edit-styled-component)\n\n;; When editing is done, use the same key sequence to return to the original file.\n(defun return-from-styled-component ()\n (interactive)\n (progn\n (widen)\n (rjsx-mode)))\n\n(spacemacs/set-leader-keys-for-major-mode 'scss-mode\n \"ms\" 'return-from-styled-component)\n\n\n```\nSo now when I edit a styled component I just hit **, m s**, which narrows the region to whatever is enclosed by backticks (i.e. all the css) and actually treats it as a bona fide css buffer, with all my snippets, completion, etc. Then when I'm done I just got **, m s** again to widen back to the original (rjsx) buffer!"}, "gj33uht": {"author": "jumpUpHigh", "upvotes": 10, "body": "## u/jumpUpHigh [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj33uht) \n**Votes:** 10\n\nAucTeX\n\nWhen you compile your TeX file and there are errors, the message asks you to see error messages using\n\n```elisp\n C-c `\n\n```\nThis leads to the last error which is sometimes incomprehensible and you are left to yourself to figure out what went wrong.\n\nInstead of getting the last error, you can get an overview of all the errors by setting below variable to `t`:\n\n```elisp\n (setq TeX-error-overview-open-after-TeX-run t)\n\n```\nYou can pop this up in a separate frame using:\n\n```elisp\n (setq TeX-error-overview-setup 'separate-frame)\n\n```\nRelated docs are [here](https://www.gnu.org/software/auctex/manual/auctex/Error-overview.html).\n\nThis totally changes the way you can handle errors messages."}, "gj9ioly": {"author": "WorldsEndless", "upvotes": 9, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/kvmmq3/comment/gj9ioly) \n**Votes:** 9\n\nJust a cool concept: if you have a keypad on your keyboard which you rarely use, bind its nums to something useful. The results are numlock-sensitive and are NOT the same keycodes as regular numbers, so they're just free keys. For example, `(define-key map (kbd \"\") 'winum-select-window-1)`"}, "gi66krb": {"author": "geza42", "upvotes": 9, "body": "## u/geza42 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/kqsw1k/comment/gi66krb) \n**Votes:** 9\n\nI created a \"smart\" enter function for C/C++ mode. Here's what it does:\n\n* if you press it on a `for`/`if`/`else`/`switch` (no matter where the cursor is on the line) it will put `{`, an empty line and `}`, and will move the cursor into the body\n* if you press it on a `struct`/`class`, it's similar to the previous case, but it puts a closing semicolon too.\n* otherwise it will put a `;`, and a newline\n* if the `{`, `;` or an empty line is already there, it won't put them again\n* In comments, it will put an indented line, without continuing the comment (I configured my RET to continue commenting, so I use M-RET when I want to close the comment)\n\nIt is useful with smartparens, because you don't have to skip the closing `)` all the time. For example, if you start writing an `if` (cursor is `|`, the closing `)` was put by smartparens):\n\n```elisp\nif (expr|)\n\n```\nThen press M-RET, this will be the result:\n\n```elisp\nif (expr) {\n |\n}\n\n```\nSince I created this function I use it all the time, I almost never press `{` `}` or `;`.\n\nAt function signatures, it cannot figure out whether you want to create a declaration (closed by `;`) or definition (closed by `{ }`), so it puts a `;`. And the function has a parameter (`force-curly`) with which you can force putting a`{` (I mapped this to M-S-return).\n\nHere's the code, maybe there can be a lot of improvements:\n\n```elisp\n(defun my-cc-mode-M-RET-context (force-curly)\n (let ((c\n (if force-curly 'curly\n (let ((s (syntax-ppss)))\n (cond\n ((nth 4 s) 'comment)\n ((and (eolp) (looking-back \"[{;]\")) 'nop)\n ((save-excursion\n (skip-syntax-forward \" \")\n (looking-at \"\\\\(for\\\\|if\\\\|switch\\\\|else\\\\|do\\\\)\\s?\")) 'curly)\n ((save-excursion\n (skip-syntax-backward \" \")\n (skip-syntax-backward \"w\")\n (looking-at \"\\\\(for\\\\|if\\\\|switch\\\\|else\\\\|do\\\\)\\s?\")) 'curly)\n ((save-excursion\n (when (nth 3 s) (skip-syntax-backward \"^\\\"\") (backward-char))\n (skip-syntax-backward \" \")\n (if (looking-back \")\")\n (backward-sexp)\n (ignore-errors (backward-up-list)))\n (skip-syntax-backward \"(\")\n (skip-syntax-backward \" \")\n (looking-back \"for\\\\|if\\\\|switch\")) 'curly)\n ((save-excursion\n (skip-syntax-forward \" \")\n (looking-at \"struct\\\\|class\")) 'curly+semicolon)\n ((save-excursion\n (skip-syntax-backward \" \")\n (skip-syntax-backward \"w\")\n (if (looking-at \"struct\\\\|class\") t\n (skip-syntax-backward \"w\")\n (skip-syntax-backward \" \")\n (looking-back \"struct\\\\|class\"))) 'curly+semicolon)\n (t 'semicolon))))))\n (cond\n ((or (eq c 'curly) (eq c 'curly+semicolon))\n (save-excursion\n (end-of-line)\n (if (looking-back \"{\")\n 'nop\n c)))\n ((eq c 'semicolon)\n (save-excursion\n (end-of-line)\n (if (looking-back \";\")\n 'nop\n c)))\n (t c))))\n \n(defun my-cc-mode-M-RET (force-curly)\n (let ((c (my-cc-mode-M-RET-context force-curly)))\n (cond\n ((eq c 'nop)\n (if (save-excursion\n (forward-line)\n (beginning-of-line)\n (looking-at-p \"[[:space:]]*$\"))\n (progn\n (forward-line)\n (c-indent-line))\n (end-of-line) (newline-and-indent)))\n ((eq c 'comment) (newline-and-indent))\n ((eq c 'semicolon)\n (end-of-line)\n (self-insert-command 1 ?\\;)\n (newline-and-indent))\n ((eq c 'curly)\n (save-excursion (end-of-line) (unless (looking-back \"\\s\") (insert \" \")) (insert \"{\") (newline-and-indent) (insert \"}\") (c-indent-line))\n (end-of-line)\n (newline-and-indent))\n ((eq c 'curly+semicolon)\n (save-excursion (end-of-line) (unless (looking-back \"\\s\") (insert \" \")) (insert \"{\") (newline-and-indent) (insert \"};\") (c-indent-line))\n (end-of-line)\n (newline-and-indent)))))\n \n(define-key c-mode-base-map (kbd \"M-RET\") (lambda () (interactive) (my-cc-mode-M-RET nil)))\n(define-key c-mode-base-map (kbd \"\") (lambda () (interactive) (my-cc-mode-M-RET t)))\n```"}, "ggoehoo": {"author": "zackallison", "upvotes": 8, "body": "## u/zackallison [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ki09cm/comment/ggoehoo) \n**Votes:** 8\n\nI posted this in the emacsclient thread, but I think it deserves to live here as well:\n\n\nThe emacsclient / server system is great. If you have it listening on tcp and port forward that when connecting to remote machine it adds another level of power.\n\nI use [emacs-vterm](https://github.com/akermu/emacs-libvterm) for a terminal inside emacs, so I've got a lot of commands remapped. Like `man` runs `emacsclient ... man ..`, which opens the man page in the \"other\" buffer, so it doesn't interrupt my flow. I use \"scroll-other-window\" to navigate the man page while I still have my prompt. `magit`, `dired`, and others map to their `emacsclient` equivalents.\n\nI've written wrapper script for e/emacs client that I've come to call `e`, because it saves keystrokes\n\n#### [The full repo is here e-emacs.sh](https://gitlab.com/zackallison/e-emacs/)\n\nIt does the standard things you would expect, starts emacs if it's not already started, open a file in a new buffer / window / terminal and optionally wait for you to finish or have the shell continue.\n\nThen I added some functions that I found useful, starting with piping results from a command into an emacs buffer, such as `find . -name foo\\* | e`. Naturally after that was piping from a buffer to a command: `e [file] | rot13` super secure encryption. And of course piping into and out of a buffer works as well `find . -name incriminating-evidence\\* | e | xargs rm`, so you can verify / tweak the results before passing them through. Maybe you want to leave the evidence on Two Time Tommy. Who knows.\n\nThe other nice feature is the ability to use templates. For example to edit a HTTP request and then send it to a server you can do that: `e -t header_template.txt | nc www.example.com 80` The template file is copied to a temp file which is the one that is edited.\n\nOr the poor man's blog system: `e -t header_template.html body_template.html footer.html > new_page.html`\n\nSee the repo for more examples and to download. The notes of getting it working on remote machines aren't the cleanest. If you have any suggestions or features that would make your life easier let me know; submit an issue or comment here.\n\n#### [The full repo is here e-emacs.sh](https://gitlab.com/zackallison/e-emacs/)\n\n~~I really should post this on one of the share your stuff posts. But I get distracted.~~ There, I did it.\n\nIn case you can't tell I *really* like emacs and it's client server model."}, "gfwlm9q": {"author": "martinslot", "upvotes": 8, "body": "## u/martinslot [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/kdgv43/comment/gfwlm9q) \n**Votes:** 8\n\nI need to try to do something custom to eshell so it feels more like home: http://www.modernemacs.com/post/custom-eshell/. Also set som aliases up.\n\nHow does your eshell look like?"}, "gf1msbr": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/k8zjx5/comment/gf1msbr) \n**Votes:** 8\n\n[deleted]"}, "ge9det9": {"author": "gopar", "upvotes": 16, "body": "## u/gopar [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/k4gv0x/comment/ge9det9) \n**Votes:** 16\n\nA very simple thing I've done is remap \";\" (semicolon) to to \"\\_\" (underscore) in almost all modes. Since I work with mainly Python, this is so much easier than always doing SHIFT-DASH every couple of keystrokes. And if I want a regular semicolon, I just do \"C-u ;\" and insert a semicolon\n\nI also set this in modes such as C/C++, etc. This works by automatically setting the last character (if it was an underscore) to a semicolon on enter. \n\neg. \"|\" is cursor\n\nint a = 10\\*10\\_|\n\nturns into\n\nint a = 10\\*10;\n\n| (cursor on new line)\n\n​\n\nPretty simple time saver \\\\o/"}, "ge8si78": {"author": "ji99", "upvotes": 8, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/k4gv0x/comment/ge8si78) \n**Votes:** 8\n\nHere's all I need for completions:\n\n```elisp\n(use-package icomplete\n :bind\n (:map icomplete-minibuffer-map\n ([C-return] . exit-minibuffer)\n ([return] . minibuffer-try-complete-and-exit))\n :config\n (defun minibuffer-try-complete-and-exit ()\n (interactive)\n (minibuffer-force-complete)\n (setq-local deactivate-mark nil)\n (throw 'exit nil))\n :hook (after-init . icomplete-mode))\n \n(use-package orderless\n :ensure t\n :custom\n (completion-styles '(orderless))\n (orderless-matching-styles 'orderless-literal))\n```"}, "gazzdyz": {"author": "TheDrownedKraken", "upvotes": 15, "body": "## u/TheDrownedKraken [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/jn6m14/comment/gazzdyz) \n**Votes:** 15\n\nIt would be good to archive the questions and tips put in here. I feel like I always find cool stuff in here, but then it becomes very hard to find it later."}, "gb502ps": {"author": "andrmuel", "upvotes": 8, "body": "## u/andrmuel [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/jn6m14/comment/gb502ps) \n**Votes:** 8\n\nThis is something I'm not actively using anymore, but it was one of my I-love-emacs moments, so I wanted to share this for a while.\n\nAt work, I used to have an org-mode journal where I would take meeting notes. After the meeting, I exported the subtree for the current meeting to a PDF (via ODT) and sent it to the participants via mail.\n\nAfter a while I extended org-export to get a shortcut (`C-e C-s o M`) to automatically\n\n* export to PDF via ODT\n * using a proper corporate design & logo via ODT\\_STYLES\\_FILE header\n* rename the file to include the current date\n* open thunderbird, starting a new message with\n * subject taken from document title (if exporting all) or subtree heading (if exporting subtree\n * pre-filled text\n * the exported PDF already attached\n\n​\n\n```elisp\n;;\n;; export and send to mail\n;;\n(defun org-foo-export-to-foo-and-sendto-mail (org-export-function &optional async subtreep visible-only ext-plist)\n (interactive)\n (when (or (string-equal (file-name-extension (buffer-file-name)) \"gpg\")\n (string-equal (file-name-extension (buffer-file-name)) \"asc\"))\n (unless (yes-or-no-p \"Really export GPG encrypted file and send via mail? \")\n (throw 'abort-export-mail-gpg \"export aborted by user\")))\n (unless subtreep\n (unless (yes-or-no-p \"Really export everything and send via mail? \")\n (throw 'abort-export-mail-everything \"export aborted by user\")))\n (let* ((title (if subtreep\n ;; subtree -> use subtree heading as title\n (nth 4 (org-heading-components))\n ;; whole document -> use document title\n (org-element-map\n (org-element-parse-buffer)\n 'keyword\n (lambda (e)\n (when (string= \"TITLE\" (org-element-property :key e))\n (org-element-property :value e)))\n nil\n t)))\n (file (file-name-nondirectory (funcall org-export-function async subtreep visible-only ext-plist))) ; note: odt export includes directory in output file name, html export includes no directory\n (newfile (format \"%s_%s\" (format-time-string \"%Y%m%d\") file))\n (directory (file-name-directory (buffer-file-name))))\n (rename-file (concat directory file) (concat directory newfile) 1)\n (my/thunderbird-compose-mail\n \"\"\n (format \"Notes: %s\" title)\n \"Please find attached my notes ...\\n\\nBest regards, Andreas\"\n (format \"file://%s%s\"\n directory newfile))))\n \n(defun org-odt-export-to-odt-and-sendto-mail (&optional async subtreep visible-only ext-plist)\n (interactive)\n (org-foo-export-to-foo-and-sendto-mail 'org-odt-export-to-odt async subtreep visible-only ext-plist))\n \n(defun org-odt-export-to-pdf-and-sendto-mail (&optional async subtreep visible-only ext-plist)\n (interactive)\n (let ((org-odt-preferred-output-format \"pdf\"))\n (org-odt-export-to-odt-and-sendto-mail async subtreep visible-only ext-plist)))\n \n(defun org-html-export-to-html-and-sendto-mail (&optional async subtreep visible-only ext-plist)\n (interactive)\n (org-foo-export-to-foo-and-sendto-mail 'org-html-export-to-html async subtreep visible-only ext-plist))\n \n(eval-after-load 'org\n '(progn\n (org-export-define-derived-backend 'odt-mail 'odt\n :menu-entry\n '(?o \"Export to ODT\"\n ((?m \"As ODT file and send mail\" org-odt-export-to-odt-and-sendto-mail)\n (?M \"As PDF file and send mail\" org-odt-export-to-pdf-and-sendto-mail))))\n \n (org-export-define-derived-backend 'html-mail 'html\n :menu-entry\n '(?h \"Export to HTML\"\n ((?m \"As HTML file and send mail\" org-html-export-to-html-and-sendto-mail))))))\n \n(defun my/thunderbird-compose-mail (&optional recipient subject body attachment)\n (interactive)\n (call-process \"thunderbird\" nil 0 nil \"-compose\" (format \"to='%s',subject='%s',body='%s',attachment='%s'\" recipient subject body attachment)))\n```"}, "g8pgyy1": {"author": "Krautoni", "upvotes": 10, "body": "## u/Krautoni [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ja97xs/comment/g8pgyy1) \n**Votes:** 10\n\nSince I find myself pair programming quite a bit, I made a small helper:\n\n```elisp\n(defvar pair-programming--pair-programmer\n nil\n \"The current pair programmer as (name email)\")\n\n(defun enable-pair-programming-mode ()\n \"Sets visuals for pair programming mode and prompt for your buddy.\"\n (global-display-line-numbers-mode 1)\n (let ((pair-programmer (git-commit-read-ident nil)))\n(setq pair-programming--pair-programmer pair-programmer)\n(message (concat \"Pair programming with \" (car pair-programmer)))))\n\n(defun disable-pair-programming-mode ()\n \"Disable pair programming visuals and settings.\"\n (setq pair-programming--pair-programmer nil)\n (global-display-line-numbers-mode -1)\n (message \"PP mode disabled\"))\n\n(define-minor-mode pair-programming-mode ()\n \"Toggle Pair Programming Mode.\n\nThis prompts for a pair programmer from your current git commit history.\nWhen you commit with (ma)git, the pair programmer is inserted as a co-author.\nAdditionally, line number mode is enabled.\"\n :global t\n :lighter \" PP\"\n (if pair-programming-mode\n (enable-pair-programming-mode)\n(disable-pair-programming-mode)))\n\n(defun insert-pair-programmer-as-coauthor ()\n \"Insert your pair programer into the current git commit.\"\n (when (and pair-programming-mode git-commit-mode)\n(pcase pair-programming--pair-programmer\n (`(,name ,email) (git-commit-insert-header \"Co-authed-by\" name email))\n (_ (error \"No pair programmer found or wrong content\")))))\n\n(add-hook 'git-commit-setup-hook 'insert-pair-programmer-as-coauthor)\n```\n\nIt sets up a co-authored-by for git commits, and enables line numbers."}, "g8op875": {"author": "adt7799", "upvotes": 9, "body": "## u/adt7799 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ja97xs/comment/g8op875) \n**Votes:** 9\n\nI find this very useful.\n\nWhen I have multiple buffers opened and I switch from another program to emacs I always get confused about which buffer the cursor is in. So I created a mapping to\n\n`(global-set-key (kbd \"M-l\") 'beacon-blink)`"}, "g7wd5gj": {"author": "Amonwilde", "upvotes": 9, "body": "## u/Amonwilde [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/j61aoh/comment/g7wd5gj) \n**Votes:** 9\n\nFor some this will be obvious, but I'm sure there will be at least one person who will find this useful. One of the most amazing features of Emacs to me is dabbrev-expand, by default bound to M-/. \n\n> Expand previous word \"dynamically\".\n\n> Expands to the most recent, preceding word for which this is a prefix.\nI> ifno suitable preceding word is found, words following point are\nconsidered. If still no suitable word is found, then look in the\n> buffers accepted by the function pointed out by variable\n\nThis command is essentially omni-autocomplete. Chances are, the term you're trying to complete is in the buffer you're using or another buffer, and you can hit multiple times to cycle through different completions. I find the expander to be quicker and more deterministic than language autocomplete about 70% of the time. It's especially useful in writing, if you use Emacs for things other than programming, as you can complete proper names and specalized vocabulary quickly."}, "g69no38": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ixjcau/comment/g69no38) \n**Votes:** 9\n\norg-variable-pitch.el users might want to give [`valign`](https://github.com/casouri/valign) a look. It aligns your tables nicely, even with pictures (e.g. LaTeX previews) and links. The significance in context of OVP specifically is that you don't need to add `org-link` to `org-variable-pitch-fixed-faces` because valign-mode handles variable pitch links neatly in tables.\n\nIf you don't use OVP but use e.g. latex fragments in tables or just pictures, this one is still very helpful.\n\nKudos to the author, great little package."}, "g3zeprg": {"author": "???", "upvotes": 11, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ikgfxd/comment/g3zeprg) \n**Votes:** 11\n\n**Suggestion for moderators** - Consider putting a note in the weekly announcement for this thread that using 3 backquotes or tildes to make code blocks doesn't work for those of us using old reddit (so the code people post that way is almost unreadable) - and that indenting by 4 spaces is better for compatibility.\n(Am I the only one who still uses old reddit? :-) )"}, "g1zlh2t": {"author": "kastauyra", "upvotes": 9, "body": "## u/kastauyra [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ibwzcu/comment/g1zlh2t) \n**Votes:** 9\n\n# 27.1 do GC if no frame has focus\n\nI am porting my [config](https://github.com/laurynas-biveinis/dotfiles) from 26.3 to 27.1, which had the tweak to do GC whenever a frame loses focus, originally from [MatthewZMD's config](https://github.com/MatthewZMD/.emacs.d) I think:\n```elisp\n(add-hook 'focus-out-hook #'garbage-collect)\n```elisp\n27.1 NEWS say more generic (and more correct) `after-focus-change-function` should be used instead. Which pointed out that I do not want to GC on just any frame going out of focus, if another frame is being focused instead. It might be a better idea to GC if no frames at all are focused. Somewhat surprisingly I was not able to find any public dotfiles repo implementing this to copy paste from, so I tried to write my own:\n```elisp\n(defun dotfiles--gc-on-last-frame-out-of-focus ()\n \"GC if all frames are inactive.\"\n (if (seq-every-p #'null (mapcar #'frame-focus-state (frame-list)))\n (garbage-collect)))\n\n(add-function :after after-focus-change-function\n #'dotfiles--gc-on-last-frame-out-of-focus)\n```"}, "fyrgnk7": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/hv3kzf/comment/fyrgnk7) \n**Votes:** 8\n\n[deleted]"}, "fy1rq34": {"author": "???", "upvotes": 15, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/hqxm5v/comment/fy1rq34) \n**Votes:** 15\n\nMigrated to native compiled emacs branch this week. Some hiccups but everything seems to work out of box, including pdf-tools. Great performance improvement."}, "fy0xduj": {"author": "ji99", "upvotes": 9, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/hqxm5v/comment/fy0xduj) \n**Votes:** 9\n\nHippie-expand google search suggestions. Completely inspired from [shell-parse.el](https://github.com/malloc47/shell-parse.el/blob/master/shell-parse.el).\n\nI've added `try-expand-google-completion` to the bottom of my `hippie-expand-try-functions-list`\n\n```elisp\n(defun google-suggest--request (query)\n (with-current-buffer\n (url-retrieve-synchronously\n (format \"http://suggestqueries.google.com/complete/search?client=firefox&q=%s\" query) t t 1)\n (goto-char (point-min))\n (re-search-forward \"^$\")\n (delete-region (point)(point-min))(buffer-string)))\n \n(defun google-suggest--list (result)\n (let* ((q (progn\n (string-match \",\\\\[\\\\(.*?\\\\)\\\\]\" result)\n (match-string 1 result)))\n (r (replace-regexp-in-string \"\\\\\\\"\" \"\" q))\n (l (split-string r \",\" t)))\n (when (> (length (car (cdr l))) 0)\n (remove\n (car l)\n (cdr l)))))\n \n(defun try-expand-google-completion (old)\n (unless old\n (he-init-string (hippie-word-bg) (point))\n (setq he-expand-list (sort\n (all-completions\n he-search-string\n (lambda (s y n) (google-suggest--list (google-suggest--request s))))\n 'string-lessp)))\n (if (null he-expand-list)\n (progn\n (when old (he-reset-string))\n ())\n (he-substitute-string (car he-expand-list) t)\n (setq he-tried-table (cons (car he-expand-list) (cdr he-tried-table)))\n (setq he-expand-list (cdr he-expand-list))\n t))\n```"}, "fwi4ikt": {"author": "Rotatop", "upvotes": 11, "body": "## u/Rotatop [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/hij4ga/comment/fwi4ikt) \n**Votes:** 11\n\nI've made it !\n\nAfter 6 month of emacs, I m able to open a side buffer when I m on ivy without using C-c C-O or hydra or alt-enter but directly with shift + arrow (except for Up because I need to go on buffer)\n\n\n```elisp\n;; Auto create new window\n(setq windmove-create-window t)\n;; thanks to https://people.gnome.org/~federico/blog/bringing-my-emacs-from-the-past.html\n;; Let me switch windows with shift-arrows instead of \"C-x o\" all the time\n(windmove-default-keybindings)\n \n;; Ugly hack :\n;; What I want is to Shift arrow, then it open the selection on a new splitted window (up left right, down)\n(defun tim/ivy-down-other ()\n (interactive)\n (ivy-exit-with-action #'tim/ivy-down-exit))\n \n(defun tim/ivy-left-other ()\n (interactive)\n (ivy-exit-with-action #'tim/ivy-left-exit))\n \n(defun tim/ivy-right-other ()\n (interactive)\n (ivy-exit-with-action #'tim/ivy-right-exit))\n \n(defun tim/ivy-down-exit (ivy-body)\n (split-window-below)\n (other-window 1)\n (tim/reuse-open-goto-line ivy-body))\n \n(defun tim/ivy-left-exit (ivy-body)\n (split-window-right)\n (tim/reuse-open-goto-line ivy-body))\n \n(defun tim/ivy-right-exit (ivy-body)\n (split-window-right)\n (other-window 1)\n (tim/reuse-open-goto-line ivy-body))\n \n \n;; Thanks to\n;; https://github.com/abo-abo/swiper/blob/master/doc/ivy.org#actions and\n;; https://www.reddit.com/r/emacs/comments/efg362/ivy_open_selection_vertically_or_horizontally/\n(defun tim/reuse-open-goto-line (ivy-body)\n (message \"reuse-open-goto-line ivy-body: %s\" ivy-body)\n (let* ((tim/list (split-string ivy-body \":\"))\n (file (car tim/list))\n (tim/number (car (cdr tim/list))))\n \n (condition-case err\n (counsel-projectile-find-file-action file)\n (void-function ; <- that s the error handler name\n (message \"open fail with projectile, try find-file. Error was: %s\" err)\n (find-file file)))\n ;; Thanks to https://stackoverflow.com/questions/3139970/open-a-file-at-line-with-filenameline-syntax\n (when tim/number\n ;; goto-line is for interactive use\n (goto-char (point-min))\n (forward-line (1- (string-to-number tim/number))))))\n ;; (ivy-resume)) ; It s strange but ivy-resume here change the way that 'ENTER' or ivy-done works afterwards\n ;; Try, as a workaround , in a timer ; no luck\n ;; (run-with-timer 0.1 nil 'ivy-resume))\n \n(use-package! ivy\n :bind (:map ivy-minibuffer-map\n (\"C-p\" . ivy-previous-history-element)\n (\"\" . tim/ivy-down-other)\n ;; no up to avoid changing buffer problems\n (\"\" . tim/ivy-left-other)\n (\"\" . tim/ivy-right-other))\n\n```\n\nEmacs is good"}, "fwt1k27": {"author": "WorldsEndless", "upvotes": 8, "body": "## u/WorldsEndless [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/hij4ga/comment/fwt1k27) \n**Votes:** 8\n\nRegisters: in Emacs from the beginning, so simple you forget how insanely useful they can be. I use them to save text, windows, and locations. https://orys.us/tv"}, "fwbtnte": {"author": "mullikine", "upvotes": 13, "body": "## u/mullikine [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fwbtnte) \n**Votes:** 13\n\n## Use chrome DOM for eww\n\nBasically, a lot of websites these days generate the DOM using javascript. You can dump the DOM from chrome and inject it into eww just before it renders.\n\nIt's set to wait 3 seconds before dumping the DOM. This allows many pages to load.\n\nSince I'm using the `unbuffer` program, this requires `expect` to be installed on your system. It creates a tty so that chrome doesn't crash when run in this way.\n\n`dump-dom` shell script\n\n```elisp\n#!/bin/bash\n \nurl=\"$1\"\ntest -n \"$url\" || exit 1\n \n0/dev/null\"\n\n```\nMake these modifications to `eww-display-html`.\n\n`eww-display-html`\n\n```elisp\n(defun eww-display-html (charset url &optional document point buffer encode)\n (unless (fboundp 'libxml-parse-html-region)\n (error \"This function requires Emacs to be compiled with libxml2\"))\n (unless (buffer-live-p buffer)\n (error \"Buffer %s doesn't exist\" buffer))\n ;; There should be a better way to abort loading images\n ;; asynchronously.\n (setq url-queue nil)\n ;; If document exists then the html is already parsed into a DOM\n (let* ((html (shell-command-to-string (concat \"dom-dump \" (shell-quote-argument url))))\n (document\n (or nil ;; document\n (list\n 'base (list (cons 'href url))\n (progn\n (setq encode (or encode charset 'utf-8))\n (condition-case nil\n (decode-coding-region (point) (point-max) encode)\n (coding-system-error nil))\n (save-excursion\n ;; Remove CRLF before parsing.\n (while (re-search-forward \"\\r$\" nil t)\n (replace-match \"\" t t)))\n (save-mark-and-excursion\n ;; Delete from here to the end. Replace with the new html\n (kill-region (point) (point-max))\n (insert (encode-coding-string html 'utf-8)))\n (libxml-parse-html-region (point) (point-max))))))\n (source (and (null document)\n (buffer-substring (point) (point-max)))))\n (with-current-buffer buffer\n (setq bidi-paragraph-direction nil)\n (plist-put eww-data :source html)\n (plist-put eww-data :dom document)\n (let ((inhibit-read-only t)\n (inhibit-modification-hooks t)\n (shr-target-id (url-target (url-generic-parse-url url)))\n (shr-external-rendering-functions\n (append\n shr-external-rendering-functions\n '((title . eww-tag-title)\n (form . eww-tag-form)\n (input . eww-tag-input)\n (button . eww-form-submit)\n (textarea . eww-tag-textarea)\n (select . eww-tag-select)\n (link . eww-tag-link)\n (meta . eww-tag-meta)\n (a . eww-tag-a)))))\n (erase-buffer)\n (shr-insert-document document)\n (cond\n (point\n (goto-char point))\n (shr-target-id\n (goto-char (point-min))\n (let ((point (next-single-property-change\n (point-min) 'shr-target-id)))\n (when point\n (goto-char point))))\n (t\n (goto-char (point-min))\n ;; Don't leave point inside forms, because the normal eww\n ;; commands aren't available there.\n (while (and (not (eobp))\n (get-text-property (point) 'eww-form))\n (forward-line 1)))))\n (eww-size-text-inputs))))\n\n```\nDemonstration:\nhttps://asciinema.org/a/UAAVfp5O8SofJZvKBusTOP8QQ"}, "fvqvedf": {"author": "jimm", "upvotes": 11, "body": "## u/jimm [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvqvedf) \n**Votes:** 11\n\nI can't say how often I use `dabbrev-expand` (`M-/`) to complete words. Saves me a ton of time."}, "fvqq7ck": {"author": "???", "upvotes": 11, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvqq7ck) \n**Votes:** 11\n\nUndo-tree and kill-ring are two of the best features in Emacs / packages. Change your life today."}, "fvrlu40": {"author": "sauntcartas", "upvotes": 10, "body": "## u/sauntcartas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvrlu40) \n**Votes:** 10\n\nI've been using `M-|` (`shell-command-on-region`) frequently for years, and I only just stumbled on the fact that the region need not be active to use it. If it isn't, the command operates on the text from point to the end of the buffer. That's very reasonable and in line with various other commands, but the documentation doesn't mention it and so I never thought to try it.\n\nThat saves me a call to `C-x h` (`mark-whole-buffer`) whenever I want to process the entire buffer, which is most of the time. Also, it's a minor distraction for the entire buffer to be highlighted when I'm composing my shell command, so it's nice to avoid that.\n\nEdited to add: Sorry folks, this doesn't work like I thought it did. See the coments below for details."}, "fvrw4cu": {"author": "aartist111", "upvotes": 8, "body": "## u/aartist111 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvrw4cu) \n**Votes:** 8\n\nFound / c for M-x ibuffer. It filters buffers by content.\nIt looks like 'grep -c' . Very helpful to locate a file quickly for which you remember any word from content\nUntil now I had only used filters for filenames or modes only. ."}, "fvy3geb": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/heaoiu/comment/fvy3geb) \n**Votes:** 8\n\n`(setq visual-order-cursor-movement t)`\n\n> If non-nil, moving cursor with arrow keys follows the visual order.\n> \n> When this is non-nil, will move to the character that is\nto the right of point on display, and will move to the left,\ndisregarding the surrounding bidirectional context. Depending on the\nbidirectional context of the surrounding characters, this can move point\nmany buffer positions away.\n> \n> When the text is entirely left-to-right, logical-order and visual-order\ncursor movements produce identical results.\"\n\nI write in Arabic."}, "fuzucay": {"author": "rhmatthijs", "upvotes": 10, "body": "## u/rhmatthijs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/h9zoy9/comment/fuzucay) \n**Votes:** 10\n\nOn a Mac: make Emacs detect if you have light or dark mode enabled system wide.\n\nIf you have two themes, a light one and a dark one, and you want the dark theme by default unless you have light mode enabled, add this to your init.el:\n\n```elisp\n;; If we're on a Mac and the file \"~/bin/get_dark.osascript\" exists\n;; and it outputs \"false\", activate light mode. Otherwise activate\n;; dark mode.\n(cond ((and (file-exists-p \"~/bin/get_dark.osascript\")\n (string> (shell-command-to-string \"command -v osascript\") \"\")\n (equal \"false\\n\"\n (shell-command-to-string \"osascript ~/bin/get_dark.osascript\")))\n (mcj/theme-set-light))\n (t (mcj/theme-set-dark)))\n\n```\n(mcj/theme-set-light and mcj/theme-set-light are functions that enable the light and the dark theme, respectively).\n\n~/bin/get_dark.osascript contains the following:\n\n```elisp\ntell application \"System Events\"\n\ttell appearance preferences\n\t\tget dark mode\n\tend tell\nend tell\n```"}, "ftgqnbp": {"author": "rhmatthijs", "upvotes": 13, "body": "## u/rhmatthijs [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gzivu3/comment/ftgqnbp) \n**Votes:** 13\n\nWorking in education, I often find myself having to assign students into groups. This week I made a function in ELisp that helps me do this. Select a region in a buffer that contains a list of students (presumably), call this function, say how many students should be in each group and the function then randomly assigns groups.\n\n```elisp\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; ;;\n;; Shuffling things. ;;\n;; ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n \n(defun mcj/shuffle (input)\n \" Shuffle a list in place. For some reason does not exist in\nEmacs by default. Uses Fisher-Yates shuffle.\n\"\n (let ((swap (lambda (list-to-swap i1 i2)\n (let ((tmp (elt list-to-swap i1)))\n (setf (elt list-to-swap i1) (elt list-to-swap i2))\n (setf (elt list-to-swap i2) tmp)))))\n (dotimes (i (length input) input)\n (funcall swap input i (random (+ i 1))))))\n\n \n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; ;;\n;; Pairing off things (students, say). ;;\n;; ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n \n(defun mcj/pair-off (input num)\n \"Return the elements of input paired off into pairs of length\n num\"\n (cond ((< (length input) (* num 2)) (list input))\n (t\n (cons (butlast input (- (length input)num)) (mcj/pair-off (nthcdr num input) num)))))\n \n \n \n(defun mcj/pair-off-region (num)\n \" Pair off lines in a region\"\n (interactive (list\n (read-number \"Members per pair (num):\" 2)))\n (let ((newcontents\n (mapconcat (lambda (item-pair)\n (mapconcat (lambda (item) item) item-pair \" + \"))\n (mcj/pair-off\n (mcj/shuffle\n (split-string\n (buffer-substring-no-properties (mark) (point)) \"[\\n]\" t ))\n num)\n \"\\n\")))\n (delete-region (mark) (point))\n (insert newcontents)))\n```"}, "fruqs1k": {"author": "_hmenke", "upvotes": 13, "body": "## u/_hmenke [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gqsz8u/comment/fruqs1k) \n**Votes:** 13\n\nAny **BibTeX** users here?\n\n- Tired of journals forcing you to download a file to get the BibTeX record of an article?\n- Tired of their usually broken formatting?\n- The journal doesn't offer BibTeX download in the first place? (Looking at you Nature)\n\nDid you know that doi.org has query interface that gives you the BibTeX record when you call it with the article DOI? Of course you can access this via Emacs:\n\n```elisp\n(require 'url)\n(defun user/url-bibtex-from-doi (doi)\n (interactive \"sDOI: \")\n (let* ((url (concat \"https://doi.org/\" doi))\n (url-mime-accept-string \"application/x-bibtex\"))\n (insert\n (with-current-buffer (url-retrieve-synchronously url)\n (let* ((start url-http-end-of-headers)\n (end (point-max))\n (all (buffer-string))\n (body (buffer-substring start end)))\n (replace-regexp-in-string \"^\\t\" \" \" (url-unhex-string body)))))))\n\n```\nJust paste the DOI of the article at the prompt and the BibTeX record will be inserted at point.\n\nHere is how I bind it in `bibtex-mode` (plus my other bindings for good measure)\n \n```elisp\n;; bibtex\n(use-package bibtex\n :bind (:map bibtex-mode-map\n (\"C-c d\" . user/url-bibtex-from-doi)\n (\"C-c v\" . bibtex-validate)\n (\"C-c s\" . bibtex-sort-buffer)\n ([down-mouse-3] . imenu))\n :config\n (setq\n bibtex-maintain-sorted-entries t))\n```"}, "fr4gdm6": {"author": "hairlesscaveman", "upvotes": 8, "body": "## u/hairlesscaveman [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gmkg4g/comment/fr4gdm6) \n**Votes:** 8\n\nI follow the format of `{ticketnumber}-{short-description}` when creating branches using Magit, but when typing the descriptive name for the branch I often type `SPC` between words instead of dash due to muscle memory when writing sentences. This causes a warning to be shown, because \"Whitespace isn't allowed here\", and breaks \"flow\" for me.\n\nThe advice below quiets this warning, and inserts a dash whenever space is pressed.\n\n```elisp\n(advice-add 'magit-whitespace-disallowed :around (lambda (orig-fun &rest args) (interactive) (insert \"-\")))\n```"}, "fr65b4d": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gmkg4g/comment/fr65b4d) \n**Votes:** 8\n\nTIL that I can disable ``company`` for some modes, I needed to do it because completion was really slow for the shell and eshell which have vanilla shell completion anyway. Thus \n\n```elisp\n(use-package company\n :after ispell\n :diminish\n :config\n .\n .\n .\n (setq company-global-modes '(not eshell-mode shell-mode))\n (global company-mode 1))\n \n```\nworks as intended"}, "fqe6yop": {"author": "celeritasCelery", "upvotes": 34, "body": "## u/celeritasCelery [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gienra/comment/fqe6yop) \n**Votes:** 34\n\n> I had received the advice to not install anything and just start with plain emacs so I can learn emacs. ... it was miserable. \n> Enter Doom Emacs. I decided to give Doom Emacs a try because it was also highly recommended in my initial RFC, especially since it is designed for Vim users. In short I love it.\n\nThis is why I disagree with the subreddits de facto advice to \u201clearn vanilla first\u201d. People who have used emacs for a long time don\u2019t realize how much **time** it takes to get it to level of a normal modern editor people are used to. I recommend distros to *everyone* who is new unless they are that certain personality type that wants to do everything themselves."}, "fqdnyhk": {"author": "celeritasCelery", "upvotes": 13, "body": "## u/celeritasCelery [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqdnyhk) \n**Votes:** 13\n\nShells in emacs like `shell-mode` and `eshell` can write multi line input using `comint-accumulate`. Normally bound to `C-c SPC`."}, "fqg7qys": {"author": "hale314", "upvotes": 11, "body": "## u/hale314 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqg7qys) \n**Votes:** 11\n\nI tend to have a lot of function that is defined solely to be added to a hook. Turns out I can customize `defun-declarations-alist` to define a new `hook` property in the `declare` form. Now I can specify the hook that the function is intended for right inside the function definition.\n\n```elisp\n;; Need to be done during compilation as well if your functions are getting compiled\n(eval-and-compile\n (setf (alist-get 'hook defun-declarations-alist)\n (list (lambda (fun _args hook &optional depth)\n `(add-hook ',hook #',fun ,@(when depth (list depth)))))))\n \n(defun ask-about-scratch-buffer ()\n \"Confirm that user want to discard the content of the scratch buffer.\"\n (declare (hook kill-emacs-query-functions))\n (let ((scratch (get-buffer \"*scratch*\")))\n (or (zerop (buffer-size scratch))\n (progn (pop-to-buffer scratch)\n (y-or-n-p \"Scratch buffer is not empty, discard?\")))))\n;; no longer needed\n;; (add-hook 'kill-emacs-query-functions #'ask-about-scratch-buffer)\n```"}, "fqczes1": {"author": "???", "upvotes": 8, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqczes1) \n**Votes:** 8\n\n[A beginers guide to emacs 24 or later by sasha chua](https://sachachua.com/blog/wp-content/uploads/2013/05/How-to-Learn-Emacs-v2-Large.png) this helped me tremendously to get started with emacs."}, "fqcycvb": {"author": "ji99", "upvotes": 8, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqcycvb) \n**Votes:** 8\n\nA rudimentary interface for the fabulous [Links web browser](http://links.twibright.com/user_en.html):\n\n```elisp\n(defun links-browser (&optional link new-window)\n (interactive)\n (unless link\n (setq link (read-from-minibuffer \"url: \")))\n (make-process\n :name \"links-browser\"\n :connection-type 'pipe\n :command (list \"links\" \"-g\" link)))\n \n(defun links-search (&optional query)\n (interactive)\n (unless query\n (setq query (read-from-minibuffer \"search query: \")))\n (pcase query\n ((pred (string-match \"\\\\`d .*\"))\n (links-search--launch \"dict\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`b .*\"))\n (links-search--launch \"book\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`w .*\"))\n (links-search--launch \"wiki\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`m .*\"))\n (links-search--launch \"imdb\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`y .*\"))\n (links-search--launch \"yout\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`t .*\"))\n (links-search--launch \"thes\" (substring query 2 nil)))\n ((pred (string-match \"\\\\`s .*\"))\n (links-search--launch \"syno\" (substring query 2 nil)))\n (_ (links-search--launch \"seax\" query))))\n \n(defun links-search--launch (engine query)\n (pcase engine\n (\"dict\" (links-browser (format \"https://en.wiktionary.org/wiki/Special:Search?search=%s\" query)))\n (\"wiki\" (links-browser (format \"https://en.wikipedia.org/w/index.php?title=Special:Search&search=%s&go=Go\" query)))\n (\"imdb\" (links-browser (format \"https://www.imdb.com/find?s=all&q=%s\" query)))\n (\"yout\" (links-browser (format \"https://www.youtube.com/results?search_query=%s\" query)))\n (\"book\" (links-browser (format \"http://gen.lib.rus.ec/search.php?req=%s&res=100&sort=id&sortmode=DESC\" query)))\n (\"thes\" (links-browser (format \"https://www.powerthesaurus.org/%s\" query)))\n (\"syno\" (links-browser (format \"https://duckduckgo.com/lite/?q=%s site:macmillandictionary.com\" query)))\n (\"seax\" (links-browser (format \"https://search.snopyta.org/?q=%s\" query)))))\n```"}, "fqfc1wi": {"author": "karthink", "upvotes": 8, "body": "## u/karthink [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gi70ye/comment/fqfc1wi) \n**Votes:** 8\n\nAucTex users: You're missing out if you don't use [CDLatex](https://github.com/cdominik/cdlatex). It's primarily a fast input tool for LaTeX, sort of like snippet templates. The difference between setting up Yasnippet templates for LaTeX and CDLatex is that CDLaTeX's TAB key to jump past stuff is _always available_, not just during snippet entry. It's difficult to explain, so here are some demos:\n\n1. [Fast input with cdlatex and preview.el](https://gfycat.com/heavenlynegligiblehoiho)\n2. [Fast input with keys displayed](https://gfycat.com/safeidolizedlangur)\n\nI wrote a longer post explaining [how I set up AucTex](https://www.reddit.com/r/emacs/comments/g8ecpj/advice_for_auclatex_what_keybinds_do_you_find/foo64ge/) recently.\n\nCDLaTeX was written by Carsten Dominik, the author of Org-mode and reftex. Thus Org ships with an `org-cdlatex` minor-mode that makes these features available in org-mode."}, "fq9186h": {"author": "b3n", "upvotes": 8, "body": "## u/b3n [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/gdtqov/comment/fq9186h) \n**Votes:** 8\n\nIf you want to switch between two themes, depending on time of day (e.g. a light and dark theme), it's as simple as this:\n\n```elisp\n;; Light\n(load-theme 'modus-operandi t t)\n(run-at-time \"05:00\" (* 60 60 24) (lambda () (enable-theme 'modus-operandi))))\n\n;; Dark\n(load-theme 'modus-vivendi t t)\n(run-at-time \"21:00\" (* 60 60 24) (lambda () (enable-theme 'modus-vivendi))))\n\n```\nThis selects the correct theme when starting Emacs and automatically switch when the times come."}, "fo362s8": {"author": "oantolin", "upvotes": 10, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/g5bat3/comment/fo362s8) \n**Votes:** 10\n\n`rx` isn't just an (extensible!) sexp syntax for regexps, it's an optimizing compiler!\n\nExamples:\n\n- `(rx (or \"dude@home.org\" \"dude@work.com\"))` produces\n```elisp\n`\"\\\\(?:dude@\\\\(?:home\\\\.org\\\\|work\\\\.com\\\\)\\\\)\"`\n```\n- `(rx (intersection (any (?g . ?z)) (any (?a . ?p))))` produces `\"[g-p]\"`\n\nAnd from Lisp code it's easy to plug in computed portions, using `eval`.\nFor example I recently used this in some silly code to count mentions\nof animals in the bible :P:\n\n```elisp\n(defun plural (word)\n (pcase word\n (\"mouse\" \"mice\")\n (\"wolf\" \"wolves\")\n (\"fish\" \"fishes\")\n (word (concat word \"s\"))))\n \n(defun bible-count (word)\n \"Count number of times WORD or its plural appears in the bible.\"\n (with-current-buffer \"king-james-bible.txt\"\n (count-matches\n (rx-to-string `(word-start (or ,word ,(plural word)) word-end)))))\n\n```\nWhich I used to make an Org mode table with an Emacs Lisp column formula:\n\n```elisp\n#+TBLFM: $2='(bible-count $1)\n\n```\n**EDIT**: A previous version of the `bible-count` function used the `rx` macro and the `eval` construct:\n\n```elisp\n(defun bible-count (word)\n \"Count number of times WORD or its plural appears in the bible.\"\n (with-current-buffer \"king-james-bible.txt\"\n (count-matches (rx word-start\n (or (eval word) (eval (plural word)))\n word-end))))\n\n```\nThis version is incorrect: `eval` is meant to be used only for value known at compile time. It's actual [behavior is very complicated](https://www.reddit.com/r/emacs/comments/g5bat3/weekly_tipstricketc_thread/fo7qdas) and depends on plenty of seemingly extraneous circumstances."}, "fnd2p6p": {"author": "shiroghost", "upvotes": 8, "body": "## u/shiroghost [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/g11mp9/comment/fnd2p6p) \n**Votes:** 8\n\nI use `mu4e` as email client. I guess that it is common to send some email to later discover that you forgot the attachment.\n\nThis routines check if a mail **likely** needs an attachment by matching a simple regexp. If this is the case and there is no attach, we are asked to confirm that this is what we want to do.\n\n```elisp\n ;;\n ;; Auto-detect if there is a missing attachment in the\n ;; mail and warn before sending.\n ;;\n ;; See https://notmuchmail.org/pipermail/notmuch/2018/026414.html\n ;;\n (defcustom message-likely-needs-attach-regex \"attach\\\\|file\\\\|adjunto\\\\|fichero\"\n \"regex that matches if a mail likely needs an attach. In\n most cases this just matches a few keywords\"\n :type '(regexp))\n \n (defun message-narrow-to-body()\n \"Narrow the compose buffer to the body of the mail\"\n (interactive)\n (widen)\n (goto-char (point-min))\n (narrow-to-region\n (re-search-forward \"--text follows this line--\" nil t 1)\n (point-max)))\n \n (defun mail-needs-attach-p ()\n \"Count number of attach keywords in buffer and return t \n if there is any\"\n (interactive)\n (save-excursion\n (message-narrow-to-body)\n (let (\n (res (count-matches message-likely-needs-attach-regex)))\n (widen)\n (> res 0))))\n \n (defun mail-number-of-attach ()\n \"Count number of attach in buffer.\"\n (interactive)\n (save-excursion\n (goto-char (point-min))\n (count-matches \"<#part [^>]*filename=[^>]*>\")))\n \n (defun check-mail-and-send ()\n \"Check if mail will likely have a missing attachment. \n If yes ask for confirmation, if no send it.\"\n (interactive)\n (if (mail-needs-attach-p)\n (if (> (mail-number-of-attach) 0)\n (message-send-and-exit)\n (if (y-or-n-p \"Mail has NO attach. Send it anyway? \")\n (message-send-and-exit)))\n (message-send-and-exit)))\n \n (define-key mu4e-compose-mode-map (kbd \"C-c C-c\") 'check-mail-and-send)\n```"}, "fnd7zkx": {"author": "???", "upvotes": 13, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/g11mp9/comment/fnd7zkx) \n**Votes:** 13\n\nIf you're not using [`native-comp`](http://akrl.sdf.org/gccemacs.html) feature yet, I strongly recommend you to try it out! Have been using it for two weeks for now and everything seem to run pretty smooth and rock solid! The speed difference is quite noticeable in some interactive aspects like completion, although my machine is quite slow, so this may not be that noticeable on newer machines."}, "fmo9d5v": {"author": "zoechi", "upvotes": 12, "body": "## u/zoechi [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fwgpkd/comment/fmo9d5v) \n**Votes:** 12\n\nI (Emacs rookie) just found out that native/fast JSON support is not guaranteed when emacs 27+ is used. jansson-dev needs to be installed when Emacs is built https://github.com/emacs-lsp/lsp-mode/issues/1557#issuecomment-608409056"}, "fmochkh": {"author": "xu-chunyang", "upvotes": 9, "body": "## u/xu-chunyang [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fwgpkd/comment/fmochkh) \n**Votes:** 9\n\nPrettify the minibuffer prompt on the default value\n\n```elisp\n(setq minibuffer-eldef-shorten-default t)\n(minibuffer-electric-default-mode)\n\n```\nThen try eval\n\n```elisp\n(read-string \"Year (default 2019): \" nil nil \"2019\")\n\n```\nYou will notice \"Year (default 2019): \" is shorten to \"Year [2019]: \", and when\nyou enter anything, the prompt is shorten further to \"Year: \". Next time, you\nuse the minibuffer api, if you provide the default value, don't forget to format\nthe prompt using that specfic format."}, "fm1fw1x": {"author": "sauntcartas", "upvotes": 14, "body": "## u/sauntcartas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fs93hk/comment/fm1fw1x) \n**Votes:** 14\n\nFor me, learning about `kill-whole-line` (control-shift-delete) was a revelation. Compared to the \"classic\" Emacs method of deleting lines (C-a to go to the beginning of the line if not already there, C-k once to kill to the end of line, C-k again to kill the newline), it feels like a major speedup.\n\nI still use C-k frequently, but it's effectively just a kill-to-end-of-line command."}, "flcwsu4": {"author": "xu_chunyang", "upvotes": 11, "body": "## u/xu_chunyang [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fo1fm3/comment/flcwsu4) \n**Votes:** 11\n\nHappy Birthday from Emacs, let's assume March 24 is your birthday, put this to your init file, when you open Emacs on your birthday, you'll receive a birthday present from Emacs\n\n```elisp\n(when (string= \"03-24\" (format-time-string \"%m-%d\"))\n (animate-birthday-present user-full-name))\n```"}, "fk3in25": {"author": "oantolin", "upvotes": 14, "body": "## u/oantolin [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fgahb2/comment/fk3in25) \n**Votes:** 14\n\nMost people probably know that `M-t` (`transpose-words`) when used between two words swaps them. But it has other a few other features that are useful:\n\n- You don't have to be between words to use it: if you are on a word, from the second character on, it will swap that word with the next.\n\n- If you are at the end of the buffer and use it you get an error message, \"Don\u2019t have two things to transpose\", _but_ you additionally get placed at the beginning of the last word in the buffer. So `M-t M-t` used at the end of the buffer will swap the last two words!\n\n- You can use it to swap _non-adjacent_ words too! If you call it with a numeric argument of 0, it will swap the word at the start of the region with the next word after the end of the region. For example, say you want to swap \"two\" with \"five\" in the following line:\n\n```elisp\n one five three four two six\n \n```\n You can mark the words \"five three four\" (but don't mark \"two\") and then `M-0 M-t` will swap \"five\", the first word in the region, with \"two\" the first word _after_ the region.\n\nThat last trick works with the other `transpose-` commands as well, not just words: `transpose-chars`, `transpose-lines`, `transpose-paragraphs`, `transpose-sentences`, and `transpose-sexps`. Of course, if that `C-0` trick can't be used with any of those commands to swap the two things you want, there is always `transpose-regions`."}, "fki3lrc": {"author": "Desmesura", "upvotes": 8, "body": "## u/Desmesura [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/fgahb2/comment/fki3lrc) \n**Votes:** 8\n\nAny Emacs Mode for dealing with Coronavirus?"}, "fiqj0dn": {"author": "loopsdeer", "upvotes": 13, "body": "## u/loopsdeer [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/f972tf/comment/fiqj0dn) \n**Votes:** 13\n\nYou can store a bookmark on a Magit status window and it WORKS!\n\nI just tried it last night figuring it would err when I tried to open the bookmark later, and it worked and I'm very excited about it.\n\nThis is the perfect entry point for projects for me, being reminded of what state source control is in. I used to jump to Dired in the .git root or some main code window but neither were helpful to start my day. This is perfect.\n\nI set the bookmark with \\`helm-filtered-bookmarks\\` by just being on the Magit window and running that then typing in my name, and this is what was added to my bookmark file:\n\n```elisp\n(\"my magit bookmark title\"\n (front-context-string . \"Unstaged changes\")\n (rear-context-string . \"[redacted for reddit]\\n\\n\")\n (position . 124)\n (handler . magit--handle-bookmark)\n (mode . magit-status-mode)\n (filename . \"/redacted/path/to/.git\")\n (magit-hidden-sections\n (stashes . \"refs/stash\")\n (unpushed . \"@{upstream}..\")))\n\n```\nI quit Emacs, made an edit in my .git elsewhere, opened Emacs back up and jumped to this bookmark and it showed me the change! \n\nIt's funny how excited I am to remove two keystrokes from the beginning of my day. Probably I am also excited that my random experiment worked. Obviously it's not so random as magit knew exactly what I wanted. Magit is life! "}, "firc94m": {"author": "fabiopapa", "upvotes": 8, "body": "## u/fabiopapa [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/f972tf/comment/firc94m) \n**Votes:** 8\n\nThis may be common knowledge, but I\u2019m always surprised at how few people know about this.\n\nIf you have an `ALTERNATE_EDITOR=''`environment variable, and start emacsclient with no emacs server running, it will start an emacs server and try starting emacsclient again. Also works with a `-a` flag on emacsclient command."}, "fipuizk": {"author": "github-alphapapa", "upvotes": 8, "body": "## u/github-alphapapa [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/f972tf/comment/fipuizk) \n**Votes:** 8\n\nAn early WIP of a perspective-like buffer grouper/switcher based on automatically grouping buffers by recursive grouping rules written by the user: https://github.com/alphapapa/buffer-groups.el Defining the grouping rules looks like this:\n\n```elisp\n(setf buffer-groups-groups\n (buffer-groups-defgroups\n (group (dir \"~/org\")\n (auto-indirect))\n (group (dir buffer-groups-emacs-source-directory))\n (group (auto-special))\n (group (mode-match \"*Helm*\" (rx bos \"helm-\")))\n (auto-project)))\n\n```\nIt's based on code from https://github.com/alphapapa/sbuffer.el, which should hit MELPA soon."}, "fhar795": {"author": "???", "upvotes": 12, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/f25er5/comment/fhar795) \n**Votes:** 12\n\nMake a `.desktop` file for emacsclient and make sure to include `-c` in the command line ([my .desktop](https://github.com/cadadr/configuration/blob/master/candy/emacsclient.desktop)). Then, you can associate Emacs with many filetypes with emacsclient, and view them in Emacs. E.g., this is how I view PDF files. `-c` is useful because it opens in a new frame, thus your window setup is left intact and the OS window is always in the current workspace (useful if you've set up your WM to not focus urgent windows automatically).\n\nIn a similar vein, I use [this script](https://github.com/cadadr/configuration/blob/master/emacs.d/extras/mailto.el.in) to redirect `mailto:` links to Emacs so that I can write my mails in `message-mode` within Emacs. I've set it as the mail program in Firefox. It's probably possible to write a `.desktop` file for this so that you can set it in `mimeapps.list` or whatever as the global mail composer, but IDK how to do that.\n\nWith emacsclient and a bit of Elisp, it's really easy to integrate Emacs to a FreeDesktop environment. I can't speak for Windows or Mac OS tho, because I don't use those often."}, "fgjj6i8": {"author": "nv-elisp", "upvotes": 8, "body": "## u/nv-elisp [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/eymwl9/comment/fgjj6i8) \n**Votes:** 8\n\nI use a number of Emacs servers daily: terminal $EDITOR, GUI Emacs, elfeed updater, and one to summon a dedicated org-capture client.\nThis macro allows running code on a group of servers by name.\n\n```elisp\n;;;###autoload\n(defmacro my/with-servers (servers &rest body)\n \"Evaluate BODY on each server in SERVERS.\nIf SERVERS is the symbol \\all\\:, evaluate BODY on all servers.\"\n (declare (indent defun))\n (let* ((files (directory-files server-socket-dir nil nil t))\n (sockets (cond\n ((eq 'all servers)\n (seq-filter (lambda (file)\n (not (member file '(\".\" \"..\"))))\n files))\n ((and (listp servers)\n (seq-every-p #'stringp servers))\n servers)\n (t (signal 'wrong-type-error `(((stringp), all) ,servers))))))\n `(let (current-server)\n (condition-case err\n (let ((servers (mapc (lambda (socket)\n (setq current-server socket)\n (server-eval-at socket '(progn ,@body nil)))\n ',sockets)))\n (format \"evaled on %d servers: %s\" (length servers) servers))\n (error (message \"%s on server %s\" err current-server))))))\n\n```\nA couple of examples:\n\n```elisp\n(defun my/kill-server (name)\n \"Kill emacs server named NAME.\"\n (eval `(my/with-servers (,name)\n (kill-emacs))))\n \n(defun my/kill-other-servers ()\n \"Kill other Emacs servers.\"\n (interactive)\n (eval `(my/with-servers all\n (when (not (equal server-name ,server-name))\n (kill-emacs)))))\n \n(defun my/reload-init-on-all-servers ()\n \"Reload init file on all Emacs servers.\"\n (interactive)\n (my/with-servers all\n (load-file \"~/.emacs.d/init.el\")))\n```"}, "fftpfj0": {"author": "kastauyra", "upvotes": 9, "body": "## u/kastauyra [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ev2q9q/comment/fftpfj0) \n**Votes:** 9\n\nI use Emacs on my laptop either undocked, either with external screens connected. It used to be manual work of dragging and resizing frames around, and then setting up windows, but no more, thanks to the great [dispwatch](https://github.com/mnp/dispwatch) package, which handles the screen changes after Emacs has been started. I [wrote some code](https://github.com/laurynas-biveinis/dotfiles/blob/master/emacs/emacs/setup.el#L154) for the initial frame setup, and now have this, which makes the docking/undocking fully seamless:\n\n```elisp\n;;; Window and frame geometry\n(defun two-windows ()\n \"Make frame contain two vertical windows.\"\n (interactive)\n (delete-other-windows)\n (split-window-right))\n \n(defun six-windows ()\n \"Make frame contain 2x3 windows.\"\n (interactive)\n (delete-other-windows)\n (split-window-below)\n (split-window-right)\n (split-window-right)\n (windmove-down)\n (split-window-right)\n (split-window-right)\n (balance-windows))\n \n(cl-defstruct dotfiles--frame-geometry top left height width)\n \n(defun dotfiles--add-frame-geometry-to-initial-alist (geometry)\n \"Add frame GEOMETRY to `initial-frame-alist'.\"\n (add-to-list 'initial-frame-alist\n `(top . ,(dotfiles--frame-geometry-top geometry)))\n (add-to-list 'initial-frame-alist\n `(left . ,(dotfiles--frame-geometry-left geometry)))\n (add-to-list 'initial-frame-alist\n `(height . ,(dotfiles--frame-geometry-height geometry)))\n (add-to-list 'initial-frame-alist\n `(width . ,(dotfiles--frame-geometry-width geometry))))\n \n(defun dotfiles--move-to-frame-geometry (geometry)\n \"Resize and repositon frame to GEOMETRY.\"\n (set-frame-position nil (dotfiles--frame-geometry-left\n geometry)\n (dotfiles--frame-geometry-top geometry))\n (set-frame-size nil (dotfiles--frame-geometry-width geometry)\n (dotfiles--frame-geometry-height geometry)))\n \n(defconst darkstar-laptop-screen '(1680 . 1050))\n(defconst darkstar-laptop-geometry\n (make-dotfiles--frame-geometry :top 1 :left 1 :height 65 :width 237))\n \n(defconst darkstar-external-screen '(7696 . 1692))\n(defconst darkstar-external-geometry\n (make-dotfiles--frame-geometry :top 4 :left 3011 :height 117 :width 426))\n \n;; Possible interim states while docking/undocking - ignore\n(defconst frame-geometries-to-ignore [(3600 . 1080) (5520 . 1080) (4688 . 1692)\n (3600 . 1692) (3008 . 1692)])\n \n(defun diagnose-unknown-display-geometry (display-geometry)\n \"Diagnose unknown DISPLAY-GEOMETRY.\"\n (message \"Unknown display size %sx%s\"\n (car display-geometry) (cdr display-geometry)))\n \n(require 'seq)\n(let ((display-geometry (cons (display-pixel-width) (display-pixel-height))))\n (cond ((equal display-geometry darkstar-laptop-screen)\n ;; darkstar without external screens: initial frame positioned in the\n ;; top left corner\n (dotfiles--add-frame-geometry-to-initial-alist\n darkstar-laptop-geometry)\n (two-windows))\n ((equal display-geometry darkstar-external-screen)\n ;; darkstar with external screens: initial frame maximized in the\n ;; middle screen\n (dotfiles--add-frame-geometry-to-initial-alist\n darkstar-external-geometry)\n (add-to-list 'initial-frame-alist '(fullscreen . fullboth))\n (add-to-list 'initial-frame-alist '(fullscreen-restore . maximized))\n (six-windows))\n ((seq-position frame-geometries-to-ignore display-geometry) ())\n (t (diagnose-unknown-display-geometry display-geometry))))\n \n;;; dispwatch\n(require 'dispwatch)\n(defun dotfiles--display-changed-hook (new-display-geometry)\n \"Reconfigure frame windows on display geometry change to NEW-DISPLAY-GEOMETRY.\"\n (message \"Resizing for %s\" new-display-geometry)\n (cond ((equal new-display-geometry darkstar-laptop-screen)\n (dotfiles--move-to-frame-geometry darkstar-laptop-geometry)\n (set-frame-parameter nil 'fullscreen 'maximized)\n (two-windows))\n ((equal new-display-geometry darkstar-external-screen)\n (dotfiles--move-to-frame-geometry darkstar-external-geometry)\n (set-frame-parameter nil 'fullscreen 'fullboth)\n (six-windows))\n ((seq-position frame-geometries-to-ignore new-display-geometry) ())\n (t (diagnose-unknown-display-geometry new-display-geometry))))\n \n(add-hook 'dispwatch-display-change-hooks #'dotfiles--display-changed-hook)\n(dispwatch-mode 1)\n\n```\nSome things here might be overkill (cl-defstruct, seq?), but this was also an Emacs lisp exercise."}, "ff90d5b": {"author": "primitiveinds", "upvotes": 10, "body": "## u/primitiveinds [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/erro41/comment/ff90d5b) \n**Votes:** 10\n\nI just now figured out that you can interactively pass flags to commands like `counsel-rg` by putting the `--` separator between the flags and the search string, so something like `-g '*.txt' -- whatever` will search for `whatever` only in `txt` files. `counsel` uses a function called `counsel--split-command-args` to split the parts before and after the `--`."}, "fed40nx": {"author": "freesteph", "upvotes": 15, "body": "## u/freesteph [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/eoigxl/comment/fed40nx) \n**Votes:** 15\n\nIf you needed more reasons to love Magit I've just found out can add the Git meta-fields in the commit message (`Co-authored-by`, `Signed-off-by`, etc, which I can never remember correctly) by typing `C-c TAB` which will interactively ask you for the field (`C-a` -> `Co-authored-by`) and then also interactively fill the relevant team member with their name and e-mail (probably from the repo's list of committers). Awesome!"}, "fdggv7n": {"author": "ji99", "upvotes": 8, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/el8oq7/comment/fdggv7n) \n**Votes:** 8\n\n```elisp\n(defun repeat-last-shell-command ()\n (interactive)\n (let ((last-cmd (cadr (assoc 'shell-command command-history))))\n (when (y-or-n-p (concat \"execute \" last-cmd))\n (async-shell-command last-cmd))))\n```"}, "fdh3fyn": {"author": "itistheblurstoftimes", "upvotes": 8, "body": "## u/itistheblurstoftimes [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/el8oq7/comment/fdh3fyn) \n**Votes:** 8\n\nI had previously written a function to replace org-beginning-of-line to behave this way, but later found `org-special-ctrl-a/e` which does exactly what I wanted for C-a (and C-e). The default behavior drove me crazy and I didn't know there was a built-in fix. \n\n```elisp\n \"Non-nil means `C-a' and `C-e' behave specially in headlines and items. When t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line.`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses.When set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions.This may also be a cons cell where the behavior for `C-a' and`C-e' is set separately.\n \n\"When t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line.`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses.When set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions. This may also be a cons cell where the behavior for `C-a' and `C-e' is set separately.\"\n \nWhen t, `C-a' will bring back the cursor to the beginning of the headline text, i.e. after the stars and after a possible TODO keyword. In an item, this will be the position after bullet and check-box, if any. When the cursor is already at that position,another `C-a' will bring it to the beginning of the line.\n \n`C-e' will jump to the end of the headline, ignoring the presence of tags in the headline. A second `C-e' will then jump to the true end of the line, after any tags. This also means that, when this variable is non-nil, `C-e' also will never jump beyond the end of the heading of a folded section, i.e. not after the ellipses.\n \nWhen set to the symbol `reversed', the first `C-a' or `C-e' works normally, going to the true line boundary first. Only a directly following, identical keypress will bring the cursor to the special positions. This may also be a cons cell where the behavior for `C-a' and `C-e' is set separately.\"\n```"}, "fcmosxh": {"author": "ji99", "upvotes": 11, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/ei02j1/comment/fcmosxh) \n**Votes:** 11\n\nHere's how I open pdf files in mupdf with the colors of my current emacs theme:\n\n```elisp\n(defun mupdf-reader (file)\n (let* ((background (face-attribute 'default :background))\n (foreground (face-attribute 'default :foreground))\n ;; if it's a hex code then remove the # prefix\n ;; if it's a color name then convert it to hex code\n (backg-color (if (equal (substring background 0 1) \"#\")\n (substring background 1)\n (substring (color-name-to-hex background) 1)))\n (font-color (if (equal (substring foreground 0 1) \"#\")\n (substring foreground 1)\n (substring (color-name-to-hex foreground) 1))))\n (make-process\n :name \"book-reader\"\n :connection-type 'pipe\n :command (list \"mupdf-gl\" \"-B\" font-color \"-C\" backg-color file))))\n\n```\nThe above function depends on `color-name-to-hex`, which basically combines two inbuilt functions:\n\n```elisp\n(defun color-name-to-hex (name)\n (let ((rgb (color-name-to-rgb name)))\n (when rgb\n (setcdr (last rgb) '(2))\n (apply 'color-rgb-to-hex rgb))))\n\n```\nHere's a simple handler function to open all pdf and epub files from emacs with mupdf:\n\n```elisp\n(defun mupdf-file-handler (operation &rest args)\n (mupdf-reader (car args))\n (kill-buffer nil)\n ;; the error here is to avoid a bug that tries to\n ;; match the true filename with the deleted buffer\n (error \"\"))\n\n```\nAdd the magic filenames to init.el so that emacs will know when to use the handler:\n\n```elisp\n(put 'mupdf-file-handler 'safe-magic t)\n(put 'mupdf-file-handler 'operations '(insert-file-contents))\n(add-to-list 'file-name-handler-alist '(\"\\\\(\\\\.\\\\(?:epub\\\\|pdf\\\\)\\\\)$\" . mupdf-file-handler))\n```"}, "fc1u840": {"author": "mullikine", "upvotes": 14, "body": "## u/mullikine [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fc1u840) \n**Votes:** 14\n\nMaking your own hooks using advice. So a hook doesn't exist where you'd like to be hooking into? You can use advice to create a hook.\n\n```elisp\n(defvar eww-restore-history-after-hook '())\n(defun eww-restore-history-after-advice (&rest args)\n (run-hooks 'eww-restore-history-after-hook))\n(advice-add 'eww-restore-history :after 'eww-restore-history-after-advice)\n(add-hook 'eww-restore-history-after-hook (lambda ()\n (interactive)\n (rename-eww-buffer-unique)) t)\n```"}, "fbxf389": {"author": "ji99", "upvotes": 9, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fbxf389) \n**Votes:** 9\n\nUpdate your hosts file to block internet ads with this function:\n\n```elisp\n(defun update-hosts-file ()\n (interactive)\n ;; make a backup in case something goes wrong\n (copy-file \"/etc/hosts\" \"/tmp/\" t)\n (let ((coding-system-for-write 'raw-text-unix))\n (with-temp-file \"/sudo:root@localhost:/etc/hosts\"\n (insert-file-contents \"/etc/hosts\")\n (goto-char (point-min))\n ;; This \"if block\" allows you to keep your custom entries untouched\n (if (re-search-forward \"^# This hosts file is\" nil t)\n (progn\n (goto-char (line-beginning-position))\n (delete-region (point)(point-max)))\n (goto-char (point-max)))\n ;; get the updated list\n (insert\n (with-current-buffer\n (url-retrieve-synchronously \"https://someonewhocares.org/hosts/hosts\" t t)\n (goto-char (point-min))\n (re-search-forward \"^$\")\n (delete-region (point) (point-min))\n (buffer-string))))))\n```"}, "fbyevye": {"author": "human_banana", "upvotes": 11, "body": "## u/human_banana [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/eeyhdz/comment/fbyevye) \n**Votes:** 11\n\nHave multiple machines where some things are available and other aren't?\n\n`when-available` takes a function name and if it exists, executes the rest.\n\n```elisp\n(defmacro when-available (func cmd)\n \"Execute CMD if FUNC exists as a function.\"\n `(when (fboundp ,func) ,cmd))\n\n```\nSo you can deal with different environments.\n\nI mostly use this for things that are nice to have, but aren't required and don't need to be installed if they aren't already."}, "fadjl3w": {"author": "MCHerb", "upvotes": 14, "body": "## u/MCHerb [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/e8nv40/comment/fadjl3w) \n**Votes:** 14\n\nA narrowing toggle that does what I need most of the time so a single key can do all narrowing and un-narrowing.\n\n```elisp\n(defun narrow-dwim ()\n \"Toggle narrowing.\"\n (interactive)\n (cond ((region-active-p)\n ;; If region is highlighted, narrow to that\n (call-interactively #'narrow-to-region)\n (deactivate-mark t))\n ((buffer-narrowed-p)\n ;; Otherwise widen if narrowed\n (widen))\n ((derived-mode-p 'org-mode)\n (call-interactively #'org-narrow-to-subtree))\n (t\n (message \"Do not know what to narrow to.\")\n (call-interactively #'narrow-to-defun))))\n```"}, "fadilfw": {"author": "ji99", "upvotes": 8, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/e8nv40/comment/fadilfw) \n**Votes:** 8\n\nI switched to exwm two days ago (even though I was satisfied with dwm) and I'm liking it so far because it's so good to have a consistent workflow environment.\n\nInitially I started with using workspaces and managing X applications to automatically start in different workspaces but now I'm using a single workspace with winner mode and save window configuration (when the view I want is a few undos away).\n\nI had to convert a few bash scripts I regularly used to elisp but that was easy and fun.\n\nHere's one I wrote for youtube-dl, which I can be run from qutebrowser with a keybinding in config.py. You can choose your desired format using ivy (best format by default, or a combination of formats can be specified with \"video+audio\" numbers manually). You have to supply it a link from qutebrowser or another script, otherwise it uses the link in your clipboard.\n\nIn qutebrowser:\n\n\tconfig.bind(',y', 'hint links spawn emacsclient -n -e \"(ivy-youtube-dl \\\\\"{hint-url}\\\\\")\"')\n\tconfig.bind(',Y', 'spawn emacsclient -n -e \"(ivy-youtube-dl \\\\\"{url}\\\\\")\"')\n\nIn emacs:\n\n\t(defun ivy-youtube-dl (&optional link)\n\t (interactive)\n\t (let ((link (or link (current-kill 0)))\n\t\t(buffer (generate-new-buffer \"*ytd-formats*\")))\n\t (make-process :name \"ytd-formats\"\n\t\t\t :buffer buffer\n\t\t\t :command (list \"youtube-dl\" \"--list-formats\" link)\n\t\t\t :connection-type 'pipe\n\t\t\t :sentinel `(lambda (p e)\n\t\t\t\t (set-buffer ',buffer)\n\t\t\t\t (goto-char (point-min))\n\t\t\t\t (unless (search-forward \"format code\" nil t)\n\t\t\t\t\t (kill-buffer)\n\t\t\t\t\t (error \"url not supported\"))\n\t\t\t\t (forward-line 1)\n\t\t\t\t (let (list)\n\t\t\t\t\t (while (not (eobp))\n\t\t\t\t\t (setq list (cons\n\t\t\t\t\t\t (split-string\n\t\t\t\t\t\t\t(buffer-substring-no-properties\n\t\t\t\t\t\t\t (point)\n\t\t\t\t\t\t\t (point-at-eol)) \"\\n\" t nil)\n\t\t\t\t\t\t list))\n\t\t\t\t\t (forward-line 1))\n\t\t\t\t\t (setq list (nreverse list))\n\t\t\t\t\t (kill-buffer \"*ytd-formats*\")\n\t\t\t\t\t (ivy-read \"youtube-dl formats (vid+aud): \" list\n\t\t\t\t\t\t :action (lambda (x)\n\t\t\t\t\t\t\t (youtube-dl\n\t\t\t\t\t\t\t (substring-no-properties\n\t\t\t\t\t\t\t (format \"%s\" x)\n\t\t\t\t\t\t\t (if (string-match \"(\" (format \"%s\" x))\n\t\t\t\t\t\t\t\t (match-end 0)\n\t\t\t\t\t\t\t\t nil)\n\t\t\t\t\t\t\t (string-match \"[[:space:]]\" (format \"%s\" x))) ',link))\n\t\t\t\t\t\t :sort nil\n\t\t\t\t\t\t :re-builder #'regexp-quote\n\t\t\t\t\t\t :preselect \"best\"))))))\n\n\t(defun youtube-dl (fmt link)\n\t (let ((buffer (generate-new-buffer \"*youtube-dl*\")))\n\t (with-current-buffer buffer\n\t (ansi-color-for-comint-mode-on)\n\t (comint-mode))\n\t (make-process :name \"youtube-dl\"\n\t\t\t :buffer buffer\n\t\t\t :command (list \"youtube-dl\" \"--flat-playlist\" \"--format\" fmt link)\n\t\t\t :connection-type 'pty\n\t\t\t :filter 'comint-output-filter\n\t\t\t :sentinal (lambda (p e) (message \"Process %s %s\" p (replace-regexp-in-string \"\\n\\\\'\" \"\" e))))))\n\n\nAnd this one for downloading files with aria2c (which can download torrents and magnet links in addition to regular files). This function takes a link from another function otherwise uses your clipboard. Can be easily bound with qutebrowser like the above function.\n\n\t(defun download-with-aria2c (&optional link)\n\t (interactive)\n\t (let ((link (or link (current-kill 0)))\n\t\t(buffer (generate-new-buffer \"*aria2c*\")))\n\t (with-current-buffer buffer\n\t (ansi-color-for-comint-mode-on)\n\t (comint-mode))\n\t (make-process :name \"aria2c\"\n\t\t\t :connection-type 'pty\n\t\t\t :buffer buffer\n\t\t\t :command (list \"aria2c\" link)\n\t\t\t :filter 'comint-output-filter\n\t\t\t :sentinel (lambda (p e)\n\t\t\t\t (make-process :name \"notify\"\n\t\t\t\t\t\t :connection-type 'pipe\n\t\t\t\t\t\t :command (list \"notify-send\" (format \"%s %s\" p e) \"download complete\"))\n\t\t\t\t (message \"Process %s %s\" p (replace-regexp-in-string \"\\n\\\\'\" \"\" e))))))"}, "f9jp341": {"author": "gausby", "upvotes": 33, "body": "## u/gausby [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/e5dzv6/comment/f9jp341) \n**Votes:** 33\n\nShouldn't it be `/etc/tips/trick` ?\n\n(\u2026I'll show myself out)"}, "f9k6yyf": {"author": "thehaas", "upvotes": 21, "body": "## u/thehaas [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/e5dzv6/comment/f9k6yyf) \n**Votes:** 21\n\nAfter using Emacs for maybe 10 years I finally started using registers and I really should have started earlier. For those who don't know:\n\n​\n\n* Highlight text and C-x r s to save to register \n* C-x r i to put the contents of the register at the cursor point. The text is still there -- use it over and over again\n\nIt seems like quite a few keystrokes but it's really not. Of course you can re-assign them to other keys if you don't like the defaults."}, "f81dslh": {"author": "unbelievable_sc2", "upvotes": 28, "body": "## u/unbelievable_sc2 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f81dslh) \n**Votes:** 28\n\nI often use the compile feature to compile and run my projects to see the results in the compilation buffer. This works well unless you are waiting for user input in your terminal. I recently found out that you can invoke the compile with an additional non nil value to start compilation in comint-mode which allows for user input! \nThe drawback is, that you then no longer can press q to close the window or g to recompile. Because of that I added a simple lambda, that switches to compilation-mode to the compilation-finish-functions. So I can give input while compiling and running, and after compilation I can close the window as usual with q."}, "f8978oj": {"author": "itistheblurstoftimes", "upvotes": 10, "body": "## u/itistheblurstoftimes [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f8978oj) \n**Votes:** 10\n\nI just started using mu4e and wanted to have some visual indication of which account was associated with each email. Did this quickly but it seems to work well. This is akin to what K9 mail does on android.\n\nThe names \"account1\" refer to the folders in your Maildir for each account, i.e., \\~/Maildir/account1\n\n​\n\n```elisp\n(setq x-mu4e-account-colors '((\"account1\" . \"orange\")\n\t\t\t (\"account2\" . \"red\")\n\t\t\t (\"account3\" . \"blue\")))\n \n(setq x-mu4e-account-colors-prefix \" \")\n \n(defun x-mu4e-header-colors (msg line)\n \"Add a small color block to headers view indicating the account for each email\"\n (let* ((maildir (nth 1 (s-split \"/\" (plist-get msg :maildir))))\n (color (cdr (assoc maildir x-mu4e-account-colors))))\n (setq line (concat x-mu4e-account-colors-prefix line))\n (put-text-property 0 (- (length x-mu4e-account-colors-prefix) 2) 'face `(:background ,color) line)\n line))\n \n(add-to-list 'mu4e~headers-line-handler-functions 'x-mu4e-header-colors t)\n```"}, "f848ctb": {"author": "ji99", "upvotes": 10, "body": "## u/ji99 [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/dyhkcd/comment/f848ctb) \n**Votes:** 10\n\nA simple ivy function to play soma.fm with mpv in emacs:\n\n```elisp\n(defun launcher-somafm ()\n (interactive)\n (let ((stations\n\t '((\"BAGeL Radio: What alternative rock radio should sound like. [explicit]\"\n\t . \"http://somafm.com/bagel32.pls\")\n\t (\"Beat Blender: A late night blend of deep-house and downtempo chill.\"\n\t . \"http://somafm.com/beatblender32.pls\")\n\t (\"Black Rock FM: From the Playa to the world, for the annual Burning Man festival.\"\n\t . \"http://somafm.com/brfm32.pls\")\n\t (\"Boot Liquor: Americana Roots music for Cowhands, Cowpokes and Cowtippers\"\n\t . \"http://somafm.com/bootliquor32.pls\")\n\t (\"Christmas Lounge: Chilled holiday grooves and classic winter lounge tracks. (Kid and Parent safe!)\"\n\t . \"http://somafm.com/christmas32.pls\")\n\t (\"Christmas Rocks!: Have your self an indie/alternative holiday season!\"\n\t . \"http://somafm.com/xmasrocks32.pls\")\n\t (\"Cliqhop idm: Blips'n'beeps backed mostly w/beats. Intelligent Dance Music.\"\n\t . \"http://somafm.com/cliqhop32.pls\")\n\t (\"Covers: Just covers. Songs you know by artists you don't. We've got you covered.\"\n\t . \"http://somafm.com/covers32.pls\")\n\t (\"DEF CON Radio: Music for Hacking. The DEF CON Year-Round Channel.\"\n\t . \"http://somafm.com/defcon32.pls\")\n\t (\"Deep Space One: Deep ambient electronic, experimental and space music. For inner and outer space exploration.\"\n\t . \"http://somafm.com/deepspaceone32.pls\")\n\t (\"Digitalis: Digitally affected analog rock to calm the agitated heart.\"\n\t . \"http://somafm.com/digitalis32.pls\")\n\t (\"Doomed (Special): For Halloween: Dark industrial/ambient music for tortured souls.\"\n\t . \"http://somafm.com/specials32.pls\")\n\t (\"Drone Zone: Served best chilled, safe with most medications. Atmospheric textures with minimal beats.\"\n\t . \"http://somafm.com/dronezone32.pls\")\n\t (\"Dub Step Beyond: Dubstep, Dub and Deep Bass. May damage speakers at high volume.\"\n\t . \"http://somafm.com/dubstep32.pls\")\n\t (\"Fluid: Drown in the electronic sound of instrumental hiphop, future soul and liquid trap.\"\n\t . \"http://somafm.com/fluid32.pls\")\n\t (\"Folk Forward: Indie Folk, Alt-folk and the occasional folk classics.\"\n\t . \"http://somafm.com/folkfwd32.pls\")\n\t (\"Groove Salad: A nicely chilled plate of ambient/downtempo beats and grooves.\"\n\t . \"http://somafm.com/groovesalad32.pls\")\n\t (\"Groove Salad Classic: The classic (early 2000s) version of Groove Salad\"\n\t . \"http://somafm.com/gsclassic32.pls\")\n\t (\"Illinois Street Lounge: Classic bachelor pad, playful exotica and vintage music of tomorrow.\"\n\t . \"http://somafm.com/illstreet32.pls\")\n\t (\"Indie Pop Rocks!: New and classic favorite indie pop tracks.\"\n\t . \"http://somafm.com/indiepop32.pls\")\n\t (\"Jolly Ol' Soul: Where we cut right to the soul of the season.\"\n\t . \"http://somafm.com/jollysoul32.pls\")\n\t (\"Left Coast 70s: Mellow album rock from the Seventies. Yacht not required.\"\n\t . \"http://somafm.com/seventies32.pls\")\n\t (\"Lush: Sensuous and mellow vocals, mostly female, with an electronic influence.\"\n\t . \"http://somafm.com/lush32.pls\")\n\t (\"Metal Detector: From black to doom, prog to sludge, thrash to post, stoner to crossover, punk to industrial.\"\n\t . \"http://somafm.com/metal32.pls\")\n\t (\"Mission Control: Celebrating NASA and Space Explorers everywhere.\"\n\t . \"http://somafm.com/missioncontrol32.pls\")\n\t (\"PopTron: Electropop and indie dance rock with sparkle and pop.\"\n\t . \"http://somafm.com/poptron32.pls\")\n\t (\"Secret Agent: The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!\"\n\t . \"http://somafm.com/secretagent32.pls\")\n\t (\"Seven Inch Soul: Vintage soul tracks from the original 45 RPM vinyl.\"\n\t . \"http://somafm.com/7soul32.pls\")\n\t (\"SF 10-33: Ambient music mixed with the sounds of San Francisco public safety radio traffic.\"\n\t . \"http://somafm.com/sf103332.pls\")\n\t (\"Sonic Universe: Transcending the world of jazz with eclectic, avant-garde takes on tradition.\"\n\t . \"http://somafm.com/sonicuniverse32.pls\")\n\t (\"Space Station Soma: Tune in, turn on, space out. Spaced-out ambient and mid-tempo electronica.\"\n\t . \"http://somafm.com/spacestation32.pls\")\n\t (\"Suburbs of Goa: Desi-influenced Asian world beats and beyond.\"\n\t . \"http://somafm.com/suburbsofgoa32.pls\")\n\t (\"The Trip: Progressive house / trance. Tip top tunes.\"\n\t . \"http://somafm.com/thetrip32.pls\")\n\t (\"ThistleRadio: Exploring music from Celtic roots and branches\"\n\t . \"http://somafm.com/thistle32.pls\")\n\t (\"Underground 80s: Early 80s UK Synthpop and a bit of New Wave.\"\n\t . \"http://somafm.com/u80s32.pls\")\n\t (\"Xmas in Frisko: SomaFM's wacky and eclectic holiday mix. Not for the easily offended.\"\n\t . \"http://somafm.com/xmasinfrisko32.pls\"))))\n (ivy-read \"soma.fm \" (mapcar 'car stations)\n\t :re-builder #'regexp-quote\n\t :action (lambda (x) (save-window-excursion\n\t\t\t\t (async-shell-command (concat \"mpv \" (cdr (assoc x stations)))\n\t\t\t\t\t\t\t \"*soma.fm*\"))))))\n \n(defun kill-soma ()\n (interactive)\n (kill-process \"*soma.fm*\")\n (sleep-for 2)\n (kill-buffer \"*soma.fm*\"))\n```"}, "f6ncyes": {"author": "clemera", "upvotes": 12, "body": "## u/clemera [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6ncyes) \n**Votes:** 12\n\n\n\n```elisp\nemacs --batch -l cl-lib --eval \"(cl-loop (print (eval (read))))\"\n```"}, "f6ys5ae": {"author": "clemera", "upvotes": 8, "body": "## u/clemera [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6ys5ae) \n**Votes:** 8\n\nMy fav org-bullets config, looks nice and you immediately know which headline level you have:\n\n```elisp\n (setq org-bullets-bullet-list\n '(\"\u24ea\" \"\u2460\" \"\u2461\" \"\u2462\" \"\u2463\" \"\u2464\" \"\u2465\" \"\u2466\" \"\u2467\" \"\u2468\"))\n```"}, "f6mm087": {"author": "jalihal", "upvotes": 8, "body": "## u/jalihal [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/drw8i3/comment/f6mm087) \n**Votes:** 8\n\nTIL about `indent-rigidly` bound to `C-x TAB`. Very useful when indenting copy-pasted python code at different levels!"}, "f5pgfu3": {"author": "laralex", "upvotes": 15, "body": "## u/laralex [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5pgfu3) \n**Votes:** 15\n\nA small basic thing, but once I'd discovered it, I started using dired.\n```C-x C-j``` is most likely bound to ```dired-jump```, and this function opens dired for this window's file, without promting for directory (and this prompt was an issue for my workflow when using ```C-x d```). That makes finding and switching files just as convenient as in OS GUI. I've also bound a few keys when in dired mode (I find them decent):\n\n```a``` - prompt a name and create empty file\n\n```d``` - prompt a name and create empty dir\n\n```u``` - go to parent dir (the key is a mnemonic to \"go Up in directory tree)\n\n```j``` - if it's a dir go into it, otherwise find this file (key is near to 'u' so jumping up and down is not a big deal with one hand, also the 'j' is the easiest key for me as a touchtyper) \n\n```n```/```p``` - move one entry down/up, which resembles ```C-n```/```C-p```"}, "f5qf3jw": {"author": "???", "upvotes": 9, "body": "## u/??? [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5qf3jw) \n**Votes:** 9\n\n[deleted]"}, "f5oz3bp": {"author": "primitiveinds", "upvotes": 10, "body": "## u/primitiveinds [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/domrl6/comment/f5oz3bp) \n**Votes:** 10\n\nThis is one of the things that I'm sure exists somewhere but I can't find it so I wrote a few lines. I work in a big monorepo and depend on `projectile` for navigation by adding `.projectile` files here and there, in subdirectories that I consider \"projects\". However there are some directories that e.g. contain libraries. If I want to work on all of them for e.g. refactoring, going into a project then locks me in that (I mean `projectile-find-file`) and I have to manually go into another project. Also I flood my projectile cache with little things that I might not use a lot. What I did was add some logic to create temporary root directories for projects, where I can then use `counsel-file-jump` and `counsel-ag`. I have some keybindings and with a prefix argument I am prompted to change the temp root. Here's the code:\n```elisp\n(defvar my/temp-project-root nil)\n\n(defun my/get-or-set-temp-root (reset)\n (let* ((reset-root (if reset my/temp-project-root nil))\n (root\n (if (or reset\n (null my/temp-project-root)\n (not (file-directory-p my/temp-project-root)))\n (read-directory-name \"Temp root dir: \" reset-root)\n my/temp-project-root)))\n(setq my/temp-project-root root)))\n\n(defun my/counsel-file-jump-temp-root (reset)\n (interactive \"P\")\n (my/get-or-set-temp-root reset)\n (let ((current-prefix-arg nil))\n(counsel-file-jump nil my/temp-project-root)))\n\n(defun my/counsel-ag-temp-root (reset)\n (interactive \"P\")\n (my/get-or-set-temp-root reset)\n (let ((current-prefix-arg nil))\n(counsel-ag \"\" my/temp-project-root)))\n```\nAlso `counsel-file-jump` is so good"}, "f65iky4": {"author": "c17g", "upvotes": 9, "body": "## u/c17g [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/domrl6/comment/f65iky4) \n**Votes:** 9\n\nI just found out the great variable `org-extend-today-until`. Basically it defines when your day really ends. If you sleep late, check it out.\n\nGoodbye to the days using `M-x org-todo-yesterday` at midnight, clocking off items before sleep.."}, "f4wdyaf": {"author": "ProfessorSexyTime", "upvotes": 12, "body": "## u/ProfessorSexyTime [\ud83d\udd17](https://www.reddit.com/r/emacs/comments/dlethf/comment/f4wdyaf) \n**Votes:** 12\n\nI feel like a lot of us average Emacs users miss out on a lot of functionality Emacs provides outside of the box. So some things you might find interesting:\n\n#### [Registers](https://www.gnu.org/software/emacs/manual/html_node/emacs/Registers.html)\n\nSomeone posted this in a weekly tips/trick/etc thread a few weeks ago, but I thought I'd mention it again.\n\nRegisters just let you store *things* in them. This can be\n\n- Cursor positions in buffers (`C-x r SPC [name you want to give the register]`)\n- Text in a region (`C-x r s [name you want to give the register]`)\n- Rectangles (`C-x r r [name you want to give the register]`)\n- State of windows in frames (`C-x r w [name you want to give the register]`)\n- State of all frames and their windows (`C-x r f [name you want to give the register]`)\n- Numbers (`C-x r n [name you want to give the register]`) and you can increment those numbers (`C-x r + [name of register you want to increment`]\n- Whole file names (it's not bound, but you can do `M-: (set-register ?z '(file . \"/some_file/somewhere/some_text.txt\"))`)\n- Keyboard macros instead of saving them (` C-x C-k x [name you want to give the register]`)\n\nYou can insert text, registers, or numbers with `C-x r i [name of register with stuff to insert]`. You can also append or prepend stuff to registers with `append-to-register` or `prepend-to-register`.\n\n`C-x r j [name of register]` can jump to a point, restore a window or frame configuration, or visit a file with a specific name.\n\nYou could always use [bookmarks](https://www.gnu.org/software/emacs/manual/html_node/emacs/Bookmarks.html#Bookmarks).\n\nOne thing I would like to do is automatically give registers names, say like a1, a2, et cetera then b1, b2 et cetera, and then A1, A2 and yaddah yaddah.\n\nI'm an idiot though and generating that sort of collection escapes me a bit.\n\nI'd rather not do just\n\n```elisp\n(loop n from 0 to 99\n collect (concat \"a\" n))\n\n```\nfor every alphabetical character. Then it'd be a matter of going through those collections for every register created and making sure they use different names. Was wondering if I could get some help.\n\n#### [Isearch](https://www.emacswiki.org/emacs/IncrementalSearch) and [Query Replace](https://www.gnu.org/software/emacs/manual/html_node/emacs/Query-Replace.html)\n\nNot much to say here, just that I might recommend that one go over the default keys for [isearch](https://www.emacswiki.org/emacs/IncrementalSearch#toc2) and query-replace.\n\nAlso I would switch `C-s` and `C-r` to use `isearch-forward-regex` and `isearch-backward-regex`, and `M-%` to use `query-replace-regex` because you can disable the use of regex for both. You can even start a query-replace from isearch with `M-%` or `C-M-%`.\n\n#### `event-apply-*` Keys\n\nI don't really know what I can use these keys for, but with which-key you can press `C-x @` to see them. They allow you to apply control, shift, alt, meta, super, or hyper keys."}} \ No newline at end of file