AlecStewart1st

joined 1 year ago
[–] [email protected] 3 points 5 months ago

I'm not 100% sure what you're referring to, but having #' before a function is is to tell the reader/compiler that you're specifically referring to the function of the name that comes after it. You could just do ' and that works in Emacs Lisp, but it's more technically correct in this case to do #' as org-deadline is a function.

If that's not what you're referring to, I apologize.

4
submitted 5 months ago* (last edited 5 months ago) by [email protected] to c/[email protected]
 

Hello, friends!

So I have a complex way of capturing TODO tasks for today or week. Someone will probably tell me that there's a package out there somewhere to do this easier, but regardless I would like to figure this out.

Here's the function I use:

(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 (concat "[%] " time-string))
         (heading-rx
          (rx (group "[" (0+ num) "%]") (0+ space)
              (group (literal time-string)))))
    (goto-char (point-max))
    (if-let (pnt (re-search-backward
                  heading-rx
                  nil t))
        (goto-char pnt)
      (goto-char (point-max))
      (or (bolp) (insert "\n"))
      (insert "* " heading "\n")
      (beginning-of-line 0))
    (org-end-of-subtree)))

And here's the org-capture-templates entry:

("gt" "Today: A task for today" entry
                     (file+function
                      ,(expand-file-name "~/Documents/Org/GTD/work.org")
                      org-capture::today-task-tree)
                     (file ,(concat my-emacs-dir "capture-templates/datetree-weekly-tasks.tmplt"))
                     :empty-lines-after 1
                     :after-finalize (lambda () (org-update-statistics-cookies t)))

And here's the actual capture template that I store in a file in my config:

** [ ] [#%^{Priority}] %^{Task name}  %(funcall-interactively #'org-deadline nil (current-time)) %^g
    %? %i

Now when I'm in that file ~/Documents/Org/GTD/work.org and I run the above function with M-: org-capture::today-task-tree it works fine. An example of what the file will look like it:

* [100%] 2024-04-27 Mon
** [X] Do something important this Monday #[A] :work:
    CLOSED: 2024-04-27 Mon 12:42  DEADLINE: 2024-04-27 Mon
* [%] 2024-04-28 Tues
** [ ] Do something else that's not as important #[B] :personal: 
     DEADLINE: 2024-04-27

But for whatever reason when I run org-capture and finish the capture with C-c C-c or refile with C-c C-w I get

rx--translate-bounded-repetition: rx ‘**’ range error

Which I don't really know what that means nor how to fix it, and I can't really find anything useful via searching the internet at the moment. A possible thing to not is that I disable Org's element caching.

If you want to look at my configuration to dig around some, you can find it here and the part where my configurations for Org-Mode are here.

[–] [email protected] 1 points 6 months ago (2 children)

Plus, ZFS supports native encryption!

Hmm, I think that was the one I was wondering about. I use Gentoo, and when I was initially setting everything up on my machine, I saw there were a lot of caveats for using ZFS on linux from the Gentoo wiki entry on it. Maybe that's changed or those issues are no longer related to native encryption specifically.

[–] [email protected] 1 points 6 months ago (4 children)

Is ZFS on Linux getting better? I've heard mixed things. I use BTRFS on my daily driver, and I really like (ab)using the file compression with zstd.

[–] [email protected] 1 points 6 months ago (1 children)

If you are not too stuck on bsd

Not really. It's more out of the curious of how DragonflyBSDs HAMMER2 filesystem works. I've good things about it and ZFS on FreeBSD. ZFS on Linux I've heard is still getting up to where it is on FreeBSD.

[–] [email protected] 1 points 6 months ago (1 children)

It's the interest in how well the HAMMER2 filesystem works for everyday storage, as well as how swapcache performs. Not much besides that, plus I've generally decent experiences with Net and OpenBSD.

https://www.dragonflybsd.org/performance/

[–] [email protected] 2 points 6 months ago

If you’re gonna spend that level of money, you may as well go for an M1 Mac Mini.

I was joking. I don't feel like shelling out $600 for a starting media server.

[–] [email protected] 4 points 6 months ago (4 children)

If you really want Intel, just get an N100 or N300. Low power, Intel HW transcoding on iGPU on Linux kernels 6.3+, and can handle Jellyfin no problem.

Didn't think about that either. I'm finding I didn't give this as much thought as I should've.

You can get a minipc with everything you for $175 for a no name brand, or maybe $250 for a more well-known brand.

But why do that when I could spend +$600? 😜

[–] [email protected] 3 points 6 months ago (2 children)

Good point. So what we're really talking about then is

  • something like a raspberry pi
  • 1 or 2 hard drives for base storage
  • 1 external hard drive as a backup
[–] [email protected] 1 points 6 months ago

I mean, right now, that's definitely not on the table.

4K would be nice, obiviously, but I don't think I myself am to act nor do I want to act as the alternative to Plex for a bunch of family and friends. 😆

[–] [email protected] 2 points 6 months ago (5 children)

I'm beginning to realize I haven't looked into this as much as I should've. 😅 So for most people, with what @[email protected] has mentioned, a raspberry pi with 1 or multiple hard drives (if you really want) is a good start.

[–] [email protected] 1 points 6 months ago (2 children)

As the project mentions:

Even though there are builds available online for these platforms, they are unofficial and from a separate project. If you do encounter issues on these platforms, please ask for support in their respective support channels first.

This that project:

https://github.com/Thefrank/jellyfin-server-freebsd

[–] [email protected] 7 points 6 months ago (4 children)

Ah, okay. So, if I understand correctly, unless I'm trying to have Jellyfin do what YouTube does with offering multiple resolutions and bitrates for video, I don't need to bother with looking for a GPU that's good at video transcoding?

 

Initial Thoughts

Hello friends!

This is something that's been muddling around in my mind for a bit, in part because I now have a decent collection of DVDs, and I am starting get a digital collection of shows that are a bit hard to find. I'm also interested in the fact that there's a TubeArchivist plugin for Jellyfin, as media archival interests me and YouTube is starting to suck with Google's position on ad-blocking. It would be nice to be able to access this stuff anywhere as well, so creating a media/Jellyfin server seems like a good solution.

Thing is I'd rather have a physical server than pay a bunch of monthly fees for VPS hosting. Not knocking it of course, but on top of monthly fees I also have my skepticism about VPS hosts and if they're sharing data with people regarding my use of their service.

Completely wishful thinking setup

I'm not so much of a hardware guy as I am a software guy, funnily enough, but to give you an idea of what I would like here's my admittedly wishful thinking of what I'd like for a setup:

  • DragonflyBSD as the server OS, utilizing it's HAMMER2 filesystem and swapcache as I've heard great things about those.
  • Jellyfin, obviously.
  • NVMe SSD storage with some level of RAID.
  • Intel GPU, as I've heard they're very good at video decoding, but I've not looked into evidence of this.
  • Whatever CPU and RAM I can get good performance out of without wasting money.
  • Add it to the Wireguard network so I can watch stuff anywhere.

A few things with this:

  1. I don't know how up-to-date DragonflyBSD's dport of Jellyfin is, but maybe this is something worth contributing to.
  2. God only knows if the new Intel graphics card drivers work well on the BSDs. I know all of the BSDs basically just pull from the official Linux firmware for graphics (I think?).
  3. I'd have to figure out if any other hardware would not play well with DragonflyBSD, probably not too big of an issue but it's still something to look out for.
  4. Cost of hardware.

Wrap up

Overall it probably be just me and my wife who would use the server, mostly me. Maybe some immediate family, a few friends, maybe down the line use it for kids when we have them.

What are your recommendations?

13
submitted 8 months ago* (last edited 8 months ago) by [email protected] to c/[email protected]
 

Hey gang!

So I've used gopass for awhile now, and Emacs for longer.

I was wondering if any of you here interact with gopass via Emacs with auth-source or something similar.

The main reason I ask is because I'm wanting to finally use Emacs for other things, such as an IRC client and making more use of Magit, and even writing with 750words.

A lot of my passwords are stored with gopass, and the structure isn't always the same for stores. For instance:

| Forums
|-- Gentoo
|-- Some other forum
|
| Email Host
|--  [email protected]
|---- password
|---- recovery codes
|
| Employer Name
|-- Some program we use at work
|---- [email protected]
|
| Some app
|-- My User Name

Maybe this structure for a password store is a no-no, though it's not a big deal to move things around.

Any tips? I've seen auth-source-gopass, but that doesn't provide any interaction with selection of passwords or creation of passwords, I think.

I've look at that mentioned library some and writing an auth-source backend doesn't seem too involved, but maybe I don't necessarily have to with auth-source.

EDIT:

A potential configuration that others might use:

(require 'consult)
(require 'auth-source-pass)

(use-package pass
  :requires password-store
  :preface
  (defvar consult:pass-source
    `(:name "Passwords"
      :narrow ?<                     ;; maybe you want something else for narrow?
      :face pass-mode-directory-face ;; maybe you want to use a different face?
      :category pass
      :enabled
      ,(lambda ()
         (auth-source-pass-file-name-p auth-source-pass-filename))
      :items ,#'password-store-list)
    "Consult source for passwords with (go)pass.")

  (defun consult:pass (arg pass)
    "Stolen from Doom Emacs.
https://github.com/doomemacs/doomemacs/blob/master/modules/tools/pass/autoload/consult.el"
    (interactive
     (list current-prefix-arg
           (progn
             (require 'consult)
             (consult--read consult:pass-source
                            :prompt "(Go)Pass: "
                            :sort nil
                            :require-match t
                            :category 'pass))))
    (funcall (if arg
                 #'password-store-url
               #'password-store-copy)
             pass))
  :custom
  (password-store-executable (executable-find "gopass"))
  (auth-source-pass-filename
   (or (getenv "PASSWORD_STORE_DIR")
       (expand-file-name "~/.local/share/gopass/stores/root")))
  :config
  (auth-source-pass-enable))
 

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:

* [%] &lt;2023-11-10>
** [ ] #[A] Some title for a task due today :work: 
     DEADLINE: &lt;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 "&lt;%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.

 

Hello friends!

For awhile now I've wanted to delve into self-hosting and the first thing I thought of was ditching my VPN Provider for my own VPN solution.

I wanted to ask about the cost/benefit of each option with those of you who are more experienced.

Option One: Stick with my VPN Provider:

This is a funky case, as my VPN Provider is with Proton, and my email and VPN accounts are linked together. Since I've been with them for awhile, I have over a gigabyte of storage for emails. I rarely ever get past 400MB. The VPN is fine, occasionally I have some hiccups with speed but it overall works. I pay roughly $19.20/month for both a paid email account and the VPN service, so it's likely the second cheapest. When it comes to privacy, though, I'm not 100% sold Proton wouldn't just sell my data for no reason. Yes, they are Swiss, but that doesn't entirely reassure me.

The weird thing about this is my PiHole is decoupled from the VPN. At least in the mobile app, I see no option to use your own DNS. There's also no provided way nor really an obvious way for me to connect to all of my devices if they're all on ProtonVPN, as opposed to the other two options.

Option Two: Just use Tailscale

Personally I'd like to mess with the ACLs so probably I'd wind up with the $6/month plan. For the $18/month plan I don't really know what "Tailscale SSH" even means, as I don't know what magic they do to wrap SSH into something worth paying for. I've heard mixed things about "Tailscale Funnel."

I hear Tailscale is easy to install and there's no real extra fidgeting you'd have to do for your home network. Tailscale will also let me use my PiHole as my DNS, getting me ad-blocking from PiHole on all devices on Tailscale.

Option Three: Self-Hosted Headscale

This is one I'm interested in, but I don't know the feasibility of it. The initial idea was to get a VPS and install OpenBSD on it and make it my Headscale instance. I've installed OpenBSD before, I mostly know my way around it and I like how lightweight it is and how security focused it is. There would be more setup initially, but I don't really mind that. I do a lot of fidgeting on my Linux desktop anyway.

The main thing for this is cost. I don't really know what performance specs for a VPS I would need to reasonably have good network performance with ~10 devices, though I'm guessing I'll have to have something =<10Gbsp. So maybe $25-$30/month depending on who I buy a VPS through?

The other thing is updating stuff. I can just SSH and do all of that manually and since the VPS will be dedicated specifically to being a Headscale server, but that is still time I have to spend.

Lastly, I wouldn't have the international selection of VPN locations like with a VPN provider, just one, but it's not like I'm trying to bounce my connection from country and that's not advisable anyway.

Other options

Setting up a VPS with Wireguard myself. While I wouldn't mind it too much, Tailscale exists for a reason and it can traverse firewalls without me having to configure a bunch of devices so that's a big plus.

Running Headscale in a container on my Linux desktop, but this means my desktop would have to be on almost 24/7 and I don't know how I feel about having my VPN stuff to be sitting directly inside my home network.

What are your opinions?

 

Intro

Hello friends,

I've been hearing mixed things about Starfield, so I thought I'd try experiencing it myself. Before you ask "why aren't you running Starfield with Steam's Proton Experimental or Proton-GE" let's say I went out sailing yesterday and met a fellow legitimate sailor who was giving many people a great discount on the game. Getting back to port, the sea was rough were quite a few torrents crashing against the cliff faces that evening.

I've tried various various environment flags to get the game working, but nothing seems to work. I even made sure the installation of lutris-GE-Proton8-14 had the most up-to-date version of VKD3D. I checked the winecfg for that version of wine and it's has the correct Windows version and all of that. Manually running the game with the wine executable in that version of wine with the WINEPREFIX set to where that's install for Lutris gives me a few interesting lines.

As of note, the game does, erm, "launch" in that it creates a new window for Starfield, but it's all black and stays that way.

First interesting lines

01b8:err:setupapi:create_dest_file failed to create L"C:\\windows\\system32\\d3d12.dll" (error=80)
wine: configuration in L"/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64" has been updated.

Okay? But the configuration for wine shouldn't be updating, for one, and running the setup script provided by VKD3D-Proton gets me the following:

setup_vkd3d_proton.sh install --symlink
wine: configuration in L"/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64" has been updated.
wine: configuration in L"/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64" has been updated.
removed '/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/system32/d3d12.dll'
'/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/system32/d3d12.dll' -> '/usr/lib/vkd3d-proton/x64/d3d12.dll'
removed '/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/syswow64/d3d12.dll'
'/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/syswow64/d3d12.dll' -> '/usr/lib/vkd3d-proton/x86/d3d12.dll'
removed '/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/system32/d3d12core.dll'
'/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/system32/d3d12core.dll' -> '/usr/lib/vkd3d-proton/x64/d3d12core.dll'
removed '/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/syswow64/d3d12core.dll'
'/home/alec/.local/share/lutris/runners/wine/lutris-GE-Proton8-14-x86_64/dosdevices/c:/windows/syswow64/d3d12core.dll' -> '/usr/lib/vkd3d-proton/x86/d3d12core.dll'

So I don't know why the wine configuration is being updated again.

Next interesting lines

163756.705:01d4:031c:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.711:01d4:0314:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.755:01d4:031c:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.758:01d4:030c:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.761:01d4:0334:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.762:01d4:0334:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.768:01d4:0344:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.
163756.769:01d4:0334:fixme:vkd3d-proton:d3d12_command_signature_create: State template is required for compute, but VKD3D_CONFIG_FLAG_FORCE_COMPUTE_ROOT_PARAMETERS_PUSH_UBO is not enabled.

I don't know what this means or if it's what would cause my issue, but since it repeated several times I'm assuming it's something worth noting.

Final Thoughts and System Info

I could just be having issues due to getting that discount from my fellow sailor, but I wouldn't know. I'm very skeptical, mainly because "Your drivers are out of date" is so specific.

System Info

I'm on Gentoo, a hardened profile on Linux Kernel 6.1.46.

I'm currently on Mesa version 23.2.0_rc3.

I'm on the master/main branch for the xf86-video-amdgpu driver.

If there's anything other system info I can provide that will help me fix this, let me know.

EDIT

Add it as a Non-Steam game in Steam and it'll work there with Proton-GE 8.14. Unfortunately, given this is a Bethesda game, your performance will vary likely until 2-3 patches later. I have the following launch options, some probably aren't necessary:

PROTON_LOG=1 DXVK_ASYNC=1 WINE_FULLSCREEN_FSR=1 WINE_FULLSCREEN_FSR_STRENGTH=1 gamemodeun %command% --skip-launcher

Stay safe, fellow Linux gamers and sailors. 🫡

 

Hey friends,

I know that this is a difficult issue to have people try and solve due to how many factors there can be, but this is an odd one for me. To start, here's some info

=== Hardware ===

CPU: 12th Gen Intel(R) Core(TM) i5-12600K
GPU: AMD Radeon RX 6700 XT (navi22, LLVM 16.0.6, DRM 3.52, 6.4.8-gentoo-dist-hardened)
Memory: DDR5 5200
Monitor  Refresh Rate: 165.00 Hz

=== Software ===

Distro: Gentoo
Kernel Version: 6.4.8-gentoo-dist-hardened
Mesa Version: 23.1.5
Vulkan Version: 1.3.250
GCC Version: 13.2.0
xf86-video-amdgpu Version: Up-to-date with the master branch
Display server: X.Org
  xorg-server version: 21.1.8
  xorg-proto version: 2023.2
  
=== Proton Info ===

Have tried GE-Proton versions 7.53 to 8.11

***
Games and their commonly used Steam Launch Options
***

Enderal: Forgotten Stories (Special Edition), Steam App ID 976620
 
PROTON_LOG=1 PROTON_NO_ESYNC=1 DXVK_ASYNC=1 WINE_FULLSCREEN_FSR=1 WINE_FULLSCREEN_FSR_STRENGTH=1 WINEDLLOVERRIDES="xaudio2_7=n,b" PULSE_LATENCY_MSEC=90 =1  LD_PRELOAD="$LD_PRELOAD:/usr/\$LIB/libgamemode.so.0.0.0" gamemoderun %command%

I've also tried without DXVK_ASYNC and adding PROTON_USE_WINED3D=1

Deep Rock Galatic, Steam App ID 548430

No extra launch options. Runs on Linux, but still the weird framerate issues

This issue with low framerates only started happening recently. The earliest I recall seeing these issues was sometime 2 weeks ago. I thought it was something related to the version of GE-Proton I was using. Last time I had a problem was with using the stable version of Mesa but that was several months ago, about 9-10 months.

When I run glxgears I get around 165-170 fps, so I don't think the physical GPU is the issue. Lower-end graphical games run perfectly fine. Nothing else has been running any slower, and I don't think I've made any notable changes to my system that would cause this. Running btop when nothing is running doesn't show any processes that's taking resources it shouldn't. Neither the GPU nor CPU make more noticeable noise or anything, nor does the CPU run hotter when I first got it and started playing games.

Without doing getting really into the weeds, my best guest is something with versions of Mesa or Vulkan. But I wouldn't exactly know. I'm just basing that on the one issue that I had with an older version of Mesa those 9-10 months ago, so I could be completely wrong. I could try with the git versions of each package. I'll see if I can install those and see if anything is better and report back.

 

Hello, friends.

So I've had my Pi-Hole setup for awhile now and it's great. I'd like to get Wireguard working with it, too, so I could browse the internet without loads of ads and trackers on the go.

However, small issue. All DNS traffic is forcibly routed to my ISP. If you need some details, I made this post on the Pi-Hole userspace.

I'm in America and my ISP is Spectrum. I was wondering if there's a way I could convince technical support to allow me to use a recursive DNS for privacy/security (more-so the second of the two) purposes, or if it is even possible to convince them to do this. I don't know if there's a specific number I should contact, email I should email to, or if I just have to endure the nightmare of getting passed around by customer service one Saturday. Any recommendations would be great.

An interesting note for anyone who's ISP is Spectrum, their DNS service, at least for me, uses OpenDNS with dnsmasq-2.57. That version of dnsmasq is over 10 years old. You see if this is the case for you with

dig CHAOS TXT version.bind @192.33.4.12 +short
dig CHAOS TXT version.bind @198.97.190.53 +short

Or something similar if those IP addresses are different for you. You can see that running those commands were a part of the steps I was asked to take in that Pi-Hole userspace post.

EDIT 1:

For those interested, here's some Github gist I found that shows how to use unbound + stubby for have a recursive DNS + DNS-over-HTTPS. There's also this from the DNS Privacy Project.

EDIT 2:

I seems that initial answer from the Pi-Hole forums was correct. There's probably something that was set in the firmware for the Netgear router that prevents me from setting up my own DNS servers. However, I notice on the router there's a "router mode" option that's on, which I can probably turn off, plug in my Pi to the Netgear device and have the Pi act as my router, thus letting me be able to use it as my DNS server as well. That or just suck it up and buy only a modem, not a router + modem combo.

 

Hey gang,

So initially I had something pretty simple to have "snippets" in my Emacs config, using Skeletons and Abbrevs. I've expanded on it a little bit since then, but I'm running into an issue where the abbrev no longer expands to call the skeleton function.

Here's what I have:

    ;;;###autoload
    (defun abbrev::abbrev-table-add-props (abbrev-table props)
      "Add one or more PROPS to an existing ABBREV-TABLE.
    PROPS should be a plist of (PROP VALUE).
    Example:
    
    (:enable-function (lambda (&rest _) (do-something)))"
      (if (cddr props)
          (cl-loop for (k v) on props by #'cddr
                   unless (not (abbrev-table-p abbrev-table))
                     unless (abbrev-table-get abbrev-table k)
                      do (abbrev-table-put abbrev-table k v))
        (unless (and (not (abbrev-table-p abbrev-table))
                     (abbrev-table-get abbrev-table (car props)))
          (abbrev-table-put abbrev-table (car props) (cadr props)))))
    
    ;;;###autoload
    (defmacro def-mode-snippet (name
                                mode
                                docstring
                                &rest prompt-and-or-skeleton)
      "Create a MODES specific \"snippet\" with NAME and SKELETON.
    NAME must be valid in the Emacs Lisp naming convention.
    
    MODE must be a valid major or minor mode that is known to Emacs.
    
    Example: ‘org-mode’, ‘emacs-lisp-mode’, etc.
    
    DOCSTRING is used in the abbrev rather than the skeleton.
    
    PROMPT-AND-OR-SKELETON can be any of the following:
    1. A valid Skeleton that uses the internal `Skeleton' langauge
    2. A key/value \"pair\" that’s :prompt STRING, followed by
       a valid Skeleton that uses the internal `Skeleton' language.
    The prompt given is used by the Skeleton to prompt the user for an input.
    
    This macro makes use of `define-skeleton' and `define-abbrev' in order to
    create something similar to a code/writing snippet system, like that of
    `YASnippet'. Keep in mind that all abbreviations created are put in the abbrev
    table of MODE you passed to this macro.
    
    Example: passing ‘org-mode’ will add the abbrev to the ‘org-mode-abbrev-table’.
    
    That may or may not be something you want depending on your uses.
    If you're looking to only define an abbrev globally, see `def-global-snippet'."
      (declare (debug t)
               (doc-string 3)
               (indent defun))
      ;; TODO need to figure out how to work with lists better
      (let* ((snip-name (symbol-name `,name))
             (func-name (intern (concat (symbol-name mode) "-" snip-name "-skel")))
             (var-str (concat (symbol-name mode) "-abbrev-table"))
             (abbrev-table (intern-soft var-str))
             (has-prompt (keywordp (car prompt-and-or-skeleton)))
             (prompt (if has-prompt (cadr prompt-and-or-skeleton) nil))
             (skeleton (if (not has-prompt) prompt-and-or-skeleton (cddr prompt-and-or-skeleton)))
             ;; Not using this for now until the issue with abbrevs not expanding is solved.
             ;;(enable-fn (lambda (&rest _) (or (eq major-mode 'mode) (numberp (cl-position 'mode minor-mode-list)))))
             )
        (macroexp-progn
         `((define-skeleton ,func-name
             ,(format "%s %s %s %s." snip-name "skeleton. Defined in" var-str "abbreviaton table")
             ,prompt
             ,@skeleton)
           ,(if (not (abbrev-table-p abbrev-table))
                `(define-abbrev ,abbrev-table
                   ,snip-name
                   ',func-name)
              `(define-abbrev-table ',abbrev-table
                 '((,snip-name ',func-name))
                 ,(format "An abbrev table for %s" mode)
                 :system t
                 :case-fixed t)
              (abbrev::abbrev-table-add-props ,abbrev-table
                                              '(:system t
                                                :case-fixed t)))))))

The example I can give is the following:

(def-mode-snippet defun emacs-lisp-mode
  "defun snippet for Emacs Lisp"
  > "(defun " @ - " (" @ _ ")" \n
  > -2 "\"" @ _ "\"" \n
  > -1 @ _ ")")

And that will macro-expand to:

(progn
  (define-skeleton emacs-lisp-mode-defun-skel "defun skeleton. Defined in emacs-lisp-mode-abbrev-table abbreviaton table." nil > "(defun " @ - " (" @ _ ")" n > -2 "\"" @ _ "\"" n > -1 @ _ ")")
  (define-abbrev emacs-lisp-mode-abbrev-table "defun" 'emacs-lisp-mode-defun-skel))

Which evals fine, even though I think the n would not be valid to Skeleton, but I'm not sure.

EDIT 1: I've put up a question on The Emacs StackExchange with more details if anyone is interested. Also, if it helps looking at my full config you can view it here.

EDIT 2: Good god, I nearly lost my mind by missing this:

(define-abbrev emacs-lisp-mode-abbrev-table "defun" 'emacs-lisp-mode-defun-skel)

When defining an abbrev using a skeleton, the skeleton function should go in an define-abbrev's hook argument. As the documentation for define-abbrev says:

If HOOK is a non-nil symbol with a non-nil no-self-insert property, it can control whether the character that triggered abbrev expansion is inserted. If such a HOOK returns non-nil, the character is not inserted. If such a HOOK returns nil, then so does abbrev-insert (and expand-abbrev), as if no abbrev expansion had taken place.

view more: next ›