Emacs

2592 readers
1 users here now

Our infinitely powerful editor.

founded 5 years ago
MODERATORS
126
127
8
submitted 1 year ago* (last edited 1 year ago) by dsemy@lemm.ee to c/emacs@lemmy.ml
 
 

I merged a new source for EMMS yesterday (a backend providing commands like 'emms-add-file' and 'emms-play-file') which reads a beets (https://beets.io) library database using Emacs' built-in SQLite support (beets is a command line program which manages your music library and automatically performs operations like tagging and converting music files; it keeps an SQLite database of tracks).

Since beets library databases already contain metadata about the tracks, this source skips running the default track info initialization function (other track init functions do run though).

On my PC (which is fairly powerful), loading ~1500 tracks (my personal library) into the EMMS cache (including their metadata) takes few minutes, during which Emacs is very annoying to use; this process takes under a second using the beets source.

Another nice feature is the ability to interactively filter chosen tracks (by passing a prefix argument to any beets source command). The filtering is done in two steps:

  1. Choose metadata types to filter by (actually columns in the beets database).

  2. For each metadata type (column) chosen, choose between unique values which appear in that column and which don't correspond only to tracks which have already been filtered by a previous choice.

Both steps use 'completing-read-multiple' (and only allow valid choices).

The source should require no configuration (only tested on Linux though) provided you haven't changed the location of the beets library database, and the source commands are autoloaded.

The source should be available in EMMS 19 (the next version, which should be released soon).

128
129
18
lem 0.19 update (codeberg.org)
submitted 1 year ago* (last edited 1 year ago) by blawsybogsy@lemmy.ml to c/emacs@lemmy.ml
 
 
  • implement overview (mixed comments + posts) for user views
  • implement unified inbox (mixed replies, mentions, private messages)
  • add communities moderated to user view
  • add sort/listing widgets to browse communities for nice sorting feedback
  • add search current user command
  • add search current community command

I thought it might be nice to add drop-down sort/listing widgets to the top of all feed-based views, roughly similar to the web client, but it seems that the emacs widget library doesn't allow placing multiple menu widgets on the same line. :/

EDIT: turns out it's possible, so i'll add them to the main views.

130
 
 

Some Emacs Lisp to help me populate random information into my Campaign Status document. This delves into the org-element-map function and some querying of information to pick the right elements.

131
 
 

additions:

  • pagination for inbox views (replies, mentions, pms)
  • create communities (basic, no images yet)
  • delete communities (completing)
  • fix view-user-at-point
  • display community's restricted/nsfw status
  • fix next/prev on user search results
132
7
submitted 1 year ago* (last edited 1 year ago) by blawsybogsy@lemmy.ml to c/emacs@lemmy.ml
 
 

I recently updated lem.el to 0.12.

The release makes encrypted tokens optional for easier use. If you update and find you can't load lem.el, delete ~/.emacs.d/lem.plstore and log in again. If you want your auth tokens to be encrypted, set lem-encrypt-auth-tokens to non-nil. You'll also need to set plstore-encrypt-to to a GPG key of yours.

133
134
 
 

Hi everyone! I'm looking for help and learning opportunity :) I am improving my emacs configuration following some tutorials, and right now I'm missing something important to understand how keybindings in emacs work. I've read Mickey Petersen blog post about this subject (https://www.masteringemacs.org/article/mastering-key-bindings-emacs), but I can't apply it to my situation.

What I want to achieve

I use general, use-package and evil. I want to use evil keybindings in undo-tree-visualizer-mode to jump between nodes and branches using "j", "k", "h", "l" keys in normal state.

My evil and general config

(use-package evil
  :init      ;; tweak evil's configuration before loading it
  (setq evil-want-integration t) ;; This is optional since it's already set to t by default.
  (setq evil-want-keybinding nil)
  (setq evil-vsplit-window-right t)
  (setq evil-split-window-below t)
  (setq evil-want-C-u-scroll t)
  (setq evil-want-C-i-jump nil)
  (setq evil-respect-visual-line-mode t)
  (setq evil-undo-system 'undo-tree)
  (evil-mode))

(use-package general
  :diminish
  :config
  (general-evil-setup)

What I have tried

  1. Defining keybindings with evil
(with-eval-after-load 'evil-maps
(evil-define-key 'normal undo-tree-visualizer-mode-map (kbd "k") 'undo-tree-visulize-undo)
(evil-define-key 'normal undo-tree-visualizer-mode-map (kbd "j") 'undo-tree-visulize-redo)
(evil-define-key 'normal undo-tree-visualizer-mode-map (kbd "h") 'undo-tree-visulize-switch-branch-left)
(evil-define-key 'normal undo-tree-visualizer-mode-map (kbd "l")
  1. use-package :bind
(use-package undo-tree
  :bind(:map undo-tree-visualizer-mode-map
             ("k" . undo-tree-visualize-undo)
             ("j" . undo-tree-visualize-redo)
             ("h" . undo-tree-visualize-switch-branch-left)
             ("l" . undo-tree-visualize-switch-branch-right))
  :init
  (global-undo-tree-mode 1))
  1. hook-mode
(use-package undo-tree     
  :init     (global-undo-tree-mode 1)     
  :config     
  (add-hook 'udno-tree-visualizer-hook
              (lambda()
              (add-to-list 'evil-previous-visual-line 'undo-tree-visualize-redo))))

I don't get any errors with these solutions, but still it doesn't remap keys as I wish to.

What I am missing here? What is the best approach to rebind these keys to undo-tree-visualizer-mode-map?

Will greatly appreciate help in understanding what I am doing wrong :)

135
136
 
 

https://protesilaos.com/emacs/ef-themes-pictures

Theme in picture is ef-summer. I love these so much. They're a breath of fresh air among the other techy-cyber-hacker themes, yknow?

137
26
submitted 2 years ago* (last edited 2 years ago) by blawsybogsy@lemmy.ml to c/emacs@lemmy.ml
 
 

updated lem.el lemmy client for emacs.

  • added an action/response/update display system for direct feedback upon executing an action (feature, save, delete, like, create, edit item).
  • added a completing-read system
  • added un/block instances, communities, and users functions.
  • various other fixes.
138
6
Emacs Meetup at CCC (graz.social)
submitted 2 years ago* (last edited 2 years ago) by cabhan@discuss.tchncs.de to c/emacs@lemmy.ml
 
 

If any of you are at the Chaos Communication Congress, we're having an impromptu Emacs and Org mode meetup today at 16:00 (in 40 minutes).

Maybe see some of you there :)

139
 
 

cross-posted from: https://lemmy.ml/post/9648279

I would like to premise this with the following:

  • The best approach is probably just testing out each and every editor that interests me until I've found what works best for me.
    • However, I wonder to what degree a test as such would be representative when the likes of Emacs and (Neo)Vim are considered; both of which are known for being a life time learning process.
  • I don't literally expect Emacs or (Neo)Vim to be drop-in replacements for any IDE. Some of the most basic IDE-functions are absent by default and some (perhaps more advanced) functionality might simply not be attainable at all.
  • I am not interested in anything that remotely resembles a flame war. The community at Lemmy has so far been very kind to me; let's keep it that way ๐Ÿ˜œ.

Motivation

I've had experiences with Atom, VS Code and some of Jetbrains' IDEs like Pycharm and Rider. While I've been generally content with all of them, it leaves a bad taste in my mouth whenever I'm forced to switch IDEs because their lifetimes and/or lack of extensibility doesn't allow me to responsibly continue using them. As such, I'm interested in a long time investment that will grow as I will. Both Emacs and (Neo)Vim have passed the test of time and I honestly don't think they'll cease to exist in the upcoming decades, that's why I would love to start using either one of them.

Furthermore, Vi(m) keybindings seem to be somewhat ubiquitous and almost any IDE offers some support. As such, improving my Vi(m)-game should only net-positive my productivity (at least eventually). Also, fluency will benefit me whenever I'm remote accessing any random server as they will always have Vi(m) installed. Thankfully, this doesn't force me to use Vi(m) (or Neovim) just yet, because Emacs offers with Evil perhaps the single best Vi(m) implementation; outside of native Vi(m)*.

My setup:

  • I'm on a custom image of uBlue using their startingpoint as template. For those unaware; an oversimplification would be that it is Fedora Silverblue with some extras.
  • As such, I would like to have my developer environments local and have used Distrobox to that extent using steps similar to the ones outlined over here. But I'm not married to that specific way of utilizing local containers. So please feel free to recommend me something that's at least as good.
  • If I go for Emacs, then I will definitely rely on Evil.
  • If possible, I would like to use it for C#, Python and Rust. Furthermore, I engage in editing Bash scripts, Dockerfiles, Linux config files, texts written in Latex and/or Markdown and other files written in Nix or JSON. As both are very extensible, I don't expect any issues, but I might be wrong.

Questions:

  • First of all, does it make sense for me to only consider these two?
  • Can the split between Vim and Neovim be interpreted as the first schism and as such be a forebode for what's yet to come?
  • Google Trends suggests that Neo(Vim) is ever-popular. On the other hand; not only is Emacs relatively less popular, but its popularity seems to be slightly declining. Should this worry me regarding their long-time future? Especially considering that a thriving community is literally the lifeline for both of them.
  • For those that have used both extensively, which one do you prefer (if any) and why?
  • While I understand that the power of both of them lies primarily in how one can literally make them behave however suits their workflow best. Therefore, the use of premade configs and/or starter kits/distributions should (ideally) only be used either temporary or as a starting point. However, at this point, they provide a decent showcase of what each 'platform' has to offer. So:
140
 
 

Hello, I like emacs. But I don't like it's default keys, so I use Evil. But the defaults stay. How do I remove them? I know, that's not an easy question, but I'm a bit of a newer emacs user, and don't like the defaults. I know it's possible, I've attempted to use spacemacs, and it gives you the option to use only vi keys (I only stopped using it because I wanted to use my own config).

Thanks

141
30
submitted 2 years ago* (last edited 2 years ago) by blawsybogsy@lemmy.ml to c/emacs@lemmy.ml
 
 

did some more hacking on lem.el. 0.8 release includes:

  • rich editing of posts/comments
  • rainbow bar indentation for comment trees
  • tabulated list for communities overview
  • fixes to comment trees and many other things.

there's still lots to fix up, but its running pretty well now.

& hm i wonder is there any other overlap btw emacsers + the lemmy codebase? i'm just adding features as i work out how things work, often in an amateur ad-hoc manner...

142
 
 

did a maniac hack on the old lem.el recently, mainly for the 0.19 release. overhauled the logic of all the sorting/listing commands. they should be more rigorous and flexible to update now. various other fixes too. pushed to main, so will hit MELPA soon.

also added unified inbox for replies, mentions, and private messages, and various other minor display improvements.

143
 
 

my talk from this past EmacsConf, Programming with Steno, was featured on the Plover Blog.

I talk about what steno is (hitting multiple keys at once to send whole words).

then at 2:43 I show skeletons in action. skeletons are expansion text with structure, super useful for boilerplate code and, really, code in general

at 10:08, I show Lem.

at 13:33, I show how to use search with steno (steno adds spaces to the end, so I have to show how to deal with that)

at 16:46, I talk about the Space Cadet Keyboard (and the other modifiers, Alt, Hyper, and Super)

those are probably the most interesting parts to people here. here is a link to the video : https://www.youtube.com/watch?v=McHurKmk-rQ

144
 
 

I've been thinking of moving my personal bookkeeping to Emacs, and I found out about Beancount, which seems perfect for me. I was wondering, though, if I could (and should) use it with Org-mode and noweb like the ledger tutorial in Worg. If so, what does such a workflow look like? Can I also use capture templates to quickly record transactions?

145
 
 

I switched to Android a few weeks ago, and being an Emacs user, I immediately installed and started tweaking Emacs' new Android port (specifically the version which shares a UID with Termux, as uploaded by Po Lu to SourceForge).

Many things didn't work out of the box, but I got large parts of my setup working under Android now, so I thought I'd share some stuff since I found little to no information online about any of this.

Running programs installed through Termux

This is covered well by the FAQ on SourceForge, but it seems to give some wrong advice for users of Android 7+: Setting LD_LIBRARY_PATH on these devices likely causes failures to link some executables installed through Termux.

I'm not sure what other ramifications doing this has, but I have been able to run all Termux programs (with a single exception, git-annex) through Emacs this way. ~~To use git-annex through Emacs I run tmux on Termux, and connect to it from an Emacs terminal buffer. This could be somewhat automated using the 'am' command.~~ git-annex can be used through Emacs on Android 10+ by disabling Emacs' default behavior of running executables under system call tracing. ~~You need to ensure every directory containing executable files is read only though (this can be done through emacs using (set-file-modes DIR 320)).~~ It actually works for me without setting directories read-only (contrary to the FAQ).

'info' and 'man'

You can use Emacs' built-in viewers for info manuals and manpages by setting INFOPATH and MANPATH appropriately. When setting INFOPATH, add the directory "/assets/info" otherwise you won't be able to see Emacs' manuals.

SSH and GPG Agents

After installing GPG through Termux, set 'epg-pinentry-mode' to 'loopback' to prompt for the GPG passphrase through Emacs. The agent should start automatically, I didn't do anything special other than this.

The SSH agent is a bit more tricky - it seems to not cleanup after itself when Termux and Emacs close, and for some reason doesn't appear in the process list through Emacs when launched through Termux.

For these reasons, I decided to launch a new agent whenever I launch Emacs, and configure Termux to connect to it, or start a new agent only if the socket file doesn't exist at all:

.profile:

export SSH_AUTH_SOCK="${SSH_AUTH_SOCK:-$HOME/.ssh/auth.socket}"

if [ ! -S "$SSH_AUTH_SOCK" ]; then
    eval "$(ssh-agent -a "$SSH_AUTH_SOCK")" > /dev/null 2>&1
    echo "$SSH_AGENT_PID" > "$HOME/.ssh/pid"
fi

export SSH_AGENT_PID="${SSH_AGENT_PID:-$(cat "$HOME/.ssh/pid")}"

profile.el:

(let* ((sr (expand-file-name ".ssh" "~"))
       (ss (setenv "SSH_AUTH_SOCK" (expand-file-name "auth.socket" sr)))
       p)
  (unless (file-exists-p sr) (make-directory sr t))
  (delete-file (expand-file-name "pid" sr))
  (delete-file ss)
  (with-temp-buffer
    (call-process "ssh-agent" nil (current-buffer) nil "-a" ss)
    (goto-char (point-min))
    (forward-line)
    (search-forward "SSH_AGENT_PID=")
    (setq p (point))
    (goto-char (line-end-position))
    (search-backward "; export SSH_AGENT_PID;")
    (setenv "SSH_AGENT_PID" (buffer-substring-no-properties p (point)))
    (write-region p (point) (expand-file-name "pid" sr))))

And, as a bonus, here's a pair of functions I use to prompt for the passphrase to an SSH key through Emacs when pulling/pushing Git repositories with VC: (it tries to use a graphical askpass program by default, which isn't possible on Android)

(defun init-interfaces-ssh-add (keys)
  "Attempt to add SSH KEYS to the agent interactively."
  (dolist (key (cond ((and keys (atom keys)) (list keys))
                     ((length= keys 1) keys)
                     (t (completing-read-multiple "SSH Keys: " keys))))
    (when-let ((key (expand-file-name key "~/.ssh"))
               ((file-readable-p key)))
      (with-temp-buffer
        (insert-file-contents (concat key ".pub"))
        (call-process "ssh-add" nil (current-buffer) nil "-L")
        (unless (search-backward
                 (buffer-substring-no-properties (point) (line-end-position))
                 nil t)
          (async-shell-command (format "ssh-add %s" key)
                               (current-buffer))
          (setq key (get-buffer-process (current-buffer)))
          (while (accept-process-output key)))))))

(defun init-interfaces-vc-add-ssh-key (&rest _)
  "Ensure the SSH key of the current repository has been added to the agent."
  (when-let ((root (vc-git-root default-directory))
             (remote (vc-git-repository-url root))
             ((string-match-p "^\\(\\(rsync\\|ssh\\)://\\)?\\([[:alnum:]][[:alnum:]._-]+@\\)?[[:alnum:]+.-]+:.*" remote)))
    (init-interfaces-ssh-add
     (seq-remove (lambda (s) (string-match-p ".pub\\'" s))
                 (directory-files
                  (expand-file-name "~/.ssh") nil
                  (format ".*\\(git\\.\\)?%s.*\\'"
                          (string-trim-left
                           (cadr (string-split remote "[@:]"))
                           "git\\.")))))))

(advice-add 'vc-git--pushpull :before 'init-interfaces-vc-add-ssh-key)

Using Termux:API from Emacs

If you install Po Lu's version of Termux (which is just Termux signed with Emacs' key) you won't be able to install Termux:API from F-Droid, as it needs to be signed by the same key used to sign Termux.

You can use 'jarsigner' and 'zipalign' to resign the APK (get the keystore from Emacs' source repository under the 'java' directory, use the password 'emacs1' with alias 'Emacs keystore').

Also, when running 'emacsclient' through Termux (whether directly or through the API app) you need to ensure Termux can find the server socket.

The easiest way to do this is to set TMPDIR to Emacs' TMPDIR ("/data/data/org.gnu.emacs/cache" by default).

Here is an example of using 'termux-notification' to display an interactive media notification for EMMS:

(defun init-emms-termux-notify-stopped ()
  "Remove EMMS' Android notification."
  (start-process "init-emms-notification-remove" nil
                 "termux-notification-remove" "emms"))

(add-hook 'emms-player-stopped-hook
          #'init-emms-termux-notify-stopped)

(defun init-emms-termux-notify-killed ()
  "Remove EMMS' Android notification (synchronously)."
  (call-process "termux-notification-remove" nil nil nil "emms"))

(add-hook 'kill-emacs-hook #'init-emms-termux-notify-killed)

(defun init-emms-termux-notify-started ()
  "Display a media notification for EMMS through Termux:API."
  (let ((track (emms-playlist-current-selected-track))
        (tmp (getenv "TMPDIR"))
        (client (executable-find emacsclient-program-name)))
    (start-process "init-emms-notification" nil "termux-notification"
                   "--id" "emms" "--alert-once" "--priority" "max"
                   "--on-delete"
                   (format "TMPDIR=%s %s --eval '(emms-stop)'" tmp client)
                   "--title" (emms-track-get track 'info-title)
                   "--content" (format "%s - %s"
                                       (emms-track-get track 'info-artist)
                                       (emms-track-get track 'info-album))
                   "--image-path"
                   (if (eq (emms-track-type track) 'file)
                       (expand-file-name "cover_med.png"
                                         (file-name-directory
                                          (emms-track-name track)))
                     (expand-file-name
                      (locate-user-emacs-file "images/emms.png")))
                   "--type" "media" "--media-next"
                   (format "TMPDIR=%s %s --eval '(emms-next)'"
                           tmp client)
                   "--media-previous"
                   (format "TMPDIR=%s %s --eval '(emms-previous)'"
                           tmp client)
                   "--media-pause"
                   (format "TMPDIR=%s %s --eval '(emms-pause)'"
                           tmp client)
                   "--media-play"
                   (format "TMPDIR=%s %s --eval '(emms-pause)'"
                           tmp client))))

(add-hook 'emms-player-started-hook #'init-emms-termux-notify-started)

Performing actions with the touchscreen

First of all, the following snippet will add a toggle for the on-screen keyboard to the Menu-bar -> Options -> Show/Hide menu:

(easy-menu-add-item nil '("Options" "Show/Hide")
                    ["Keyboard" (if touch-screen-display-keyboard
                                    (setopt touch-screen-display-keyboard nil)
                                  (setopt touch-screen-display-keyboard t))
                       :visible (eq system-type 'android)
                       :style toggle
                       :selected touch-screen-display-keyboard])

Other than that, to bind commands to a touchscreen 'tap', use "mouse-1" (which is translated automatically from the touchscreen events), and for a 'hold' use "touchscreen-hold".

Prefer using ESC over Alt if possible, since Android doesn't seem to support many Alt+ combinations (for example, M-:, 'eval-expression'). This is possibly only an issue with software keyboards (I haven't tested with a hardware keyboard, I use Emacs with the Unexpected Keyboard).

Other stuff

Enable 'confirm-kill-emacs' to get a popup allowing you to prevent Emacs from being killed by the system in the background.

~~Sending mail using Emacs' built-in smtpmail package doesn't work for me for some reason; I suspect this is solvable but I haven't figured it out yet. Termux doesn't seem to include a 'sendmail' (but I haven't looked too hard) so currently I have to use a separate app to send mail from my phone (oh no).~~ This works, my configuration was wrong.

~~I made one attempt to compile Jinx' dynamic module and gave up when it failed. I highly suspect this is also possible.~~ I got around to trying Jinx again and it just worked.

Many commands which read a character fail on Android since in most situations the 'character' returned will be 'text-conversion'. Every few times I update the app I notice a new command which now works correctly, so it seems there is an ongoing effort to fix these commands. I will say though, my own package Window Commander doesn't really work on Android due to this and I tried very hard to make it work recently, so don't be surprised by issues in external packages (as most probably aren't even considering this yet).

Most of the code in this post (or code similar to it) can be found in my repository: https://git.sr.ht/~dsemy/emacs-config

146
 
 

Weird order of switch-to-buffer with packages that augment completing-read?

I'm using vertico, consult, consult embark, and orderless and it's OK but for switch-to-buffer specifically it kind of bugs me that the order isn't connected to the last-used-order (the order that list-all-buffers uses). I'm like "I just used that buffer three seconds ago and now I need to search for it?!"

Help please? ๐Ÿ™๐Ÿป โ™ฅ @emacs@lemmy.ml

147
148
 
 

Why does replace-regexp backwards work so differently?

C-u - M-x replace-regexp \w+

The - prefix arg replaces backwards but it hits one char at a time, as if the plus sign weren't there. The same replacement forwards (without the prefix arg) does hit one word at a time. What's going on, @emacs@lemmy.ml?

149
 
 

Hey gang, so I've been attempting to create a more organized way to capture daily tasks in with org-capture and I'm having trouble figuring out the best way to do so.

The structure I want is the following:

* [%] <2023-11-10>
** [ ] #[A] Some title for a task due today :work: 
     DEADLINE: <2023-11-10>

The idea would be:

  1. If a top level heading for today's date doesn't exist, create it and create a subheading
  2. If a top level heading for today's date does exist, simply just add a subheading.

At first, I had a function I tried to use that didn't work the way I wanted when I first wrote it. In retrospect, I don't know why I thought it would.

Then I tried using capture templates but that doesn't meet the requirements.

In rewriting the function I linked to previously, this is what I have so far:

      (defun org-capture::today-task-tree ()
        "Create a task tree for tasks TODO today."
        (let* ((time-string (format-time-string "<%Y-%m-%d %a>" (current-time)))
               (heading-rx
                (rx (group "[" (0+ num) "%]") (0+ space)
                    (group (literal time-string))))
               (heading (concat "[%] " time-string)))
          (goto-char (point-max))
          (if-let (pnt (re-search-backward
                        heading-rx
                        nil t))
              (progn
                (goto-char pnt)
                (end-of-line)
                (insert "\n")
                (insert "** [ ] ")
                (beginning-of-line 0))
            (goto-char (point-max))
            (or (bolp) (insert "\n"))
            (insert "* " heading "\n")
            (beginning-of-line 0)))))))

Any suggestions? I just learned out the Org Mapping API but I'm not entirely sure if that'll suit my needs.

150
 
 

I recently had to add a Mac to my zoo of hardware I'm trying to do productive work on - which prompted me to clean up and document my environment variable importer, which had grown to platform specific functions with lots of code duplication.

On both Windows and MacOS I have properly configured shells with all relevant variables - so it makes sense to query them, instead of duplicating the logic how they create that configuration into Emacs.

On Linux that'd have worked too, but I also have the relevant variables in the systemd user session, and querying that is a tiny bit faster than launching a shell.

view more: โ€น prev next โ€บ