changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra > home / .emacs.d/ellis.el

changeset 36: 963513ec0fcd
parent: 6eef2d50b7fd
child: 964e4427f5ad
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 04 Jun 2024 18:54:01 -0400
permissions: -rw-r--r--
description: skt-templates
1 ;;; ellis.el --- Richard's custom-file -*- lexical-binding: t; -*-
2 
3 ;; Copyright (C) 2023
4 
5 ;; Author: Richard Westhaver <ellis@rwest.io>
6 
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
11 
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16 
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
19 
20 ;;; Commentary:
21 
22 ;; This is an example of what you may want to add to your custom
23 ;; config file. Feel free to rip.
24 
25 ;;; Code:
26 (require 'inbox)
27 (require 'sk)
28 ;; (require 'slime-cape)
29 (require 'sxp)
30 (require 'ulang)
31 
32 (defalias 'make #'compile)
33 
34 (setopt default-theme 'modus-vivendi-tritanopia
35  user-lab-directory (join-paths user-home-directory "lab")
36  company-source-directory (join-paths user-home-directory "comp"))
37 
38 (unless (display-graphic-p) (setq default-theme 'wheatgrass))
39 
40 (when (linux-p) (setq dired-listing-switches "-alsh"))
41 
42 (defvar emacs-config-source (join-paths company-source-directory "core/emacs"))
43 
44 ;;;###autoload
45 (defun edit-emacs-config (&optional src)
46  (interactive (list current-prefix-arg))
47  (let ((file (if src
48  (expand-file-name "default.el" emacs-config-source)
49  user-custom-file)))
50  (find-file file)))
51 
52 (keymap-set user-map "e c" #'edit-emacs-config)
53 (keymap-set emacs-lisp-mode-map "C-c C-l" #'load-file)
54 (keymap-set emacs-lisp-mode-map "C-c M-k" #'elisp-byte-compile-file)
55 (keymap-set user-map "v t" #'org-tags-view)
56 
57 (require 'paredit)
58 (add-hook 'lisp-mode-hook #'enable-paredit-mode)
59 (add-hook 'slime-editing-mode-hook #'enable-paredit-mode)
60 (repeat-mode)
61 
62 (defun remember-project ()
63  (interactive)
64  (project-remember-project (project-current))
65  project--list)
66 
67 (defun remember-lab-projects ()
68  (interactive)
69  (project-remember-projects-under user-lab-directory t))
70 
71 (defun remember-comp-projects ()
72  (interactive)
73  (project-remember-projects-under company-source-directory t))
74 
75 (keymap-global-set "C-<tab>" #'hippie-expand)
76 (keymap-set minibuffer-local-map "C-<tab>" #'hippie-expand)
77 (keymap-set ctl-x-x-map "p p" #'remember-project)
78 (keymap-set ctl-x-x-map "p l" #'remember-lab-projects)
79 
80 (add-hook 'prog-mode-hook #'skel-minor-mode)
81 (add-hook 'org-mode-hook #'skel-minor-mode)
82 (add-hook 'prog-mode-hook #'company-mode)
83 
84 (add-hook 'notmuch-message-mode-hook #'turn-on-orgtbl)
85 
86 (use-package markdown-mode :ensure t)
87 
88 (use-package ol-notmuch :ensure t)
89 
90 (use-package notmuch
91  :ensure t
92  :init
93  (setopt
94  mail-user-agent 'message-user-agent
95  smtpmail-smtp-server "smtp.gmail.com"
96  message-send-mail-function 'message-smtpmail-send-it
97  smtpmail-debug-info t
98  message-default-mail-headers "Cc: \nBcc: \n"
99  message-kill-buffer-on-exit t
100  user-mail-address "ellis@rwest.io"
101  user-full-name "Richard Westhaver"
102  notmuch-hello-sections '(notmuch-hello-insert-saved-searches
103  notmuch-hello-insert-search
104  notmuch-hello-insert-recent-searches
105  notmuch-hello-insert-alltags)
106  notmuch-show-logo nil
107  notmuch-search-oldest-first nil
108  notmuch-hello-hide-tags '("kill")
109  notmuch-saved-searches '((:name "inbox" :query "tag:inbox" :key "i")
110  (:name "unread" :query "tag:unread" :key "u")
111  (:name "new" :query "tag:new" :key "n")
112  (:name "sent" :query "tag:sent" :key "e")
113  (:name "drafts" :query "tag:draft" :key "d")
114  (:name "all mail" :query "*" :key "a")
115  (:name "todo" :query "tag:todo" :key "t")))
116  :config
117  ;;;###autoload
118  (defun notmuch-exec-offlineimap ()
119  "execute offlineimap command and tag new mail with notmuch"
120  (interactive)
121  (start-process-shell-command "offlineimap"
122  "*offlineimap*"
123  "offlineimap -o")
124  (notmuch-refresh-all-buffers))
125 
126  (defun offlineimap-get-password (host port)
127  (let* ((netrc (netrc-parse (expand-file-name "~/.netrc.gpg")))
128  (hostentry (netrc-machine netrc host port port)))
129  (when hostentry (netrc-get hostentry "password"))))
130 
131  (defun mark-as-read ()
132  "mark message as read."
133  (interactive)
134  (notmuch-search-tag '("-new" "-unread" "-inbox")))
135 
136  (defun mark-as-todo ()
137  "mark message as todo."
138  (interactive)
139  (mark-as-read)
140  (notmuch-search-tag '("-new" "-unread" "-inbox" "+todo")))
141 
142  (defun mark-as-spam ()
143  "mark message as spam."
144  (interactive)
145  (mark-as-read)
146  (notmuch-search-tag (list "+spam")))
147 
148  (keymap-set user-map "e m" #'notmuch)
149  (keymap-set user-map "e M" #'notmuch-exec-offlineimap)
150  (keymap-set notmuch-search-mode-map "S" #'mark-as-spam)
151  (keymap-set notmuch-search-mode-map "R" #'mark-as-read)
152  (keymap-set notmuch-search-mode-map "T" #'mark-as-todo))
153 
154 (use-package elfeed
155  :ensure t
156  :custom
157  elfeed-feeds
158  '(("http://threesixty360.wordpress.com/feed/" blog math)
159  ("http://www.50ply.com/atom.xml" blog dev)
160  ("http://blog.cryptographyengineering.com/feeds/posts/default" blog)
161  ("http://abstrusegoose.com/feed.xml" comic)
162  ("http://accidental-art.tumblr.com/rss" image math)
163  ("http://researchcenter.paloaltonetworks.com/unit42/feed/" security)
164  ("http://curiousprogrammer.wordpress.com/feed/" blog dev)
165  ("http://feeds.feedburner.com/amazingsuperpowers" comic)
166  ("http://amitp.blogspot.com/feeds/posts/default" blog dev)
167  ("http://pages.cs.wisc.edu/~psilord/blog/rssfeed.rss" blog)
168  ("http://www.anticscomic.com/?feed=rss2" comic)
169  ("http://feeds.feedburner.com/blogspot/TPQSS" blog dev)
170  ("http://techchrunch.com/feeds" tech news)
171  ("https://rss.nytimes.com/services/xml/rss/nyt/Technology.xml" tech news)
172  ("https://static.fsf.org/fsforg/rss/news.xml" tech news)
173  ("https://feeds.npr.org/1001/rss.xml" news)
174  ("https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=10000664" fin news)
175  ("https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=19854910" tech news)
176  ("https://search.cnbc.com/rs/search/combinedcms/view.xml?partnerId=wrss01&id=100003114" us news)
177  ("http://arxiv.org/rss/cs" cs rnd)
178  ("http://arxiv.org/rss/math" math rnd)
179  ("http://arxiv.org/rss/q-fin" q-fin rnd)
180  ("http://arxiv.org/rss/stat" stat rnd)
181  ("http://arxiv.org/rss/econ" econ rnd)
182  ;; John Wiegley
183  ("http://newartisans.com/rss.xml" dev blog)
184  ;; comp
185  ;; ("https://lab.rwest.io/comp.atom?feed_token=pHu9qwLkjy4CWJHx9rrJ" comp vc)
186  ("https://www.reddit.com/r/listentothis/.rss" music reddit)
187  ("https://www.ftc.gov/feeds/press-release-consumer-protection.xml" gov ftc)
188  ("https://api2.fcc.gov/edocs/public/api/v1/rss/" gov fcc)
189  )
190  :init
191  (defun yt-dl-it (url)
192  "Downloads the URL in an async shell"
193  (let ((default-directory "~/media/yt"))
194  (async-shell-command (format "youtube-dl %s" url))))
195 
196  (defun elfeed-youtube-dl (&optional use-generic-p)
197  "Youtube-DL link"
198  (interactive "P")
199  (let ((entries (elfeed-search-selected)))
200  (cl-loop for entry in entries
201  do (elfeed-untag entry 'unread)
202  when (elfeed-entry-link entry)
203  do (yt-dl-it it))
204  (mapc #'elfeed-search-update-entry entries)
205  (unless (use-region-p) (forward-line))))
206  :config
207  (keymap-set elfeed-search-mode-map "d" 'elfeed-youtube-dl)
208  (keymap-set user-map "e f" #'elfeed)
209  (keymap-set user-map "e F" #'elfeed-update))
210 
211 (use-package org-mime :ensure t)
212 
213 (use-package sh-script
214  :hook (sh-mode . flymake-mode))
215 
216 (use-package tempo
217  :custom
218  tempo-interactive t
219  :config
220  (tempo-define-template
221  "org:readme"
222  '("#+TITLE: " p n>
223  "#+AUTHOR: " user-full-name " <" user-mail-address ">" n>)
224  "org:readme"
225  "Insert a readme.org file template.")
226  (tempo-define-template "org:src"
227  '("#+begin_src " p n>
228  "#+end_src" n>)
229  "org:src"))
230 ;;; Org Config
231 (keymap-set user-map "t" #'org-todo)
232 
233 ;; populate org-babel
234 (org-babel-do-load-languages
235  ;; TODO 2021-10-24: bqn, apl, k
236  'org-babel-load-languages '((shell . t)
237  (emacs-lisp . t)
238  (lisp . t)
239  (org . t)
240  (eshell . t)
241  (calc . t)
242  (sed . t)
243  (awk . t)
244  (dot . t)
245  (js . t)
246  (C . t)
247  (python . t)
248  (lua . t)
249  (lilypond . t)))
250 ;;; IRC
251 (setq erc-format-nick-function 'erc-format-@nick)
252 
253 (defun start-erc ()
254  "Connect to IRC."
255  (interactive)
256  (erc-tls :server "irc.libera.chat" :port 6697
257  :client-certificate '("/mnt/y/data/private/krypt/libera.pem"))
258  (setq erc-autojoin-channels-alist '(("irc.libera.chat" "#emacs")
259  ("irc.libera.chat" "#linux")
260  ("irc.libera.chat" "#rust")
261  ("irc.libera.chat" "#btrfs")
262  ("irc.libera.chat" "#lisp")
263  ("irc.libera.chat" "#sbcl")
264  ("irc.oftc.net" "#llvm"))))
265 ;;; Tags
266 ;;;###autoload
267 (defun refresh-tags ()
268  "Refresh TAGS database in `user-emacs-directory'."
269  (interactive)
270  (let ((default-directory user-emacs-directory))
271  (async-shell-command
272  "etags ./*.el \\
273 ./lib/*.el \\
274 ~/comp/org/*.el \\
275 ~/comp/core/emacs/*.el \\
276 ~/comp/core/emacs/lib/*.el \\
277 -o TAGS")))
278 
279 (unless (string-equal "hyde" system-name)
280  (add-hook 'dired-mode-hook #'all-the-icons-dired-mode)
281  (add-hook 'ibuffer-mode-hook #'all-the-icons-ibuffer-mode))
282 
283 ;; strangerdanger
284 (setq slime-enable-evaluate-in-emacs t)
285 
286 (defun org-word-count (beg end
287  &optional count-latex-macro-args?
288  count-footnotes?)
289  "Report the number of words in the Org mode buffer or selected region.
290 Ignores:
291 - comments
292 - tables
293 - source code blocks (#+BEGIN_SRC ... #+END_SRC, and inline blocks)
294 - hyperlinks (but does count words in hyperlink descriptions)
295 - tags, priorities, and TODO keywords in headers
296 - sections tagged as 'not for export'.
297 
298 The text of footnote definitions is ignored, unless the optional argument
299 COUNT-FOOTNOTES? is non-nil.
300 
301 If the optional argument COUNT-LATEX-MACRO-ARGS? is non-nil, the word count
302 includes LaTeX macro arguments (the material between {curly braces}).
303 Otherwise, and by default, every LaTeX macro counts as 1 word regardless
304 of its arguments."
305  (interactive "r")
306  (unless mark-active
307  (setf beg (point-min)
308  end (point-max)))
309  (let ((wc 0)
310  (latex-macro-regexp "\\\\[A-Za-z]+\\(\\[[^]]*\\]\\|\\){\\([^}]*\\)}"))
311  (save-excursion
312  (goto-char beg)
313  (while (< (point) end)
314  (cond
315  ;; Ignore comments.
316  ((or (org-in-commented-line) (org-at-table-p))
317  nil)
318  ;; Ignore hyperlinks. But if link has a description, count
319  ;; the words within the description.
320  ((looking-at org-bracket-link-analytic-regexp)
321  (when (match-string-no-properties 5)
322  (let ((desc (match-string-no-properties 5)))
323  (save-match-data
324  (cl-incf wc (length (remove "" (org-split-string
325  desc "\\W")))))))
326  (goto-char (match-end 0)))
327  ((looking-at org-any-link-re)
328  (goto-char (match-end 0)))
329  ;; Ignore source code blocks.
330  ((org-in-regexps-block-p "^#\\+BEGIN_SRC\\W" "^#\\+END_SRC\\W")
331  nil)
332  ;; Ignore inline source blocks, counting them as 1 word.
333  ((save-excursion
334  (backward-char)
335  (looking-at org-babel-inline-src-block-regexp))
336  (goto-char (match-end 0))
337  (setf wc (+ 2 wc)))
338  ;; Count latex macros as 1 word, ignoring their arguments.
339  ((save-excursion
340  (backward-char)
341  (looking-at latex-macro-regexp))
342  (goto-char (if count-latex-macro-args?
343  (match-beginning 2)
344  (match-end 0)))
345  (setf wc (+ 2 wc)))
346  ;; Ignore footnotes.
347  ((and (not count-footnotes?)
348  (or (org-footnote-at-definition-p)
349  (org-footnote-at-reference-p)))
350  nil)
351  (t
352  (let ((contexts (org-context)))
353  (cond
354  ;; Ignore tags and TODO keywords, etc.
355  ((or (assoc :todo-keyword contexts)
356  (assoc :priority contexts)
357  (assoc :keyword contexts)
358  (assoc :checkbox contexts))
359  nil)
360  ;; Ignore sections marked with tags that are
361  ;; excluded from export.
362  ((assoc :tags contexts)
363  (if (intersection (org-get-tags-at) org-export-exclude-tags
364  :test 'equal)
365  (org-forward-same-level 1)
366  nil))
367  (t
368  (cl-incf wc))))))
369  (re-search-forward "\\w+\\W*")))
370  (message (format "%d words in %s." wc
371  (if mark-active "region" "buffer")))))
372 
373 (defun org-check-misformatted-subtree ()
374  "Check misformatted entries in the current buffer."
375  (interactive)
376  (show-all)
377  (org-map-entries
378  (lambda ()
379  (when (and (move-beginning-of-line 2)
380  (not (looking-at org-heading-regexp)))
381  (if (or (and (org-get-scheduled-time (point))
382  (not (looking-at (concat "^.*" org-scheduled-regexp))))
383  (and (org-get-deadline-time (point))
384  (not (looking-at (concat "^.*" org-deadline-regexp)))))
385  (when (y-or-n-p "Fix this subtree? ")
386  (message "Call the function again when you're done fixing this subtree.")
387  (recursive-edit))
388  (message "All subtrees checked."))))))
389 
390 (defun org-sort-list-by-checkbox-type ()
391  "Sort list items according to Checkbox state."
392  (interactive)
393  (org-sort-list
394  nil ?f
395  (lambda ()
396  (if (looking-at org-list-full-item-re)
397  (cdr (assoc (match-string 3)
398  '(("[X]" . 1) ("[-]" . 2) ("[ ]" . 3) (nil . 4))))
399  4))))
400 
401 (defun org-time-string-to-seconds (s)
402  "Convert a string HH:MM:SS to a number of seconds."
403  (cond
404  ((and (stringp s)
405  (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)" s))
406  (let ((hour (string-to-number (match-string 1 s)))
407  (min (string-to-number (match-string 2 s)))
408  (sec (string-to-number (match-string 3 s))))
409  (+ (* hour 3600) (* min 60) sec)))
410  ((and (stringp s)
411  (string-match "\\([0-9]+\\):\\([0-9]+\\)" s))
412  (let ((min (string-to-number (match-string 1 s)))
413  (sec (string-to-number (match-string 2 s))))
414  (+ (* min 60) sec)))
415  ((stringp s) (string-to-number s))
416  (t s)))
417 
418 (defun org-time-seconds-to-string (secs)
419  "Convert a number of seconds to a time string."
420  (cond ((>= secs 3600) (format-seconds "%h:%.2m:%.2s" secs))
421  ((>= secs 60) (format-seconds "%m:%.2s" secs))
422  (t (format-seconds "%s" secs))))
423 
424 (defmacro with-time (time-output-p &rest exprs)
425  "Evaluate an org-table formula, converting all fields that look
426 like time data to integer seconds. If TIME-OUTPUT-P then return
427 the result as a time value."
428  (list
429  (if time-output-p 'org-time-seconds-to-string 'identity)
430  (cons 'progn
431  (mapcar
432  (lambda (expr)
433  `,(cons (car expr)
434  (mapcar
435  (lambda (el)
436  (if (listp el)
437  (list 'with-time nil el)
438  (org-time-string-to-seconds el)))
439  (cdr expr))))
440  `,@exprs))))
441 
442 (defun org-hex-strip-lead (str)
443  (if (and (> (length str) 2) (string= (substring str 0 2) "0x"))
444  (substring str 2) str))
445 
446 (defun org-hex-to-hex (int)
447  (format "0x%x" int))
448 
449 (defun org-hex-to-dec (str)
450  (cond
451  ((and (stringp str)
452  (string-match "\\([0-9a-f]+\\)" (setf str (org-hex-strip-lead str))))
453  (let ((out 0))
454  (mapc
455  (lambda (ch)
456  (setf out (+ (* out 16)
457  (if (and (>= ch 48) (<= ch 57)) (- ch 48) (- ch 87)))))
458  (coerce (match-string 1 str) 'list))
459  out))
460  ((stringp str) (string-to-number str))
461  (t str)))
462 
463 (defmacro with-hex (hex-output-p &rest exprs)
464  "Evaluate an org-table formula, converting all fields that look
465  like hexadecimal to decimal integers. If HEX-OUTPUT-P then
466  return the result as a hex value."
467  (list
468  (if hex-output-p 'org-hex-to-hex 'identity)
469  (cons 'progn
470  (mapcar
471  (lambda (expr)
472  `,(cons (car expr)
473  (mapcar (lambda (el)
474  (if (listp el)
475  (list 'with-hex nil el)
476  (org-hex-to-dec el)))
477  (cdr expr))))
478  `,@exprs))))
479 
480 (require 'mm-url) ; to include mm-url-decode-entities-string
481 
482 (defun org-insert-link-with-title ()
483  "Insert org link where default description is set to html title."
484  (interactive)
485  (let* ((url (read-string "URL: "))
486  (title (get-html-title-from-url url)))
487  (org-insert-link nil url title)))
488 
489 (defun get-html-title-from-url (url)
490  "Return content in <title> tag."
491  (let (x1 x2 (download-buffer (url-retrieve-synchronously url)))
492  (save-excursion
493  (set-buffer download-buffer)
494  (beginning-of-buffer)
495  (setq x1 (search-forward "<title>"))
496  (search-forward "</title>")
497  (setq x2 (search-backward "<"))
498  (mm-url-decode-entities-string (buffer-substring-no-properties x1 x2)))))
499 
500 (defun org-remove-empty-propert-drawers ()
501  "*Remove all empty property drawers in current file."
502  (interactive)
503  (unless (eq major-mode 'org-mode)
504  (error "You need to turn on Org mode for this function."))
505  (save-excursion
506  (goto-char (point-min))
507  (while (re-search-forward ":PROPERTIES:" nil t)
508  (save-excursion
509  (org-remove-empty-drawer-at "PROPERTIES" (match-beginning 0))))))
510 
511 (defun check-for-clock-out-note ()
512  (interactive)
513  (save-excursion
514  (org-back-to-heading)
515  (let ((tags (org-get-tags)))
516  (and tags (message "tags: %s " tags)
517  (when (member "clocknote" tags)
518  (org-add-note))))))
519 
520 (add-hook 'org-clock-out-hook 'check-for-clock-out-note)
521 
522 (defun org-list-files (dirs ext)
523  "Function to create list of org files in multiple subdirectories.
524 This can be called to generate a list of files for
525 org-agenda-files or org-refile-targets.
526 
527 DIRS is a list of directories.
528 
529 EXT is a list of the extensions of files to be included."
530  (let ((dirs (if (listp dirs)
531  dirs
532  (list dirs)))
533  (ext (if (listp ext)
534  ext
535  (list ext)))
536  files)
537  (mapc
538  (lambda (x)
539  (mapc
540  (lambda (y)
541  (setq files
542  (append files
543  (file-expand-wildcards
544  (concat (file-name-as-directory x) "*" y)))))
545  ext))
546  dirs)
547  (mapc
548  (lambda (x)
549  (when (or (string-match "/.#" x)
550  (string-match "#$" x))
551  (setq files (delete x files))))
552  files)
553  files))
554 
555 (defvar org-agenda-directories (list org-directory user-lab-directory)
556  "List of directories containing org files.")
557 (defvar org-agenda-extensions '(".org")
558  "List of extensions of agenda files")
559 
560 (defun org-set-agenda-files ()
561  (interactive)
562  (setq org-agenda-files (org-list-files
563  org-agenda-directories
564  org-agenda-extensions)))
565 
566 (add-hook 'after-init-hook 'org-set-agenda-files)
567 
568 ;;; Skel Config
569 
570 (setopt skt-enable-tempo-elements t
571  skt-delete-duplicate-marks t)
572 
573 (keymap-set skt-minor-mode-map "b" #'tempo-backward-mark)
574 (keymap-set skt-minor-mode-map "f" #'tempo-forward-mark)
575 (keymap-set skt-minor-mode-map "SPC" #'tempo-complete-tag)
576 (keymap-set skt-minor-mode-map "t" #'skt-add-tag)
577 
578 (skt-define-template defmacro (:abbrev "defvar" :tag t :mode lisp-mode)
579  "(defmacro " (p "Name: ") " (" (p "Args: ") ")" > n> r ")")
580 
581 (skt-define-template defun (:abbrev "defvar" :tag t :mode lisp-mode)
582  "(defun " (p "Name: ") " (" (p "Args: ") ")" > n> r ")")
583 
584 (skt-define-template defvar (:abbrev "defvar" :tag t :mode lisp-mode)
585  > "(defvar " > r ")")
586 
587 (skt-define-function capture (:abbrev "capture" :tag t) org-capture)
588 (skt-define-function agenda (:abbrev "agenda" :tag t) org-agenda)
589 (skt-define-function mjump (:abbrev "mjump" :tag t) bookmark-jump)
590 (skt-define-function bjump (:abbrev "bjump" :tag t) ibuffer-jump)
591 (skt-define-function rjump (:abbrev "rjump" :tag t)
592  (lambda () (jump-to-register (read-char "register: "))))
593 (skt-define-function pjump (:abbrev "pjump" :tag t) (lambda () (project-switch-project default-directory)))
594 
595 (defvar skt-skeleton-path-function #'abbreviate-file-name
596  "Function to be called when expanding file-header skeletons. Useful to
597 rebind locally inside a project or module, where you want to delete some
598 prefix or replace it.")
599 
600 (defun skt-buffer-path () (funcall skt-skeleton-path-function buffer-file-name))
601 
602 (defun skt-skelfile-path ()
603  (if (string= (file-name-nondirectory buffer-file-name) "skelfile")
604  "skelfile"
605  (skt-buffer-path)))
606 
607 (skt-define-skeleton head (:abbrev "head" :mode lisp-mode)
608  "title: "
609  ";;; " (skt-buffer-path) " --- " str \n \n \n ";;; Code:" \n > _)
610 
611 (skt-define-skeleton head (:abbrev "head" :mode rust-mode)
612  "title: "
613  "//! " (skt-buffer-path) " --- " str \n \n "// " _ \n \n "//! Code:" \n > _)
614 
615 (skt-define-skeleton head (:abbrev "head" :mode skel-mode)
616  "title: "
617  ";;; " (skt-skelfile-path) " --- " str " -*- mode: skel; -*-" \n _)
618 
619 (skt-define-skeleton head (:abbrev "head" :mode org-mode)
620  "title: "
621  "#+title: " str \n
622  "#+author: " (skeleton-read "author: ") \n
623  "#+description: " (skeleton-read "description: ") \n
624  "#+setupfile: clean.theme" \n > _)
625 
626 (skt-define-skeleton local-vars
627  (:tag t :abbrev "local-vars"
628  :docstring "Insert a local variables section. Use current comment syntax if any.")
629  (completing-read "Mode: " obarray
630  (lambda (symbol)
631  (if (commandp symbol)
632  (string-match "-mode$" (symbol-name symbol))))
633  t)
634  '(save-excursion
635  (if (re-search-forward page-delimiter nil t)
636  (error "Not on last page")))
637  comment-start "Local Variables:" comment-end \n
638  comment-start "mode: " str
639  & -5 | '(kill-line 0) & -1 | comment-end \n
640  ( (completing-read (format "Variable, %s: " skeleton-subprompt)
641  obarray
642  (lambda (symbol)
643  (or (eq symbol 'eval)
644  (custom-variable-p symbol)))
645  t)
646  comment-start str ": "
647  (read-from-minibuffer "Expression: " nil read-expression-map nil
648  'read-expression-history) | _
649  comment-end \n)
650  resume:
651  comment-start "End:" comment-end \n)
652 
653 ;; autoinsert
654 (skt-register-auto-insert "skelfile" #'skt-template-skel-head)
655 (setq auto-insert :unmodified)
656 (setq auto-insert-query nil)
657 (auto-insert-mode t)
658 
659 (keymap-set skel-minor-mode-map "C-<return>" 'company-tempo)
660 
661 (provide 'ellis)
662 ;;; ellis.el ends here