init.el 108 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341
  1. ;; -*- lexical-binding: t; -*-
  2. ;;; Initialisation
  3. ;;;; Bootstrap and use package
  4. (defvar jao-emacs-dir (expand-file-name "~/etc/emacs"))
  5. (setq package-user-dir
  6. (expand-file-name (format "~/.emacs.d/elpa.%s" emacs-major-version))
  7. package-check-signature 'allow-unsigned)
  8. (require 'package)
  9. (setq package-archives
  10. '(("gnu-devel" . "https://elpa.gnu.org/devel/")
  11. ("nongnu-devel" . "https://elpa.nongnu.org/nongnu-devel/")
  12. ("melpa" . "https://melpa.org/packages/"))
  13. package-archive-priorities '(("gnu-devel" . 2)
  14. ("nongnu-devel" . 1)
  15. ("melpa" . 0)))
  16. (package-initialize)
  17. (unless (package-installed-p 'use-package)
  18. (package-refresh-contents)
  19. (package-install 'use-package))
  20. (require 'use-package)
  21. (use-package gnu-elpa-keyring-update :ensure t)
  22. ;;;; .elc vs .el loading
  23. (setq load-prefer-newer t)
  24. (setq comp-async-report-warnings-errors nil
  25. warning-suppress-types '((comp)))
  26. ;;; Paths
  27. (defvar jao-local-lisp-dir "~/lib/elisp"
  28. "Directory for external elisp libraries and repos")
  29. (defvar jao-data-dir (expand-file-name "data" jao-emacs-dir)
  30. "Directory containing static data, such as images.")
  31. (defun jao-data-file (file) (expand-file-name file jao-data-dir))
  32. (setq jao-org-dir (expand-file-name "~/doc/org"))
  33. (defvar jao-sink-dir
  34. (file-name-as-directory (expand-file-name "~/doc/sink"))
  35. "Directory used for downloads and such.")
  36. (defvar jao-site-dir (expand-file-name "site" jao-emacs-dir))
  37. (defun jao-site-el (basename &optional gpg)
  38. (expand-file-name (concat basename ".el" (when gpg ".gpg")) jao-site-dir))
  39. (defun jao-load-site-el (basename &optional gpg)
  40. (let ((lf (jao-site-el basename gpg)))
  41. (if (file-exists-p lf)
  42. (load lf)
  43. (message "Attempted to load non existing %s" lf))))
  44. (defun jao-exec-path (dir)
  45. (let ((fn (expand-file-name dir)))
  46. (add-to-list 'exec-path fn nil)
  47. (setenv "PATH" (concat fn ":" (getenv "PATH")))))
  48. (defun jao-load-path (subdir)
  49. "Add to load path a subdir of `jao-local-lisp-dir'"
  50. (let ((path (expand-file-name subdir jao-local-lisp-dir)))
  51. (when (file-directory-p path) (add-to-list 'load-path path))))
  52. ;;;; load and info path initialisation
  53. (add-to-list 'load-path jao-site-dir)
  54. (add-to-list 'load-path jao-local-lisp-dir)
  55. (add-to-list 'load-path (expand-file-name "custom" jao-emacs-dir))
  56. (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/")
  57. (let ((libd (expand-file-name "lib" jao-emacs-dir)))
  58. (add-to-list 'load-path libd)
  59. (dolist (f (directory-files libd t "^[^.]+$"))
  60. (when (file-directory-p f) (add-to-list 'load-path f))))
  61. (defvar jao-info-dir (expand-file-name "~/doc/info"))
  62. (require 'info)
  63. (add-to-list 'Info-directory-list jao-info-dir)
  64. ;;;; custom location of custom.el and co.
  65. (setq custom-file (jao-site-el "custom"))
  66. (load custom-file)
  67. (setq custom-unlispify-tag-names nil)
  68. (setq custom-buffer-done-kill t)
  69. (setq custom-raised-buttons nil)
  70. ;;; Preamble
  71. ;;;; preamble (pre.el)
  72. (jao-load-site-el "pre")
  73. ;;; System Utilities
  74. ;;;; persist
  75. (require 'persist)
  76. ;;;; (no) backups
  77. (setq vc-make-backup-files nil
  78. make-backup-files nil)
  79. ;;;; history (saveplace, recentf, savehist)
  80. (require 'saveplace)
  81. (setq save-place-file (expand-file-name "~/.emacs.d/cache/places"))
  82. (save-place-mode 1)
  83. (setq recentf-save-file (expand-file-name "~/.emacs.d/cache/recentf")
  84. recentf-max-saved-items 2000
  85. recentf-exclude '("/home/jao/\\.emacs\\.d/elpa.*/.*"
  86. ".*/.git/COMMIT_EDITMSG"))
  87. (require 'recentf)
  88. (recentf-mode 1)
  89. (setq savehist-file (expand-file-name "~/.emacs.d/cache/history"))
  90. (require 'savehist)
  91. (savehist-mode t)
  92. (defun jao-unpropertize-kill-ring ()
  93. (setq kill-ring (mapcar #'substring-no-properties kill-ring)))
  94. (add-hook 'kill-emacs-hook #'jao-unpropertize-kill-ring)
  95. (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
  96. savehist-ignored-variables '(ido-file-history))
  97. ;;;; yes/no, bell, startup message
  98. (setq use-short-answers t)
  99. (setq inhibit-startup-message t)
  100. (setq visible-bell t)
  101. ;;;; server
  102. (setenv "EDITOR" "emacsclient")
  103. (require 'server)
  104. (unless (or (daemonp) (server-running-p)) (server-start))
  105. ;;;; timers
  106. (put 'list-timers 'disabled nil)
  107. ;;;; tramp
  108. (inhibit-remote-files)
  109. ;;;; sleep/awake
  110. (use-package jao-sleep)
  111. (jao-sleep-dbus-register)
  112. ;;;; process runners
  113. (use-package jao-shell
  114. :demand t
  115. :config (jao-shell-def-exec jao-trayer "trayer.sh")
  116. :bind (("s-r" . jao-shell-exec)))
  117. ;;;; app launcher
  118. (jao-load-path "app-launcher")
  119. (use-package app-launcher
  120. :bind (("s-R" . app-launcher-run-app)))
  121. ;;;; brightness control
  122. (jao-shell-def-exec jao-bright-set-up "brightnessctl" "-q" "s" "5%+")
  123. (jao-shell-def-exec jao-bright-set-down "brightnessctl" "-q" "s" "5%-")
  124. (defun jao-brightness ()
  125. (string-trim (or (cadr (jao-shell-cmd-lines "brightnessctl")) "(Unknown)")))
  126. (defun jao-bright-show ()
  127. (interactive)
  128. (message "%s" (jao-brightness)))
  129. (defun jao-bright-up ()
  130. (interactive)
  131. (jao-shell-exec "brightnessctl -q s 5%%+" t)
  132. (jao-bright-show))
  133. (defun jao-bright-down ()
  134. (interactive)
  135. (jao-shell-exec "brightnessctl -q s 5%%-" t)
  136. (jao-bright-show))
  137. ;;;; keyboard
  138. (when (> emacs-major-version 27)
  139. (use-package repeat
  140. :config (setq repeat-echo-function 'repeat-echo-mode-line
  141. repeat-exit-key "SHIFT"
  142. repeat-exit-timeout 2))
  143. (repeat-mode))
  144. (defun jao-kb-toggle (&optional lyt)
  145. (interactive)
  146. (shell-command-to-string (or lyt
  147. (if (jao-kb-toggled-p)
  148. "setxkbmap us"
  149. "setxkbmap us -variant intl"))))
  150. (defun jao-kb-toggled-p ()
  151. (not (string-empty-p
  152. (shell-command-to-string "setxkbmap -query|grep variant"))))
  153. (customize-set-variable 'default-input-method "catalan-prefix")
  154. ;; http://mbork.pl/2022-03-07_Transient_input_method
  155. (customize-set-variable 'default-transient-input-method "TeX")
  156. (setq echo-keystrokes 1
  157. suggest-key-bindings nil)
  158. ;;;; transient
  159. (use-package transient
  160. :init (setq transient-show-popup t) ;; 2.0
  161. :demand t
  162. :config
  163. (transient-bind-q-to-quit))
  164. (defmacro jao-transient-major-mode (mode &rest suffix)
  165. (declare (indent defun))
  166. (let ((mode (intern (format "%s-mode" mode)))
  167. (mmap (intern (format "%s-mode-map" mode)))
  168. (name (intern (format "jao-transient-%s" mode))))
  169. `(progn
  170. (transient-define-prefix ,name ()
  171. ,(format "Transient ops for %s" mode)
  172. [,(format "Operations for %s" mode) :if-derived ',mode ,@suffix])
  173. (define-key ,mmap (kbd "s-SPC") #',name)
  174. (define-key ,mmap (kbd "C-c SPC") #',name))))
  175. (defmacro jao-transient-major-mode+1 (mode suffix)
  176. (declare (indent defun))
  177. (let ((name (intern (format "jao-transient-%s" mode))))
  178. (if (fboundp name)
  179. `(transient-append-suffix ',name '(0 -1) ,suffix)
  180. `(jao-transient-major-mode ,mode ,suffix))))
  181. (defmacro jao-transient-major-mode+ (mode &rest suffixes)
  182. (declare (indent defun))
  183. `(progn ,@(mapcar (lambda (s) `(jao-transient-major-mode+1 ,mode ,s))
  184. suffixes)))
  185. ;;;; disk monitoring
  186. (use-package jao-dirmon
  187. :commands jao-dirmon-report)
  188. ;;;; mailcap
  189. (use-package mailcap
  190. :config
  191. (add-to-list 'mailcap-mime-extensions '(".JPEG" . "image/jpeg"))
  192. (add-to-list 'mailcap-mime-extensions '(".JPG" . "image/jpeg"))
  193. (defun jao-icalendar-import-buffer (&optional no-kill)
  194. (let ((icalendar-import-format "%s%u%l%d"))
  195. (icalendar-import-buffer diary-file t nil))
  196. (unless no-kill (kill-buffer))
  197. (message "Event imported into diary"))
  198. (defun jao-icalendar-import-invite (file)
  199. (with-temp-buffer
  200. (insert-file-contents file)
  201. (jao-icalendar-import-buffer t)))
  202. :custom
  203. ((mailcap-user-mime-data
  204. `((jao-icalendar-import-buffer "application/ics")
  205. ("emacsclient -e '(jao-icalendar-import-invite \"%s\")'" "application/ics")
  206. (doc-view-mode "application/.*pdf" (display-graphic-p))
  207. ("zathura \"%s\"" "application/.*pdf")
  208. (image-mode "image/.*" (display-graphic-p))
  209. ("firefox %s && riverctl set-focused-tags 2" "text/html" jao-river-enabled)
  210. ("swayimg \"%s\"" "image/.*" jao-sway-enabled)
  211. ("imv-wayland \"%s\"" "image/.*" jao-wayland-enabled)
  212. ("imv-x11 \"%s\"" "image/.*")))))
  213. ;;; Crypto
  214. ;;;; PGP, EPG, passwords
  215. (setq auth-source-debug nil)
  216. (require 'auth-source)
  217. (add-to-list 'auth-source-protocols '(local "local"))
  218. (setq auth-sources '("~/.emacs.d/authinfo.gpg" "~/.netrc"))
  219. (use-package epa-file
  220. :init (setq epa-file-cache-passphrase-for-symmetric-encryption t)
  221. :config (epa-file-enable))
  222. (require 'epa-file)
  223. (defun jao--get-user/password (h)
  224. (let ((item (car (auth-source-search :type 'netrc :host h :max 1))))
  225. (when item
  226. (let ((user (plist-get item :user))
  227. (pwd (plist-get item :secret)))
  228. (list user (when pwd (funcall pwd)))))))
  229. (defun jao-call-with-auth (host fun)
  230. (let ((up (jao--get-user/password host)))
  231. (funcall fun (car up) (cadr up))))
  232. (defmacro jao-with-auth (host usr pwd &rest body)
  233. (declare (indent defun))
  234. `(jao-call-with-auth ,host (lambda (,usr ,pwd) ,@body)))
  235. ;;;; pass
  236. (use-package password-store-menu
  237. :ensure t
  238. :config (password-store-menu-enable)
  239. :custom (password-store-menu-key "C-c p"))
  240. ;;; Fonts and color themes
  241. ;;;; widgets
  242. (setq widget-image-enable nil
  243. widget-link-prefix ""
  244. widget-link-suffix ""
  245. widget-button-prefix " "
  246. widget-button-suffix " "
  247. widget-push-button-prefix ""
  248. widget-push-button-suffix "")
  249. ;;;; nobreak char display
  250. (setq nobreak-char-display nil)
  251. ;;;; vertical separator
  252. (unless (display-graphic-p)
  253. (set-display-table-slot standard-display-table
  254. 'vertical-border
  255. (make-glyph-code ?│)))
  256. ;;;; transparency
  257. (defvar jao-transparent-only-bg (> emacs-major-version 28))
  258. (defvar jao-frames-default-alpha
  259. (cond ((eq window-system 'pgtk) 85)
  260. (jao-transparent-only-bg 88)
  261. (t 85)))
  262. (defvar jao-transparent-frame (< jao-frames-default-alpha 100))
  263. (defun jao-alpha-parameters (&optional level)
  264. (let ((level (or level jao-frames-default-alpha)))
  265. (if jao-transparent-only-bg
  266. `((alpha-background . ,level) (alpha))
  267. `((alpha . ,(cons level level)) (alpha-background)))))
  268. (defun jao-set-transparency (&optional level all)
  269. (interactive "nOpacity (0-100): ")
  270. (let ((level (or level jao-frames-default-alpha)))
  271. (setq jao-transparent-frame (< level 100))
  272. (if all
  273. (modify-all-frames-parameters (jao-alpha-parameters level))
  274. (modify-frame-parameters nil (jao-alpha-parameters level)))))
  275. (defun jao-toggle-transparency (&optional all)
  276. (interactive "P")
  277. (let ((level (if jao-transparent-frame 100 jao-frames-default-alpha)))
  278. (jao-set-transparency level all)))
  279. (jao-set-transparency)
  280. ;;;; themes
  281. (defun jao-colors-scheme-dark-p ()
  282. (equal "dark" (getenv "JAO_COLOR_SCHEME")))
  283. (defun jao-colors-scheme ()
  284. (if (jao-colors-scheme-dark-p) 'dark 'light))
  285. (customize-set-variable 'frame-background-mode (jao-colors-scheme))
  286. (setq custom-theme-directory
  287. (expand-file-name "lib/themes" jao-emacs-dir))
  288. (require 'jao-themes)
  289. (defvar jao-theme-dark 'jao-dark)
  290. (defvar jao-theme-light 'jao-light)
  291. (defvar jao-theme-term-dark 'modus-vivendi)
  292. (defvar jao-theme-term-light 'jao-light-term)
  293. (defun jao-themes-setup ()
  294. (let* ((dark (jao-colors-scheme-dark-p))
  295. (theme (cond ((and dark window-system) jao-theme-dark)
  296. (dark jao-theme-term-dark)
  297. (window-system jao-theme-light)
  298. (t jao-theme-term-light))))
  299. (load-theme theme t)
  300. (modify-all-frames-parameters `((font . ,jao-themes-default-face)))))
  301. (jao-themes-setup)
  302. ;;; Help system
  303. ;;;; help buffers
  304. (setq help-window-select t
  305. help-window-keep-selected nil
  306. help-link-key-to-documentation t)
  307. ;;;; find-func/var/lib
  308. (use-package find-func
  309. :bind (("C-h C-v" . find-variable)
  310. ("C-h C-f" . find-function)
  311. ("C-h C-k" . find-function-on-key)
  312. ("C-h C-l" . find-library)))
  313. ;;;; eldoc
  314. (use-package eldoc
  315. :init (setq eldoc-minor-mode-string nil
  316. eldoc-idle-delay 0.1
  317. eldoc-echo-area-display-truncation-message nil
  318. eldoc-echo-area-use-multiline-p 5
  319. eldoc-echo-area-prefer-doc-buffer 'maybe
  320. eldoc-display-functions '(eldoc-display-in-echo-area))
  321. :config (global-eldoc-mode 1))
  322. (defun jao-eldoc-toggle ()
  323. "Toggle eldoc's documentation buffer."
  324. (interactive)
  325. (let ((buffer (eldoc-doc-buffer)))
  326. (if-let (w (and buffer (get-buffer-window buffer)))
  327. (delete-window w)
  328. (eldoc-doc-buffer t))))
  329. ;;;; bookmarks
  330. (setq bookmark-default-file "~/.emacs.d/emacs.bmk"
  331. bookmark-fringe-mark nil)
  332. ;;;; man pages
  333. (use-package man
  334. :config (setq Man-notify-method 'pushy)) ;; pushy - same window
  335. ;;; Minibuffer
  336. (use-package jao-minibuffer
  337. :init
  338. (if (jao-colors-scheme-dark-p)
  339. (setq jao-minibuffer-active-buffer-line-color "azure4"
  340. jao-minibuffer-inactive-buffer-line-color "grey25")
  341. (setq jao-minibuffer-active-buffer-line-color "burlywood3"
  342. jao-minibuffer-inactive-buffer-line-color "grey65"))
  343. (setq jao-minibuffer-adaptive-alignment nil)
  344. :commands (jao-minibuffer-add-variable
  345. jao-minibuffer-refresh
  346. jao-minibuffer-mode))
  347. (setq enable-recursive-minibuffers t)
  348. (require 'mb-depth)
  349. (minibuffer-depth-indicate-mode 1)
  350. (setq minibuffer-default-prompt-format " (default %s)")
  351. (minibuffer-electric-default-mode 1)
  352. (jao-minibuffer-mode 1)
  353. ;;; Mode line
  354. ;;;; config
  355. (setq line-number-display-limit-width 250
  356. mode-line-position-column-format '(" %c")
  357. mode-line-position-line-format '(" %c %l")
  358. mode-line-end-spaces nil
  359. mode-line-percent-position
  360. '("%2l" (:eval (format " %d " (line-number-at-pos (point-max)))) "%2c"))
  361. (line-number-mode -1)
  362. (column-number-mode -1)
  363. ;;;; jao-mode-line
  364. (defvar jao-mode-line-in-minibuffer t)
  365. (use-package jao-mode-line
  366. :commands (jao-mode-line-add-to-minibuffer-left
  367. jao-mode-line-add-to-minibuffer-right
  368. jao-mode-line-remove-from-minibuffer))
  369. ;;;; time display
  370. (setq world-clock-list
  371. '(("Europe/London" "Edinburgh")
  372. ("Europe/Paris" "Barcelona")
  373. ("Asia/Tokyo" "Tokyo")
  374. ("America/Los_Angeles" "Corvallis")
  375. ("America/New_York" "New York")))
  376. (setq display-time-day-and-date nil
  377. display-time-24hr-format nil
  378. display-time-default-load-average nil
  379. display-time-format " %a %e %H:%M")
  380. (defun jao-time-to-epoch (&optional s)
  381. "Transform a time string to an epoch integer in milliseconds."
  382. (interactive)
  383. (let ((s (or s (read-string "Time string: " (thing-at-point 'string)))))
  384. (message "%s = %s"
  385. s
  386. (round (* 1000 (time-to-seconds (parse-time-string s)))))))
  387. (defun jao-epoch-to-time (&optional v)
  388. "Transform an epoch, given in milliseconds, to a time string."
  389. (interactive)
  390. (let ((v (or v (read-number "Milliseconds: " (thing-at-point 'number)))))
  391. (message "%s = %s" v
  392. (format-time-string "%Y-%m-%d %H:%M:%S"
  393. (seconds-to-time (/ v 1000.0))))))
  394. ;;;; mode line toggle
  395. (use-package jao-mode-line
  396. :init
  397. (when (and window-system (not jao-mode-line-in-minibuffer))
  398. (add-to-list 'after-make-frame-functions #'jao-mode-line-hide-inactive)
  399. (add-hook 'after-init-hook #'jao-mode-line-toggle-inactive))
  400. :demand t
  401. :bind (("<home>" . jao-mode-line-toggle-inactive)
  402. ("<end>" . jao-mode-line-toggle)
  403. ("<insert>" . jao-mode-line-echo)))
  404. ;;;; diminish
  405. (use-package diminish
  406. :ensure t
  407. :demand t
  408. :diminish ((auto-fill-function . " §")
  409. (auto-revert-mode . "")))
  410. (use-package outline
  411. :diminish ((outline-minor-mode . "")))
  412. ;;;; battery
  413. (use-package battery
  414. :init (setq battery-load-low 15
  415. battery-load-critical 8
  416. battery-mode-line-limit 40
  417. battery-echo-area-format
  418. "%L %r %B (%p%% load, remaining time %t)"
  419. battery-mode-line-format " 🔋%b%p% "))
  420. (with-eval-after-load "jao-minibuffer"
  421. (if jao-mode-line-in-minibuffer
  422. (display-battery-mode 1)
  423. (jao-minibuffer-add-variable 'battery-mode-line-string 80)))
  424. ;;; Notifications
  425. ;;;; jao-notify
  426. (use-package jao-notify
  427. :demand t
  428. :init (setq jao-notify-use-messages t))
  429. ;;;; tracking
  430. (use-package tracking
  431. :demand t
  432. :init (setq tracking-position 'before-modes
  433. tracking-frame-behavior nil
  434. tracking-most-recent-first nil
  435. tracking-max-mode-line-entries 10
  436. tracking-sort-faces-first t
  437. tracking-shorten-modes '())
  438. :config
  439. (setq erc-track-enable-keybindings nil))
  440. (use-package jao-tracking
  441. :demand t
  442. :init (setq jao-tracking-bkg (if (jao-colors-scheme-dark-p) "grey20" "grey93"))
  443. :config (jao-tracking-setup t))
  444. ;;;; ednc
  445. (use-package ednc
  446. :ensure t
  447. :diminish nil)
  448. (use-package jao-ednc
  449. :demand t
  450. :init (setq jao-ednc-use-tracking nil)
  451. :commands (jao-ednc-setup)
  452. :after ednc
  453. :config
  454. (jao-ednc-ignore-app "Firefox")
  455. (transient-define-prefix jao-transient-ednc ()
  456. ["Notifications"
  457. ("s" "show last" jao-ednc-show)
  458. ("S" "show all" jao-ednc-pop)
  459. ("n" "dismiss and show" jao-ednc-dismiss-and-show :transient t)
  460. ("d" "dismiss last" jao-ednc-dismiss)
  461. ("D" "dismiss all" jao-ednc-dismiss-all)
  462. ("i" "invoke last action" jao-ednc-invoke-last-action)])
  463. (global-set-key (kbd "s-n") #'jao-transient-ednc))
  464. ;;; Calendar, diary, weather
  465. ;;;; diary
  466. (setq diary-file (expand-file-name "diary" jao-org-dir)
  467. diary-display-function 'diary-fancy-display
  468. diary-mail-addr "jao@localhost"
  469. diary-comment-start ";;"
  470. diary-comment-end "")
  471. (add-hook 'diary-list-entries-hook 'diary-sort-entries t)
  472. ;;;; calendar
  473. (setq appt-display-format nil)
  474. (appt-activate 1)
  475. (setq calendar-latitude 55.9533
  476. calendar-longitude -3.1883
  477. calendar-left-margin 4
  478. calendar-location-name "Edinburgh, Scotland"
  479. calendar-mark-diary-entries-flag t
  480. calendar-week-start-day 1 ;; 0 sunday
  481. calendar-date-echo-text '(format "ISO date: %s"
  482. (calendar-iso-date-string
  483. (list month day year))))
  484. (setq calendar-holidays
  485. '((holiday-fixed 1 1 "New Year's Day")
  486. (holiday-fixed 4 1 "April Fools' Day")
  487. (holiday-float 5 0 2 "Mother's Day")
  488. (holiday-fixed 3 19 "Father's Day")
  489. (holiday-float 11 4 4 "Thanksgiving")
  490. (holiday-fixed 12 25 "Christmas")
  491. (holiday-chinese-new-year)
  492. (solar-equinoxes-solstices)
  493. (holiday-sexp calendar-daylight-savings-starts
  494. (format "Daylight Saving Time Begins %s"
  495. (solar-time-string
  496. (/ calendar-daylight-savings-starts-time
  497. (float 60))
  498. calendar-standard-time-zone-name)))
  499. (holiday-sexp calendar-daylight-savings-ends
  500. (format "Daylight Saving Time Ends %s"
  501. (solar-time-string
  502. (/ calendar-daylight-savings-ends-time
  503. (float 60))
  504. calendar-daylight-time-zone-name)))))
  505. (add-to-list 'display-buffer-alist
  506. `(,(regexp-quote diary-fancy-buffer)
  507. (display-buffer-at-bottom)
  508. (window-parameters (mode-line-format . none))
  509. (window-height . fit-window-to-buffer)))
  510. (defun jao-diary--select ()
  511. (switch-to-buffer diary-fancy-buffer))
  512. (add-hook 'diary-fancy-display-mode-hook #'jao-diary--select)
  513. (setq org-calendar-insert-diary-entry-key nil
  514. org-agenda-diary-file 'diary-file)
  515. ;;;; winttr
  516. (defun jao-weather (&optional wide)
  517. (interactive "P")
  518. (if (not wide)
  519. (message "%s"
  520. (jao-shell-string "curl -s"
  521. "https://wttr.in/?format=%l++%m++%C+%c+%t+%w++%p"))
  522. (jao-afio-goto-scratch)
  523. (if-let ((b (get-buffer "*wttr*")))
  524. (progn (pop-to-buffer b)
  525. (term-send-string (get-buffer-process nil) "clear;curl wttr.in\n"))
  526. (jao-exec-in-term "curl wttr.in" "*wttr*"))))
  527. (global-set-key (kbd "<f5>") #'jao-weather)
  528. ;;; Files, dired and scratch buffer
  529. ;;;; so-long
  530. (setq large-file-warning-threshold (* 200 1024 1024))
  531. ;; (use-package so-long
  532. ;; :ensure t
  533. ;; :diminish)
  534. ;; (global-so-long-mode 1)
  535. ;;;; persistent scratch
  536. (use-package persistent-scratch
  537. :ensure t
  538. :config (persistent-scratch-setup-default))
  539. ;;;; dired
  540. (use-package dired
  541. :init
  542. (setq dired-recursive-deletes 'top
  543. dired-recursive-copies 'top
  544. dired-listing-switches "-alhF --group-directories-first"
  545. ls-lisp-dirs-first t
  546. dired-dwim-target t
  547. dired-kill-when-opening-new-dired-buffer t
  548. dired-mouse-drag-files t
  549. wdired-create-parent-directories t
  550. dired-guess-shell-alist-user
  551. '(;; ("\\.\\(png\\|jpe?g\\|tiff\\)" "feh" "xdg-open")
  552. ("\\.\\(mp[34]\\|m4a\\|ogg\\|flac\\|webm\\|mkv\\)" "mpv" "xdg-open")
  553. (".*" "xdg-open")))
  554. (put 'dired-find-alternate-file 'disabled nil)
  555. :hook (dired-mode . turn-on-gnus-dired-mode)
  556. :bind (:map dired-mode-map
  557. ("C-c C-r" . wdired-change-to-wdired-mode)
  558. ("C-M-m" . gnus-dired-attach)))
  559. (use-package dired-x :demand t)
  560. (use-package find-dired
  561. :init (setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld"))
  562. :bind ("C-c D" . find-name-dired))
  563. (use-package dired-duplicates :ensure t)
  564. ;;; General editing
  565. ;;;; automatically uncompress
  566. (require 'jka-compr)
  567. (auto-compression-mode 1)
  568. ;;;; wgrep
  569. (use-package wgrep :ensure t)
  570. (require 'wgrep)
  571. ;;;; executable scripts
  572. (add-hook 'after-save-hook
  573. 'executable-make-buffer-file-executable-if-script-p)
  574. ;;;; spaces, tabs, kill
  575. (setq kill-whole-line t)
  576. (setq-default indent-tabs-mode nil)
  577. (setq indent-tabs-width 4)
  578. (setq-default default-tab-width 8)
  579. (setq kill-read-only-ok t)
  580. (setq view-read-only nil)
  581. ;;;; whitespace and filling column
  582. (add-hook 'write-file-functions 'delete-trailing-whitespace)
  583. (setq-default indicate-empty-lines nil)
  584. (setq-default fill-column 78)
  585. (setq comment-auto-fill-only-comments nil)
  586. (use-package whitespace
  587. :init
  588. (setq whitespace-style '(face tabs trailing ;; lines-tail
  589. empty missing-newline-at-eof)
  590. whitespace-line-column 80)
  591. :hook (prog-mode . whitespace-mode)
  592. :diminish nil)
  593. (use-package display-fill-column-indicator
  594. :init (setq-default display-fill-column-indicator-column 80)
  595. :hook (prog-mode . display-fill-column-indicator-mode))
  596. ;;;; visible mode
  597. (use-package visible-mode
  598. :bind (("s-v" . visible-mode)))
  599. ;;;; changes
  600. (use-package goto-chg
  601. :ensure t
  602. :bind (("C-." . goto-last-change)
  603. ("C-c ." . goto-last-change)
  604. ("C-c ," . goto-last-change-reverse)))
  605. ;;;; eval-and-replace
  606. (defun fc-eval-and-replace ()
  607. "Replace the preceding sexp with its value."
  608. (interactive)
  609. (backward-kill-sexp)
  610. (condition-case nil
  611. (prin1 (eval (read (current-kill 0)))
  612. (current-buffer))
  613. (error (message "Invalid expression")
  614. (insert (current-kill 0)))))
  615. (global-set-key "\C-ce" 'fc-eval-and-replace)
  616. ;;;; skeletons and autoinsert
  617. (use-package autoinsert
  618. :config
  619. (setq auto-insert-directory "~/.emacs.d/autoinsert/"
  620. auto-insert t
  621. auto-insert-query t)
  622. (setf (alist-get 'html-mode auto-insert-alist nil t) nil))
  623. (add-hook 'find-file-hook #'auto-insert)
  624. (use-package jao-skel
  625. :demand t
  626. :config
  627. (defvar flymake-allowed-file-name-masks nil)
  628. (require 'jao-skel-geiser)
  629. (require 'jao-skel-lisp)
  630. (require 'jao-skel-haskell)
  631. (require 'jao-skel-latex))
  632. ;;; Completion and search
  633. ;;;; completion
  634. (require 'jao-custom-completion)
  635. ;;;; recoll
  636. (jao-load-path "consult-recoll")
  637. (defun jao-recoll-format (title url _mtype)
  638. (let* ((u (replace-regexp-in-string "file://" "" url))
  639. (u (replace-regexp-in-string "/home/jao/" "" u))
  640. (u (replace-regexp-in-string
  641. "\\(doc\\|org/doc\\|.emacs.d/gnus/Mail\\|var/mail\\)/" "" u)))
  642. (format "%s (%s)" ;; "%s (%s, %s)"
  643. title
  644. (propertize u 'face 'jao-themes-f01)
  645. ;; (propertize mtype 'face 'jao-themes-f01)
  646. )))
  647. (defun jao-recoll-open-html (file &optional _page)
  648. (if (string-match-p "\.epub\\'" file)
  649. (find-file file)
  650. (jao-afio-goto-www)
  651. (if jao-afio-use-w3m (w3m-find-file file) (eww-open-file file))))
  652. (defun jao-recoll-open-pdf (file &optional page)
  653. (if (string-match-p "/gnus/Mail/" file)
  654. (funcall (or (cdr (assoc-string "message/rfc822" consult-recoll-open-fns))
  655. 'find-file)
  656. file
  657. page)
  658. (jao-open-doc file page)))
  659. (defun jao-recoll-consult-messages ()
  660. (interactive)
  661. (consult-recoll "mime:message "))
  662. (defun jao-recoll-consult-docs ()
  663. (interactive)
  664. (consult-recoll (format "dir:%s/doc " jao-org-dir)))
  665. (defun jao-recoll-consult-notes ()
  666. "Use consult-recoll to search notes."
  667. (interactive)
  668. (consult-recoll (format "dir:%s " jao-org-notes-dir)))
  669. (use-package consult-recoll
  670. :commands (consult-recoll consult-recoll-embark-setup)
  671. :init (setq consult-recoll-open-fns
  672. '(("application/pdf" . jao-recoll-open-pdf)
  673. ("text/html" . jao-recoll-open-html))
  674. consult-recoll-search-flags 'query
  675. consult-recoll-inline-snippets t
  676. consult-recoll-format-candidate #'jao-recoll-format)
  677. :config
  678. (consult-customize consult-recoll :preview-key 'any)
  679. (transient-define-prefix jao-transient-recoll ()
  680. ["Consult recoll queries"
  681. ("r" "everywhere" consult-recoll)
  682. ("n" "on notes" jao-recoll-consult-notes)
  683. ("d" "on docs" jao-recoll-consult-docs)
  684. ("m" "on messages" jao-recoll-consult-messages)])
  685. :bind (("s-r" . #'jao-transient-recoll)))
  686. (with-eval-after-load "embark" (consult-recoll-embark-setup))
  687. ;;; Buffers
  688. ;;;; cursor and mark
  689. (transient-mark-mode -1)
  690. (blink-cursor-mode -1)
  691. (setopt cursor-in-non-selected-windows nil
  692. visible-cursor nil) ;; stop blinking in xterm
  693. ;;;; uniquifiy
  694. (require 'uniquify)
  695. (setq uniquify-buffer-name-style 'forward
  696. uniquify-trailing-separator-p t)
  697. ;;;; autosave
  698. (setq auto-save-list-file-prefix "~/.emacs.d/auto-save-list/.saves-"
  699. auto-save-no-message t
  700. kill-buffer-delete-auto-save-files t)
  701. (setq lock-file-name-transforms
  702. '(("\\`/.*/\\([^/]+\\)\\'" "/tmp/emacs-lock/\\1" t)))
  703. ;;;; autorevert
  704. (setq auto-revert-check-vc-info nil)
  705. (setq auto-revert-verbose nil)
  706. (setq auto-revert-avoid-polling t)
  707. (setq auto-revert-mode-text "")
  708. (require 'autorevert)
  709. (global-auto-revert-mode 1)
  710. ;;;; attached buffers
  711. (defun jao-display-buffer-below-selected (buffer alist)
  712. (delete-other-windows-vertically)
  713. (display-buffer-below-selected buffer alist))
  714. (defun jao-attached-buffer-entry (name-rx height)
  715. `(,name-rx (display-buffer-reuse-window
  716. jao-display-buffer-below-selected)
  717. (window-height . ,(or height 25))))
  718. (defmacro jao-with-attached-buffer (name-rx height &rest body)
  719. (declare (indent defun))
  720. `(let ((display-buffer-alist '(,(jao-attached-buffer-entry name-rx height))))
  721. ,@body))
  722. (defun jao-define-attached-buffer (name-rx &optional height)
  723. (add-to-list 'display-buffer-alist
  724. (jao-attached-buffer-entry name-rx height)))
  725. (jao-define-attached-buffer "\\*eldoc\\( .*\\)?\\*" 0.33)
  726. ;;;; same mode
  727. (defun jao-buffer-same-mode (&optional mode pre-fn switch-fn)
  728. (interactive)
  729. (let* ((mode (or mode major-mode))
  730. (modes (if (symbolp mode) (list mode) mode))
  731. (pred `(lambda (b)
  732. (let ((b (get-buffer (if (consp b) (car b) b))))
  733. (member (buffer-local-value 'major-mode b)
  734. ',modes))))
  735. (buff (read-buffer "Buffer: " nil t pred)))
  736. (when pre-fn (funcall pre-fn))
  737. (if switch-fn (funcall switch-fn buff) (switch-to-buffer buff))))
  738. (defun jao-buffer-same-mode-cmd (&optional pop)
  739. (interactive "P")
  740. (jao-buffer-same-mode nil nil (and pop #'pop-to-buffer)))
  741. (global-set-key (kbd "C-c C-b") #'jao-buffer-same-mode-cmd)
  742. ;;;; projects
  743. (use-package project :demand t)
  744. (global-set-key "\C-xp" 'jao-prev-window)
  745. ;;;; buffer quit function (the triple ESC)
  746. (setq buffer-quit-function (lambda () t))
  747. ;;;; redisplay escape hatch
  748. ;; (setq max-redisplay-ticks 2250000)
  749. ;;;; scrolling
  750. (if window-system
  751. (setq scroll-preserve-screen-position 'always
  752. scroll-conservatively most-positive-fixnum
  753. scroll-margin 0
  754. scroll-step 2
  755. redisplay-skip-fontification-on-input t)
  756. (setq scroll-preserve-screen-position nil
  757. scroll-conservatively 0
  758. scroll-margin 0
  759. scroll-step 1
  760. redisplay-skip-fontification-on-input nil))
  761. ;;;; show diffs when running C-x s
  762. (add-to-list 'save-some-buffers-action-alist
  763. `("d"
  764. ,(lambda (buffer)
  765. (diff-buffer-with-file (buffer-file-name buffer)))
  766. "show diff between the buffer and its file"))
  767. ;;; Windows
  768. ;;;; splitting and switch
  769. (setq split-height-threshold 80
  770. split-width-threshold 144
  771. display-buffer-avoid-small-windows 20)
  772. (setq switch-to-buffer-preserve-window-point nil
  773. switch-to-buffer-obey-display-actions t
  774. switch-to-prev-buffer-skip 'this) ;; don't switch to a
  775. ;; buffer already visible in
  776. ;; this frame
  777. (global-set-key (kbd "C-x _") #'delete-other-windows-vertically)
  778. ;;;; first window
  779. (defvar jao-first-window--from nil)
  780. (defun jao-first-window ()
  781. "Go to previous windows in frame, remembering where we were."
  782. (interactive)
  783. (let ((cb (current-buffer)))
  784. (if (eq (get-buffer-window cb) (select-window (frame-first-window)))
  785. (when jao-first-window--from (pop-to-buffer jao-first-window--from))
  786. (setq jao-first-window--from cb))))
  787. (global-set-key (kbd "s-a") #'jao-first-window)
  788. (global-set-key (kbd "M-a") #'jao-first-window)
  789. ;;;; window navigation (custom)
  790. (defun jao-nth-window (n)
  791. (if (zerop n)
  792. 'jao-first-window
  793. `(lambda ()
  794. (interactive)
  795. (select-window (frame-first-window))
  796. (dotimes (x ,n) (other-window 1)))))
  797. (defun jao-prev-window ()
  798. "Go to previous window."
  799. (interactive)
  800. (other-window -1))
  801. (defvar jao-prev-window-repeat-map
  802. (let ((map (make-sparse-keymap)))
  803. (define-key map "p" 'jao-prev-window)
  804. (define-key map "P" (lambda ()
  805. (interactive)
  806. (setq repeat-map 'jao-prev-window-repeat-map)
  807. (other-window 1)))
  808. map)
  809. "Keymap to repeat `prev-window' key sequences. Used in `repeat-mode'.")
  810. (put 'jao-prev-window 'repeat-map jao-prev-window-repeat-map)
  811. (mapc (lambda (n)
  812. (global-set-key (format "\C-c%s" (1+ n)) (jao-nth-window n)))
  813. '(0 1 2 3 4 5 6 7 8))
  814. ;; transposing windows
  815. (defun transpose-windows (arg)
  816. "Transpose the buffers shown in two windows."
  817. (interactive "p")
  818. (let ((selector (if (>= arg 0) 'next-window 'previous-window)))
  819. (while (/= arg 0)
  820. (let ((this-win (window-buffer))
  821. (next-win (window-buffer (funcall selector))))
  822. (set-window-buffer (selected-window) next-win)
  823. (set-window-buffer (funcall selector) this-win)
  824. (select-window (funcall selector)))
  825. (setq arg (if (> arg 0) (1- arg) (1+ arg))))))
  826. (define-key ctl-x-4-map (kbd "t") 'transpose-windows)
  827. ;;;; winner mode
  828. (winner-mode 1)
  829. ;;; Frames
  830. ;;;; frame geometry
  831. (setq frame-resize-pixelwise t)
  832. (modify-all-frames-parameters
  833. `((horizontal-scroll-bars . nil)
  834. (vertical-scroll-bars . nil)
  835. (scroll-bar-width . 0)
  836. (menu-bar . nil)))
  837. ;;;; frame layout, title, etc
  838. (setq frame-title-format '("%b - emacs"))
  839. (use-package fringe)
  840. (fringe-mode)
  841. (menu-bar-mode -1)
  842. ;; (setting it to nil avoids mouse wrapping after other-frame)
  843. (setq focus-follows-mouse (and window-system t))
  844. (use-package scroll-bar)
  845. (set-scroll-bar-mode nil)
  846. (use-package tool-bar)
  847. (tool-bar-mode -1)
  848. (defalias 'jao-trisect 'jao-afio-trisect)
  849. (defun jao-bisect ()
  850. (interactive)
  851. (jao-trisect t)
  852. (other-window 1)
  853. (delete-window))
  854. ;;;; afio
  855. (use-package jao-afio
  856. :demand t
  857. :config (jao-afio-setup (not window-system))
  858. :bind (("C-c f" . 'jao-afio-goto-main)
  859. ("C-c g" . 'jao-afio-goto-mail)
  860. ("C-c w" . 'jao-afio-goto-www)
  861. ("C-c z" . 'jao-afio-goto-docs)
  862. ("C-c t" . 'jao-afio-goto-chats)
  863. ("C-c 0" . 'jao-afio-goto-scratch)
  864. ("M-o" . 'jao-afio-toggle)))
  865. (add-hook 'jao-afio-switch-hook 'jao-minibuffer-refresh t)
  866. (defun jao-current--frame-id ()
  867. (propertize (cond ((and (fboundp 'jao-exwm-enabled)
  868. (jao-exwm-enabled-p)
  869. (not (bound-and-true-p jao-exwm--use-afio))
  870. (boundp 'exwm-workspace-current-index))
  871. (format "F%s" exwm-workspace-current-index))
  872. (t jao-afio-use-frames (or (jao-afio-frame-name) ""))
  873. (t (format "%s" (or (jao-afio-frame-no) ""))))
  874. 'face 'font-lock-warning-face))
  875. (jao-minibuffer-add-variable '(jao-current--frame-id) 100)
  876. ;;; Writing and writing modes
  877. ;;;; copyright notices
  878. (setq copyright-year-ranges t)
  879. (add-hook 'write-file-functions 'copyright-update)
  880. ;;;; indent on yank
  881. (defvar jao-auto-indent-modes
  882. '(emacs-lisp-mode ;; clojure-mode
  883. scheme-mode objc-mode
  884. tuareg-mode c-mode c++-mode
  885. tcl-mode sql-mode
  886. perl-mode cperl-mode
  887. java-mode jde-mode
  888. LaTeX-mode TeX-mode))
  889. (defadvice yank (after indent-region activate)
  890. (if (member major-mode jao-auto-indent-modes)
  891. (indent-region (region-beginning) (region-end) nil)))
  892. ;;;; org mode
  893. (require 'jao-custom-org)
  894. ;;;; blog
  895. (require 'jao-custom-blog)
  896. ;;;; text-ish mode settings
  897. ;; SENTENCES separated by just one space
  898. (setq sentence-end "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*")
  899. (setq sentence-end-double-space t)
  900. ;; copy rectangle
  901. (defun kill-rectangle-save (start end)
  902. "Save the region-rectangle as the last killed one."
  903. (interactive "r")
  904. (require 'rect) ; Make sure killed-rectangle is defvar'ed.
  905. (setq killed-rectangle (extract-rectangle start end))
  906. (message "Rectangle saved"))
  907. ;; text mode, autoinserts and write hooks
  908. (setq default-major-mode 'text-mode)
  909. (add-hook 'text-mode-hook 'turn-on-auto-fill)
  910. ;;;; dictionaries
  911. (use-package dictionary
  912. :init (setq dictionary-use-single-buffer t
  913. dictionary-server "localhost")
  914. :commands (dictionary-search
  915. dictionary-match-words
  916. dictionary-lookup-definition
  917. dictionary
  918. dictionary-mouse-popup-matching-words
  919. dictionary-popup-matching-words
  920. dictionary-tooltip-mode
  921. global-dictionary-tooltip-mode)
  922. :bind (("C-c d" . dictionary-search)))
  923. (use-package ispell
  924. :custom ((ispell-personal-dictionary
  925. (expand-file-name "~/.emacs.d/ispell.dict"))))
  926. (use-package reverso
  927. :ensure t
  928. :init (setq reverso-languages '(english spanish french german)))
  929. ;; (use-package wordreference
  930. ;; :ensure t
  931. ;; :init (setq wordreference-target-lang "es"
  932. ;; wordreference-source-lang "en")
  933. ;; :bind (("C-c D" . wordreference-search)))
  934. ;;;; markdown
  935. (use-package markdown-mode
  936. :ensure t
  937. :init (setq markdown-command '("pandoc" "--from=markdown" "--to=html5")
  938. markdown-asymmetric-header t
  939. markdown-enable-wiki-links t
  940. markdown-wiki-link-fontify-missing t
  941. markdown-enable-math nil ;; toggle with M-x markdown-toggle-math
  942. markdown-link-space-sub-char "-"
  943. markdown-gfm-additional-languages '("whizzml" "flatline")
  944. markdown-hide-urls t
  945. markdown-hide-markup nil
  946. markdown-fontify-code-blocks-natively t
  947. markdown-fontify-whole-heading-line t
  948. markdown-unordered-list-item-prefix t)
  949. :hook (markdown-mode . outline-minor-mode)
  950. :config
  951. (dolist (u '("doc" "message" "notmuch"))
  952. (add-to-list 'markdown-uri-types u))
  953. (use-package markdown-toc :ensure t))
  954. ;; used by markdown mode to edit code blocks
  955. (use-package edit-indirect :ensure t)
  956. (dolist (ext '("\\.md$" "\\.markdown$"))
  957. (add-to-list 'auto-mode-alist (cons ext 'markdown-mode)))
  958. ;;;; TeX and LaTex
  959. (use-package tex-site
  960. :ensure auctex
  961. :init
  962. (setq TeX-auto-save t)
  963. (setq TeX-parse-self t)
  964. (setq TeX-a4-paper t)
  965. (setq TeX-auto-local ".tex-auto-local")
  966. ;; Preferred view format: dvi, ps, pdf, pdfs
  967. (setq TeX-view-format "pdf")
  968. (setq-default TeX-master "../main") ; nil to ask
  969. (setq TeX-view-program-selection
  970. ;; '((output-dvi "open")
  971. ;; (output-pdf "open")
  972. ;; (output-html "open"))
  973. '(((output-dvi has-no-display-manager) "dvi2tty")
  974. ((output-dvi style-pstricks) "dvips and gv")
  975. (output-dvi "xdvi")
  976. (output-pdf "xdg-open")
  977. (output-html "xdg-open")))
  978. ;; to make RefTeX faster for large documents, try these:
  979. (setq reftex-enable-partial-scans t)
  980. (setq reftex-save-parse-info t)
  981. (setq reftex-use-multiple-selection-buffers t)
  982. ;; to integrate with AUCTeX
  983. (setq reftex-plug-into-AUCTeX t)
  984. (setq reftex-ref-style-default-list
  985. '("Hyperref" "Varioref" "Fancyref"))
  986. (setq LaTeX-command "latex -shell-escape")
  987. (setq LaTeX-biblatex-use-Biber t)
  988. (setq bibtex-dialect 'biblatex)
  989. :config
  990. (add-hook 'TeX-after-compilation-finished-functions 'TeX-revert-document-buffer)
  991. (add-hook 'LaTeX-mode-hook 'turn-on-reftex))
  992. ;;; Browsing
  993. ;;;; variables
  994. (defvar jao-browse-doc-use-emacs-p t)
  995. (defvar jao-browse-url-function nil)
  996. (defvar jao-browse-url-external-function nil)
  997. ;;;; url around point
  998. (defun jao-url-around-point (&optional current-url)
  999. (or (and (fboundp 'w3m-anchor) (w3m-anchor))
  1000. (shr-url-at-point nil)
  1001. (ffap-url-at-point)
  1002. (thing-at-point 'url)
  1003. (when current-url
  1004. (or (and (fboundp 'w3m-anchor) (w3m-anchor))
  1005. (and (derived-mode-p 'eww-mode) (plist-get eww-data :url))))))
  1006. (defun jao--url-prompt (&optional prefix)
  1007. (let* ((def (jao-url-around-point t))
  1008. (prompt (concat prefix "URL" (if def (format " (%s): " def) ": "))))
  1009. (read-string prompt nil nil def)))
  1010. ;;;; downloads using wget
  1011. (defun jao-wget--get-title (filename)
  1012. (or (and (derived-mode-p 'w3m-mode) (w3m-current-title))
  1013. (plist-get eww-data :title)
  1014. (and (not (string-blank-p (or filename "")))
  1015. (subst-char-in-string ?- ? (capitalize (file-name-base filename))))))
  1016. (defun jao-wget (url &optional user pwd)
  1017. "Download URL using wget and kill a link for an org note."
  1018. (let* ((def (file-name-nondirectory url))
  1019. (pmt (format "Save %s to: " url))
  1020. (read-file-name-function nil)
  1021. (dest (expand-file-name
  1022. (read-file-name pmt jao-sink-dir nil nil def)))
  1023. (title (jao-wget--get-title dest))
  1024. (src-url (or (jao-url-around-point t) (file-name-directory url)))
  1025. (auth (when (and user pwd)
  1026. `(,(format "--http-user=%s" user)
  1027. ,(format "--http-password=%s" pwd))))
  1028. (lnk (concat "doc:" (file-name-nondirectory dest))))
  1029. (switch-to-buffer-other-window (get-buffer-create "*downloads*"))
  1030. (erase-buffer)
  1031. (kill-new (format "%s (from %s)"
  1032. (org-link-make-string lnk title)
  1033. (org-link-make-string src-url "here")))
  1034. (apply 'make-term `("downloads" "wget" nil ,@auth "-O" ,dest ,url))))
  1035. (defun jao-download (url &optional pws)
  1036. "Download URL using wget"
  1037. (interactive (list (jao--url-prompt)))
  1038. (when url
  1039. (let ((usr (and pws (read-string "Login name: ")))
  1040. (pwd (and pws (read-passwd "Password: "))))
  1041. (jao-wget url usr pwd))))
  1042. (with-eval-after-load "embark"
  1043. (define-key embark-url-map (kbd "d") #'jao-download))
  1044. ;;;; video
  1045. (defvar jao-video--url-rx
  1046. (format "^https?://\\(?:www\\.\\)?%s/.+"
  1047. (regexp-opt '("youtu.be"
  1048. "youtube.com"
  1049. "blip.tv"
  1050. "vimeo.com"
  1051. "infoq.com")
  1052. t)))
  1053. (defvar jao-video--ext-rx
  1054. (format "^https?://.+/.+\\.%s" (regexp-opt '("mp3" "webm" "mp4"))))
  1055. (defun jao-video--url-p (url)
  1056. (or (string-match-p jao-video--url-rx url)
  1057. (string-match-p jao-video--ext-rx url)))
  1058. (defun jao--remote-run (url prg)
  1059. (let ((args (format "%s %s" prg (shell-quote-argument url))))
  1060. (start-process-shell-command prg nil args)))
  1061. (defun jao--mpv (url &rest _args) (jao--remote-run url "mpv"))
  1062. (defun jao--vlc (url &rest _args) (jao--remote-run url "vlc"))
  1063. (defvar jao--video-player 'jao--mpv)
  1064. (defun jao-view-video (url)
  1065. "Tries to stream a video from the current or given URL"
  1066. (interactive (list (jao--url-prompt "Video ")))
  1067. (when url (funcall jao--video-player url)))
  1068. (defun jao-maybe-view-video (url &rest _ignored)
  1069. (interactive)
  1070. (if (y-or-n-p "View video (y) or web page (n)? ")
  1071. (jao-view-video url)
  1072. (funcall jao-browse-url-function url)))
  1073. ;;;; web browsers
  1074. (defun jao-www--buffer-p (b)
  1075. (with-current-buffer b
  1076. (or (derived-mode-p 'w3m-mode 'eww-mode)
  1077. (and (boundp 'exwm-class-name)
  1078. (member exwm-class-name '("vlc" "mpv"))))))
  1079. (require 'jao-custom-eww)
  1080. ;; (require 'jao-custom-w3m)
  1081. ;;;; browse-url
  1082. (require 'browse-url)
  1083. (setq browse-url-generic-program "~/bin/firehog")
  1084. (defun jao-browse-with-external-browser (&rest url)
  1085. "Browse with external hogging"
  1086. (interactive "s")
  1087. (let ((url (or (car url) (jao-url-around-point))))
  1088. (if (not url)
  1089. (message "No URL at point")
  1090. (cond ((and (jao-exwm-enabled-p) (fboundp 'jao-exwm-firefox))
  1091. (jao-exwm-firefox))
  1092. (jao-river-enabled (jao-river-to-ws 2))
  1093. (jao-sway-enabled (jao-sway-firefox)))
  1094. (browse-url-generic url))))
  1095. (setq jao-browse-url-external-function 'jao-browse-with-external-browser)
  1096. (defun jao--fln (url)
  1097. (shell-quote-argument
  1098. (if (string-match "^[^:]*:/*?\\(/?[^/].*\\)" url)
  1099. (match-string-no-properties 1 url)
  1100. url)))
  1101. (defun jao--browse-doc (url &rest _ignored)
  1102. (let* ((url (substring-no-properties url))
  1103. (file (jao--fln url)))
  1104. (when file
  1105. (unless (file-exists-p file)
  1106. (error "File %s does not exist" file))
  1107. (jao-open-doc file))))
  1108. (defun jao--make-file-rx (exts)
  1109. (format "file:/?/?.+\\.%s$" (regexp-opt exts)))
  1110. (defvar jao--see-exts (jao--make-file-rx '("jpg" "jpeg" "png")))
  1111. (defvar jao--doc-exts
  1112. (jao--make-file-rx '("ps" "ps.gz" "pdf" "dvi" "djvu" "chm")))
  1113. (defvar jao-browse-url-wget-exts
  1114. '("ps" "pdf" "dvi" "djvu" "zip" "gz" "tgz"))
  1115. (defvar jao-browse-external-domains
  1116. '("github.com" "gitlab.com" "slack.com" "spotify.com" "drive.google.com"
  1117. "meet.google.com" "docs.google.com" "x.com" "twitter.com"
  1118. "t.com" "linkedin.com" "bigml.com" "slack.com" "zoom.us"))
  1119. (defvar jao-browse--external-regexp
  1120. (format "https?://.*%s\\(/.*\\)?"
  1121. (regexp-opt jao-browse-external-domains)))
  1122. (defun jao-wget--regexp ()
  1123. (concat "^http[s]?://.+\\(\\."
  1124. (mapconcat 'identity jao-browse-url-wget-exts "\\|\\.")
  1125. "\\)\\'"))
  1126. (defun jao--see (url &rest _r)
  1127. (start-process-shell-command "see" nil (format "see %s" (jao--fln url))))
  1128. (defun jao--find-file-other-window (url &rest _)
  1129. (find-file-other-window (jao--fln url)))
  1130. (defvar jao-browse--sound-rx
  1131. (format "^https?://.*/.*\\.%s" (regexp-opt '("mp3" "flv"))))
  1132. (defun jao-browse-play-sound-url (url &rest _)
  1133. (jao-mpc-add-or-play-url url))
  1134. (defun jao-browse-url-browse (&rest args)
  1135. (apply jao-browse-url-function args))
  1136. (setq browse-url-handlers
  1137. `((jao-video--url-p . jao-maybe-view-video)
  1138. (,jao--doc-exts . jao--browse-doc)
  1139. (,jao--see-exts . jao--see)
  1140. ("^file://?.+\\.html?$" . ,jao-browse-url-function)
  1141. ("^file://?" . jao--find-file-other-window)
  1142. (,jao-browse--external-regexp . ,jao-browse-url-external-function)
  1143. ("^https?://.*\\.gotomeeting\\.com\\.*" . browse-url-chrome)
  1144. (,jao-browse--sound-rx . jao-browse-play-sound-url)
  1145. (,(jao-wget--regexp) . jao-download)
  1146. ("." . jao-browse-url-browse)))
  1147. (when (< emacs-major-version 28)
  1148. (setf (alist-get 'jao-video--url-p browse-url-handlers nil t) nil)
  1149. (setq browse-url-browser-function browse-url-handlers))
  1150. ;;;; subscribe to rss using r2e
  1151. (autoload 'View-quit "view")
  1152. (defun jao-rss--find-url ()
  1153. (save-excursion
  1154. (when (derived-mode-p 'w3m-mode 'eww-mode)
  1155. (if (fboundp 'w3m-view-source) (w3m-view-source) (eww-view-source)))
  1156. (goto-char (point-min))
  1157. (when (re-search-forward
  1158. "type=\"application/\\(?:atom\\|rss\\)\\+xml\" +" nil t)
  1159. (let ((url (save-excursion
  1160. (when (re-search-forward
  1161. "href=\"\\([^\n\"]+\\)\"" nil t)
  1162. (match-string-no-properties 1))))
  1163. (title (when (re-search-forward
  1164. "\\(?:title=\"\\([^\n\"]+\\)\" +\\)" nil t)
  1165. (match-string-no-properties 1))))
  1166. (cond ((derived-mode-p 'w3m-view-mode) (w3m-view-source))
  1167. ((string-match-p ".*\\*eww-source\\b.*" (buffer-name))
  1168. (View-quit)))
  1169. (when url (cons url (or title "")))))))
  1170. (defun jao-rss2e-append (name url mbox)
  1171. (with-current-buffer (find-file-noselect "~/.config/rss2email.cfg")
  1172. (goto-char (point-max))
  1173. (insert "[feed." name "]\nurl = " url)
  1174. (insert "\nto = " mbox "+" name "@localhost")
  1175. (insert "\nmaildir-mailbox = " mbox "\n\n")
  1176. (save-buffer)))
  1177. (defun jao-rss--feeds-dirs ()
  1178. (mapcar (lambda (d) (cadr (split-string d "\\.")))
  1179. (directory-files "~/.emacs.d/gnus/Mail/" nil "^feeds")))
  1180. (defun jao-rss-subscribe (url)
  1181. "Subscribe to a given RSS URL. If URL not given, look for it."
  1182. (interactive (list (or (jao-url-around-point)
  1183. (jao-rss--find-url)
  1184. (read-string "Feed URL: "))))
  1185. (let* ((url+title (ensure-list url))
  1186. (url (car url+title))
  1187. (title (cdr url+title)))
  1188. (unless url (error "No feeds found"))
  1189. (let ((url (if (string-match "^feed:" url) (substring url 5) url)))
  1190. (when (y-or-n-p (format "Subscribe to <%s>? " url))
  1191. (let* ((name (read-string "Feed name: " title))
  1192. (cats (cons "prog" (jao-notmuch--subtags "feeds")))
  1193. (cat (completing-read "Category: " cats nil t))
  1194. (subs (format "r2e add %s '%s' feeds.%s@localhost"
  1195. name url cat)))
  1196. ;; (jao-rss2e-append name url cat)
  1197. (shell-command-to-string subs)
  1198. (shell-command (format "r2e run %s" name)))))))
  1199. ;;; PDFs and other docs
  1200. ;;;; open pdfs
  1201. (use-package jao-pdf :demand t)
  1202. (use-package saveplace-pdf-view
  1203. :ensure t
  1204. :demand t
  1205. :after doc-view)
  1206. (setq jao-open-doc-fun 'jao-find-or-open)
  1207. (setq jao-org-open-pdf-fun 'jao-find-or-open)
  1208. (defun jao-zathura-open (file page)
  1209. (let ((id (jao-x11-search-window (jao-pdf-zathura-title-rx file))))
  1210. (if (string-blank-p id)
  1211. (progn
  1212. (when jao-xmonad-enabled (jao-x11-goto-ws 2))
  1213. (jao-shell-exec (jao-pdf-zathura-open-cmd file page)))
  1214. (let* ((page (if page (format " && xdotool type %dg" page) ""))
  1215. (cmd (format "xdotool windowactivate %s%s" id page)))
  1216. (jao-shell-exec cmd t)))))
  1217. (defun jao-x11-zathura-goto-org (&optional title no-ask)
  1218. (let ((title (or title (jao-shell-string "xdotool"
  1219. "getactivewindow"
  1220. "getwindowname"))))
  1221. (jao-org-open-from-zathura title no-ask)))
  1222. (defun jao-find-or-open (file &optional page height)
  1223. (cond ((and jao-browse-doc-use-emacs-p window-system)
  1224. (let* ((buffs (buffer-list))
  1225. (b (catch 'done
  1226. (while buffs
  1227. (when (string-equal (buffer-file-name (car buffs)) file)
  1228. (throw 'done (car buffs)))
  1229. (setq buffs (cdr buffs))))))
  1230. (jao-afio-goto-docs)
  1231. (if b (pop-to-buffer b) (find-file file))
  1232. (when page (jao-doc-view-goto-page page height))))
  1233. (jao-river-enabled (jao-river-open-with-zathura file page))
  1234. (jao-sway-enabled (jao-sway-open-with-zathura file page))
  1235. (t (jao-zathura-open file page))))
  1236. (defun jao-open-doc (&optional file page height)
  1237. (interactive)
  1238. (when-let (file (or file
  1239. (read-file-name "Document: "
  1240. (concat jao-org-dir "/doc/"))))
  1241. (funcall jao-open-doc-fun file page height)))
  1242. (defun jao-select-pdf ()
  1243. (interactive)
  1244. (jao-buffer-same-mode '(pdf-view-mode doc-view-mode)
  1245. #'jao-afio-goto-docs))
  1246. (defun jao-open-with-zathura ()
  1247. (interactive)
  1248. (when-let (f buffer-file-name)
  1249. (let ((p (jao-doc-view-current-page)))
  1250. (cond (jao-river-enabled (jao-river-open-with-zathura f p))
  1251. (jao-sway-enabled (jao-sway-open-with-zathura f p))
  1252. (t (jao-zathura-open f p))))))
  1253. ;; doc:// links for browse-url
  1254. (defun jao-open-doc-url (url &rest _)
  1255. (when (string-match "doc://\\([^?]+\\)\\(\\?.*\\)?" url)
  1256. (let ((file (match-string 1 url))
  1257. (page (when-let* ((qs (match-string 2 url))
  1258. (long (> (length qs) 1))
  1259. (ps (url-parse-query-string (substring qs 1)))
  1260. (pn (cadr (assoc "page" ps))))
  1261. (string-to-number pn))))
  1262. (jao-open-doc (expand-file-name (concat "doc/" file) jao-org-dir) page))))
  1263. (add-to-list 'browse-url-handlers (cons "^doc://.+" 'jao-open-doc-url))
  1264. ;;;; doc-view
  1265. (use-package doc-view
  1266. :init
  1267. (setq doc-view-cache-directory "~/.emacs.d/cache/docview"
  1268. doc-view-resolution 110
  1269. doc-view-continuous t
  1270. doc-view-conversion-refresh-interval 1
  1271. doc-view-mupdf-use-svg t)
  1272. :hook ((doc-view-mode . jao-doc-session-mark))
  1273. :bind (:map doc-view-mode-map
  1274. ("j" . doc-view-next-line-or-next-page)
  1275. ("J" . doc-view-search-next-match)
  1276. ("k" . doc-view-previous-line-or-previous-page)
  1277. ("K" . doc-view-search-previous-match)
  1278. ("z" . jao-open-with-zathura)))
  1279. (use-package jao-doc-session :demand t)
  1280. (use-package jao-doc-view
  1281. :demand t
  1282. :bind (:map doc-view-mode-map
  1283. ("b" . jao-doc-view-back)
  1284. ("B" . jao-doc-view-forward)
  1285. ("S" . jao-doc-session-save)
  1286. ("u" . jao-doc-view-visit-url)))
  1287. ;;;; epub
  1288. (use-package nov
  1289. :ensure t
  1290. :after doc-view
  1291. :init (setq nov-variable-pitch t
  1292. nov-text-width nil)
  1293. :config
  1294. (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
  1295. (defun jao-nov-register-session ()
  1296. (jao-doc-session-mark nov-file-name))
  1297. (add-hook 'nov-mode-hook #'jao-nov-register-session))
  1298. ;;;; transient
  1299. (defun jao-org-pdf-goto-org-linking ()
  1300. (interactive)
  1301. (jao-org-pdf-goto-org 4))
  1302. (jao-transient-major-mode doc-view
  1303. ["Notes"
  1304. ("o" "notes file" jao-org-pdf-goto-org)
  1305. ("O" "notes file, linking" jao-org-pdf-goto-org-linking)]
  1306. ["Navigation"
  1307. ("b" "back jump" jao-doc-view-back)
  1308. ("B" "forward jump" jao-doc-view-back)
  1309. ("u" "visit URL" jao-doc-view-visit-url)]
  1310. ["Slices"
  1311. ("cb" "bounding box" doc-view-set-slice-from-bounding-box)
  1312. ("cm" "using mouse" doc-view-set-slice-using-mouse)]
  1313. ["Session"
  1314. ("s" "load session" jao-afio-open-pdf-session)
  1315. ("S" "save session" jao-doc-session-save)
  1316. ("d" "visit cache directory" doc-view-dired-cache)]
  1317. ["External viewers"
  1318. ("z" "open with zathura" jao-open-with-zathura)])
  1319. (with-eval-after-load "pdf-view"
  1320. (jao-transient-major-mode pdf-view
  1321. ["Notes"
  1322. ("o" "notes file" jao-org-pdf-goto-org)
  1323. ("O" "notes file, linking" jao-org-pdf-goto-org-linking)]
  1324. ["Navigation"
  1325. ("b" "back jump" pdf-history-backward)
  1326. ("f" "forward jump" pdf-history-forward)]
  1327. ["Session"
  1328. ("s" "load session" jao-afio-open-pdf-session)
  1329. ("S" "save session" jao-doc-session-save)]
  1330. ["External viewers"
  1331. ("z" "open with zathura" jao-open-with-zathura)]))
  1332. ;; (transient-get-suffix 'jao-transient-pdf-view '(0 -1))
  1333. ;;; Email
  1334. (require 'jao-custom-email)
  1335. ;;; Shells and terms
  1336. ;;;; shell modes
  1337. (setq sh-basic-offset 2)
  1338. ;; translates ANSI colors into text-properties, for eshell
  1339. (autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
  1340. (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
  1341. (defvar jao-use-vterm nil)
  1342. (defvar jao-use-eat nil)
  1343. (add-to-list 'display-buffer-alist
  1344. '("\\*Async Shell Command\\*" (display-buffer-no-window)))
  1345. ;;;; eat
  1346. (use-package eat
  1347. :ensure t
  1348. :commands jao-exec-in-term
  1349. :init (setq jao-use-eat t
  1350. eat-kill-buffer-on-exit t
  1351. eat-enable-yank-to-terminal t)
  1352. :hook ((eshell-mode . eat-eshell-mode)
  1353. (eshell-mode . eat-eshell-visual-command-mode))
  1354. :diminish ((eat-eshell-mode . "")))
  1355. ;;;; term
  1356. (defvar-local jao-term--cmd nil)
  1357. (defun jao-term--find (cmd)
  1358. (seq-find (lambda (b)
  1359. (with-current-buffer b
  1360. (and (derived-mode-p 'eat-mode 'term-mode 'vterm-mode)
  1361. (string= (or jao-term--cmd "") cmd))))
  1362. (buffer-list)))
  1363. (defun jao-exec-in-term (cmd &optional name)
  1364. (interactive "SCommand")
  1365. (require 'eat nil t)
  1366. (cond ((and jao-use-vterm (fboundp 'jao-exec-in-vterm))
  1367. (jao-exec-in-vterm cmd name))
  1368. (jao-use-eat (let ((eat-term-name "xterm-256color"))
  1369. (with-current-buffer (eat cmd t)
  1370. (setq-local jao-term--cmd cmd))))
  1371. (t (ansi-term "bash" name)
  1372. (set-process-sentinel (get-buffer-process (current-buffer))
  1373. (lambda (process event)
  1374. (when (string= event "finished\n")
  1375. (kill-buffer (process-buffer process)))))
  1376. (setq-local jao-term--cmd cmd)
  1377. (term-send-string nil (concat cmd " ; exit\n")))))
  1378. (defmacro jao-def-exec-in-term (name cmd &rest prelude)
  1379. `(defun ,(intern (format "jao-term-%s" name)) (&optional term)
  1380. (interactive "P")
  1381. ,@prelude
  1382. (let ((jao-use-vterm (if term (not jao-use-vterm) jao-use-vterm)))
  1383. (if-let ((b (jao-term--find ,cmd)))
  1384. (pop-to-buffer b)
  1385. (jao-exec-in-term ,cmd ,(format "*%s*" name))))))
  1386. ;;;; eshell
  1387. ;;;;; basic custom
  1388. (use-package eshell
  1389. :init
  1390. (setq eshell-directory-name "~/.emacs.d/eshell"
  1391. eshell-hist-ignoredups 'erase
  1392. eshell-history-size 1000000
  1393. eshell-error-if-no-glob nil)
  1394. (defun jao-eshell--outline ()
  1395. (setq-local outline-regexp eshell-prompt-regexp))
  1396. :config (setq eshell-prompt-repeat-map nil)
  1397. :hook (eshell-mode . jao-eshell--outline))
  1398. ;;;;; colors
  1399. (autoload 'ansi-color-apply "ansi-color")
  1400. ;; (add-hook 'eshell-preoutput-filter-functions 'ansi-color-filter-apply)
  1401. (add-hook 'eshell-preoutput-filter-functions 'ansi-color-apply)
  1402. (use-package eshell-syntax-highlighting
  1403. :after esh-mode
  1404. :ensure t
  1405. :config
  1406. ;; Enable in all Eshell buffers.
  1407. (eshell-syntax-highlighting-global-mode +1))
  1408. ;;;;; visual commands
  1409. (require 'em-term)
  1410. (dolist (c '("editor" "more" "wget" "dict" "vim" "links" "w3m" "guile"
  1411. "zmore" "pager" "aptitude" "su" "htop" "top"
  1412. "screen" "whizzml" "iex" "spt"))
  1413. (add-to-list 'eshell-visual-commands c))
  1414. (setq eshell-visual-subcommands '(("git" "log" "diff" "show")
  1415. ("sudo" "vim")
  1416. ("rebar3" "shell"))
  1417. eshell-destroy-buffer-when-process-dies nil
  1418. eshell-escape-control-x t)
  1419. ;;;;; bol
  1420. (defun jao-eshell-maybe-bol ()
  1421. (interactive)
  1422. (let ((p (point)))
  1423. (eshell-bol)
  1424. (if (= p (point))
  1425. (beginning-of-line))))
  1426. ;;;;; prompt
  1427. ;; tracking git repos
  1428. (defun jao-eshell--git-dirty ()
  1429. (shell-command-to-string "git diff-index --quiet HEAD -- || echo -n '*'"))
  1430. (use-package git-ps1-mode
  1431. :ensure t
  1432. :init (setq git-ps1-mode-showupstream "1"
  1433. git-ps1-mode-showdirtystate "1"))
  1434. (defun jao-eshell--git-info ()
  1435. (if (fboundp 'git-ps1-mode-get-current)
  1436. (git-ps1-mode-get-current)
  1437. (let ((desc (shell-command-to-string "git branch --no-color")))
  1438. (when (string-match "^* \\(\\<.+\\>\\)" desc)
  1439. (format "%s%s" (match-string 1 desc) (jao-eshell--git-dirty))))))
  1440. (defun jao-eshell--git-current-branch (suffix)
  1441. (let ((desc (or (jao-eshell--git-info) "")))
  1442. (cond ((and (string-empty-p desc) suffix) (format " (%s)" suffix))
  1443. ((string-empty-p (or suffix "")) (format " (%s)" desc))
  1444. (t (format " (%s %s)" desc suffix)))))
  1445. (defun jao-eshell--virtualenv ()
  1446. (let ((venv (getenv "VIRTUAL_ENV")))
  1447. (when (and venv (string-match ".*/\\([^/]+\\)/$" venv))
  1448. (match-string-no-properties 1 venv))))
  1449. (defun jao-eshell-prompt-function ()
  1450. (let* ((venv (jao-eshell--virtualenv))
  1451. (venv (if venv (format "%s" venv) "")))
  1452. (concat (abbreviate-file-name (eshell/pwd))
  1453. (jao-eshell--git-current-branch venv)
  1454. (if (= (user-uid) 0) " # " " $ "))))
  1455. (setq eshell-prompt-function 'jao-eshell-prompt-function)
  1456. ;;;;; in-term
  1457. (defun eshell/in-term (prog &rest args)
  1458. (switch-to-buffer
  1459. (apply #'make-term (format "in-term %s %s" prog args) prog nil args))
  1460. (term-mode)
  1461. (term-char-mode))
  1462. ;;;;; dir navigation
  1463. (use-package eshell-up
  1464. :ensure t
  1465. :config (setq eshell-up-print-parent-dir t))
  1466. (use-package eshell-autojump :ensure t)
  1467. ;;;;; completion
  1468. (defun jao-eshell-completion-capf ()
  1469. (let* ((b (save-excursion (eshell-bol) (point)))
  1470. (c (bash-completion-dynamic-complete-nocomint b (point) t)))
  1471. (when (and c (listp c))
  1472. (append c '(:exclusive no)))))
  1473. (defun jao-eshell--set-up-completion ()
  1474. (setq-local completion-styles '(basic partial-completion)
  1475. completion-at-point-functions
  1476. '(jao-eshell-completion-capf
  1477. pcomplete-completions-at-point t)))
  1478. (use-package bash-completion
  1479. :ensure t
  1480. :hook (eshell-mode . jao-eshell--set-up-completion))
  1481. ;;;;; toggle
  1482. (use-package jao-eshell-here
  1483. :demand t
  1484. :config (jao-define-attached-buffer "^\\*eshell" 0.5)
  1485. :bind (("<f1>" . jao-eshell-here-toggle)
  1486. ("C-<f1>" . jao-eshell-here-toggle-new)))
  1487. ;;;;; workarounds
  1488. ;; at some point, bash completion started insertig the TAB
  1489. ;; after the commands ends
  1490. (defun jao-eshell--clean-prompt ()
  1491. (eshell-bol)
  1492. (ignore-errors (kill-line)))
  1493. (add-hook 'eshell-after-prompt-hook 'jao-eshell--clean-prompt)
  1494. ;;;;; keybindings
  1495. (defun jao-eshell--kbds ()
  1496. (define-key eshell-mode-map "\C-a" 'jao-eshell-maybe-bol)
  1497. (define-key eshell-mode-map "\C-ci" 'consult-outline))
  1498. (jao-eshell--kbds)
  1499. ;;; Version control and CI
  1500. ;;;; vc options
  1501. (setq vc-follow-symlinks t)
  1502. (setq auto-revert-check-vc-info nil)
  1503. ;;;; diff fringe indicators (diff-hl)
  1504. (use-package diff-hl
  1505. :ensure t
  1506. :custom ((diff-hl-draw-borders nil)
  1507. (diff-hl-side 'right)
  1508. (diff-hl-margin-symbols-alist
  1509. '((insert . "█")
  1510. (delete . "█")
  1511. (change . "█")
  1512. (unknown . "█")
  1513. (ignored . "█"))))
  1514. :config
  1515. (map-keymap (lambda (_k cmd)
  1516. (put cmd 'repeat-map 'diff-hl-command-map))
  1517. diff-hl-command-map)
  1518. (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
  1519. (global-diff-hl-mode 1)
  1520. (unless (display-graphic-p) (diff-hl-margin-mode 1))
  1521. ;;;; magit/forge
  1522. (use-package magit
  1523. :ensure t
  1524. :commands magit-status
  1525. :init
  1526. (setq magit-status-initial-section nil
  1527. magit-define-global-key-bindings nil
  1528. magit-completing-read-function 'magit-builtin-completing-read
  1529. magit-display-buffer-function
  1530. 'magit-display-buffer-fullcolumn-most-v1
  1531. magit-delete-by-moving-to-trash nil
  1532. magit-last-seen-setup-instructions "1.4.0"
  1533. magit-log-edit-confirm-cancellation t
  1534. magit-omit-untracked-dir-contents t
  1535. magit-process-connection-type nil
  1536. magit-push-always-verify nil
  1537. magit-repository-directories
  1538. '(("/home/jao/usr/bigml" . 2)
  1539. ("/home/jao/usr/jao" . 3)
  1540. ("/usr/local/src" . 1))
  1541. magit-save-repository-buffers 'dontask
  1542. magit-section-visibility-indicator '("…" . t)
  1543. magit-status-buffer-switch-function 'switch-to-buffer
  1544. magit-status-show-hashes-in-headers t))
  1545. ;;;; forge
  1546. (use-package forge
  1547. :ensure t
  1548. :after magit
  1549. :init
  1550. (setq forge-topic-list-limit (cons 100 -1)
  1551. forge-pull-notifications nil)
  1552. :config
  1553. (use-package embark-vc :ensure t)
  1554. :bind ((:map forge-topic-mode-map ("M-w" . copy-region-as-kill))))
  1555. ;;;; code reviews
  1556. (use-package code-review
  1557. :disabled t
  1558. :ensure t
  1559. :after forge
  1560. :bind (:map magit-status-mode-map
  1561. ("C-c C-r" . code-review-forge-pr-at-point)))
  1562. ;;;; other git packages
  1563. (use-package git-timemachine :ensure t)
  1564. (use-package consult-git-log-grep
  1565. :ensure t
  1566. :custom (consult-git-log-grep-open-function #'magit-show-commit)
  1567. :bind (("C-c K" . consult-git-grep)))
  1568. ;; git config --local git-link.remote / git-link.branch
  1569. (use-package git-link :ensure t)
  1570. (use-package git-modes :ensure t)
  1571. ;;;; jenkins
  1572. (use-package jenkins
  1573. :ensure t
  1574. :init
  1575. ;; one also needs jenkins-api-token, jenkins-username and jenkins-url
  1576. ;; optionally: jenkins-colwidth-id, jenkins-colwidth-last-status
  1577. (setq jenkins-colwidth-name 35)
  1578. :config
  1579. (defun jao-jenkins-first-job (&rest _)
  1580. (interactive)
  1581. (goto-char (point-min))
  1582. (when (re-search-forward "^- Job" nil t)
  1583. (goto-char (match-beginning 0))))
  1584. (add-hook 'jenkins-job-view-mode-hook #'jao-jenkins-first-job)
  1585. (advice-add 'jenkins-job-render :after #'jao-jenkins-first-job)
  1586. (defun jenkins-refresh-console-output ()
  1587. (interactive)
  1588. (let ((n (buffer-name)))
  1589. (when (string-match "\\*jenkins-console-\\([^-]+\\)-\\(.+\\)\\*$" n)
  1590. (jenkins-get-console-output (match-string 1 n) (match-string 2 n))
  1591. (goto-char (point-max)))))
  1592. :bind (:map jenkins-job-view-mode-map
  1593. (("n" . next-line)
  1594. ("p" . previous-line)
  1595. ("f" . jao-jenkins-first-job)
  1596. ("RET" . jenkins--show-console-output-from-job-screen))
  1597. :map jenkins-console-output-mode-map
  1598. (("n" . next-line)
  1599. ("p" . previous-line)
  1600. ("g" . jenkins-refresh-console-output))))
  1601. ;;; Programming
  1602. ;;;; automatic modes
  1603. (add-to-list 'auto-mode-alist '("\\.mix\\'" . hexl-mode))
  1604. (add-to-list 'auto-mode-alist '("\\.m4\\'" . m4-mode))
  1605. (add-to-list 'auto-mode-alist '("\\.am\\'" . makefile-mode))
  1606. (add-to-list 'auto-mode-alist '("\\.pl\\'\\|\\.pm\\'" . cperl-mode))
  1607. ;;;; symbol overlay
  1608. (use-package symbol-overlay
  1609. :ensure t
  1610. :config
  1611. (defun jao-symbol-reveal (&rest _)
  1612. (when outline-minor-mode (outline-show-entry)))
  1613. (advice-add 'symbol-overlay-basic-jump :after 'jao-symbol-reveal)
  1614. (defun jao-symbol-put-and-next ()
  1615. (interactive)
  1616. (symbol-overlay-put)
  1617. (symbol-overlay-jump-next))
  1618. (defun jao-symbol-put-and-prev ()
  1619. (interactive)
  1620. (symbol-overlay-put)
  1621. (symbol-overlay-jump-prev))
  1622. :bind (:map prog-mode-map (("M-i" . symbol-overlay-put)
  1623. ("M-n" . jao-symbol-put-and-next)
  1624. ("M-p" . jao-symbol-put-and-prev)))
  1625. :hook (prog-mode . symbol-overlay-mode)
  1626. :diminish " ^")
  1627. ;;;; eglot
  1628. (use-package eglot
  1629. :bind (:map eglot-mode-map (("C-h ." . jao-eldoc-toggle))))
  1630. ;;;; paredit and parens
  1631. (require 'paren)
  1632. (show-paren-mode t)
  1633. (setq show-paren-context-when-offscreen t
  1634. show-paren-when-point-inside-paren nil)
  1635. (use-package paredit
  1636. :ensure t
  1637. :commands paredit-mode
  1638. :hook ((pie-mode . paredit-mode)
  1639. (scheme-mode . paredit-mode)
  1640. (clojure-mode . paredit-mode)
  1641. (emacs-lisp-mode . paredit-mode)
  1642. ;; (eval-expression-minibuffer-setup . paredit-mode)
  1643. (lisp-interaction-mode . disable-paredit-mode))
  1644. :diminish ((paredit-mode . " þ")))
  1645. ;;;; diff/ediff
  1646. (setq ediff-split-window-function 'split-window-horizontally)
  1647. (setq ediff-make-buffers-readonly-at-startup nil)
  1648. (setq ediff-window-setup-function 'ediff-setup-windows-plain)
  1649. (setq ediff-keep-variants nil)
  1650. ;;;; compilation
  1651. ;;;;; compilation mode options
  1652. (require 'compile)
  1653. (setq compilation-scroll-output t)
  1654. (setq compilation-error-regexp-alist
  1655. (remove 'omake compilation-error-regexp-alist))
  1656. ;; (add-hook 'compilation-mode-hook #'visual-line-mode)
  1657. ;;;;; mode line (no "Compiling"!)
  1658. (require 'compile)
  1659. (diminish 'compilation-minor-mode " ‡")
  1660. (when (< emacs-major-version 27)
  1661. (setcdr (assq 'compilation-in-progress minor-mode-alist) '(" ‡")))
  1662. (when (> emacs-major-version 26)
  1663. (setcdr (assq 'compilation-in-progress mode-line-modes) '("‡ ")))
  1664. ;;;;; colorizing compilation buffer
  1665. (setq compilation-message-face 'default)
  1666. (require 'ansi-color)
  1667. (defun endless/colorize-compilation ()
  1668. "Colorize from `compilation-filter-start' to `point'."
  1669. (let ((inhibit-read-only t))
  1670. (ansi-color-apply-on-region
  1671. compilation-filter-start (point))))
  1672. (add-hook 'compilation-filter-hook #'endless/colorize-compilation)
  1673. ;;;;; compilation commands
  1674. (use-package jao-compilation
  1675. :commands jao-compilation-setup
  1676. :bind (("C-c C" . compile)
  1677. ("C-c c" . jao-compile)))
  1678. (jao-compilation-setup)
  1679. ;;;;; next error
  1680. (setq next-error-find-buffer-function
  1681. #'next-error-buffer-on-selected-frame
  1682. next-error-verbose t)
  1683. ;;;; flymake
  1684. (use-package flymake
  1685. :ensure t
  1686. :custom ((flymake-mode-line-format '(" " flymake-mode-line-counters)))
  1687. :config
  1688. (jao-define-attached-buffer "^\\*Flymake diagnostics .*\\*\\'")
  1689. (transient-define-prefix jao-transient-flymake ()
  1690. ["Flymake"
  1691. ("d" "show diagnostics" flymake-show-buffer-diagnostics)
  1692. ("i" "show diagnostic" flymake-show-diagnostic)
  1693. ("n" "next error" flymake-goto-next-error)
  1694. ("p" "previous error" flymake-goto-prev-error)
  1695. ("c" "consult flymake" consult-flymake)])
  1696. :bind (:map flymake-mode-map (("M-m" . jao-transient-flymake))))
  1697. ;;;; workarounds
  1698. (setq c-type-finder-time-slot nil)
  1699. ;;;; outline minor mode
  1700. (use-package outline
  1701. :init (setq outline-minor-mode-use-buttons nil
  1702. outline-minor-mode-use-margins nil
  1703. outline-minor-mode-cycle t))
  1704. (defvar-local jao-outline-folded nil)
  1705. (dolist (v '(4 5 outline-show-only-headings))
  1706. (add-to-list 'safe-local-variable-values `(outline-default-state . ,v)))
  1707. (defun jao-outline-minor-mode-hide-all (&optional arg)
  1708. (interactive "P")
  1709. (outline-hide-sublevels (if arg 5 4)))
  1710. (defun jao-outline-minor-expand-all ()
  1711. (when jao-outline-minor-mode (outline-show-all)))
  1712. (defun jao-outline-minor-mode-toogle-fold (&optional arg)
  1713. (interactive "P")
  1714. (if (setq jao-outline-folded (not jao-outline-folded))
  1715. (jao-outline-minor-mode-hide-all arg)
  1716. (jao-outline-minor-expand-all)))
  1717. (use-package outline-minor-faces
  1718. :ensure t
  1719. :after outline)
  1720. (define-minor-mode jao-outline-minor-mode
  1721. "Minor outline mode for programming languages"
  1722. :lighter ""
  1723. :keymap `((,(kbd "C-c C-n") . outline-next-visible-heading)
  1724. (,(kbd "C-c C-p") . outline-previous-visible-heading)
  1725. (,(kbd "C-c o") . consult-outline)
  1726. (,(kbd "<f3>") . jao-outline-minor-mode-toogle-fold))
  1727. (if jao-outline-minor-mode
  1728. (progn (setq-local outline-level #'outline-level
  1729. outline-regexp (format "[%s]\\{3,\\} " comment-start))
  1730. (outline-minor-mode 1)
  1731. (outline-minor-faces-mode 1))
  1732. (outline-minor-mode -1)
  1733. (outline-minor-faces-mode -1)))
  1734. (add-hook 'find-function-after-hook #'jao-outline-minor-expand-all)
  1735. ;;; Programming languages
  1736. ;;;; Elisp
  1737. (add-hook 'emacs-lisp-mode-hook #'jao-outline-minor-mode)
  1738. (use-package edit-list :ensure t)
  1739. (use-package package-lint :ensure t)
  1740. ;; (use-package tree-inspector :ensure t)
  1741. (defun elisp-disassemble (function)
  1742. (interactive (list (function-called-at-point)))
  1743. (disassemble function))
  1744. (defun elisp-pp (sexp)
  1745. (with-output-to-temp-buffer "*Pp Eval Output*"
  1746. (pp sexp)
  1747. (with-current-buffer standard-output
  1748. (emacs-lisp-mode))))
  1749. (defun elisp-macroexpand (form)
  1750. (interactive (list (form-at-point 'sexp)))
  1751. (elisp-pp (macroexpand form)))
  1752. (defun elisp-macroexpand-all (form)
  1753. (interactive (list (form-at-point 'sexp)))
  1754. (elisp-pp (macroexpand-all form)))
  1755. (defun elisp-find-definition (name)
  1756. (interactive (list (thing-at-point 'symbol)))
  1757. (cond (name
  1758. (let ((symbol (intern-soft name))
  1759. (search (lambda (fun sym)
  1760. (let* ((r (save-excursion (funcall fun sym)))
  1761. (buffer (car r))
  1762. (point (cdr r)))
  1763. (cond ((not point)
  1764. (error "Found no definition for %s in %s"
  1765. name buffer))
  1766. (t
  1767. (switch-to-buffer buffer)
  1768. (goto-char point)
  1769. (recenter 1)))))))
  1770. (cond ((fboundp symbol)
  1771. (xref-push-marker-stack)
  1772. (funcall search 'find-function-noselect symbol))
  1773. ((boundp symbol)
  1774. (xref-push-marker-stack)
  1775. (funcall search 'find-variable-noselect symbol))
  1776. (t
  1777. (message "Symbol not bound: %S" symbol)))))
  1778. (t (message "No symbol at point"))))
  1779. (defun elisp-bytecompile-and-load ()
  1780. (interactive)
  1781. (or buffer-file-name
  1782. (error "The buffer must be saved in a file first"))
  1783. (require 'bytecomp)
  1784. ;; Recompile if file or buffer has changed since last compilation.
  1785. (when (and (buffer-modified-p)
  1786. (y-or-n-p (format "save buffer %s first? " (buffer-name))))
  1787. (save-buffer))
  1788. (let ((filename (expand-file-name buffer-file-name)))
  1789. (with-temp-buffer
  1790. (byte-compile-file filename))))
  1791. (use-package elisp-mode
  1792. :bind (:map emacs-lisp-mode-map
  1793. (("C-c C-M" . emacs-lisp-macroexpand)
  1794. ("C-c C-m" . elisp-macroexpand-all)
  1795. ("C-c C-k" . elisp-bytecompile-and-load)
  1796. ;; ("C-c C-p" . pp-eval-last-sexp)
  1797. ("M-." . elisp-find-definition)
  1798. ("M-," . pop-tag-mark)
  1799. ("C-c <" . lc-show-package-summary))))
  1800. ;;;; Clojure
  1801. (use-package clojure-mode
  1802. :ensure t
  1803. :config
  1804. (defun jao-clojure--fix-things ()
  1805. (setq-local completion-styles '(basic partial-completion emacs22))
  1806. (eldoc-mode 1)
  1807. (setq mode-name "λ"))
  1808. :hook (clojure-mode . jao-clojure--fix-things))
  1809. (use-package cider
  1810. :ensure t
  1811. :commands cider-mode
  1812. :init (setq cider-annotate-completion-candidates t
  1813. cider-auto-select-error-buffer nil
  1814. cider-auto-select-test-report-buffer nil
  1815. cider-eldoc-display-for-symbol-at-point t
  1816. cider-eldoc-ns-function #'identity ;; #'cider-last-ns-segment
  1817. cider-enrich-classpath nil
  1818. cider-lein-parameters "repl :headless :host localhost"
  1819. cider-mode-line " ÷"
  1820. cider-prompt-for-symbol nil
  1821. cider-repl-history-file
  1822. (expand-file-name "~/.emacs.d/cache/cider.history")
  1823. cider-repl-pop-to-buffer-on-connect nil
  1824. cider-repl-use-pretty-printing t
  1825. cider-show-error-buffer 'except-in-repl
  1826. cider-test-show-report-on-success nil
  1827. cider-use-fringe-indicators nil
  1828. cider-use-overlays nil
  1829. clojure-docstring-fill-column 72
  1830. nrepl-prompt-to-kill-server-buffer-on-quit nil)
  1831. :bind (("<f3>" . cider-selector)))
  1832. (with-eval-after-load "cider-test"
  1833. (advice-add 'cider-scale-background-color :override
  1834. (lambda () (frame-parameter nil 'background-color)))
  1835. (setq cider-test-items-background-color
  1836. (frame-parameter nil 'background-color)))
  1837. (use-package cider-macroexpansion
  1838. :after cider
  1839. :diminish " µ")
  1840. ;;;; Geiser
  1841. (defun jao-org--set-geiser-impl () (setq-local geiser-repl--impl 'guile))
  1842. (add-hook 'org-mode-hook #'jao-org--set-geiser-impl)
  1843. (jao-load-path "geiser")
  1844. ;; (package-vc-install-from-checkout ...)
  1845. (use-package geiser
  1846. :demand t
  1847. :init
  1848. (setq geiser-repl-history-filename "~/.emacs.d/cache/geiser-history"
  1849. geiser-repl-startup-time 20000
  1850. geiser-debug-auto-display-images t
  1851. geiser-log-verbose t)
  1852. :config
  1853. (dolist (m '(geiser-repl-mode geiser-doc-mode geiser-debug-mode))
  1854. (jao-define-attached-buffer `(major-mode . ,m) 0.4)))
  1855. (jao-load-path "geiser-guile")
  1856. (use-package geiser-guile)
  1857. (jao-load-path "geiser-chez")
  1858. (use-package geiser-chez)
  1859. ;; (jao-load-path "geiser/mit")
  1860. ;; (use-package geiser-mit)
  1861. ;; (jao-load-path "geiser/chicken")
  1862. ;; (use-package geiser-chicken)
  1863. ;; (jao-load-path "geiser/chibi")
  1864. ;; (use-package geiser-chibi)
  1865. ;; (jao-load-path "geiser/gambit")
  1866. ;; (use-package geiser-gambit)
  1867. ;; (jao-load-path "geiser/gauche")
  1868. ;; (use-package geiser-gauche)
  1869. ;;;; Haskell
  1870. ;;;;; packages
  1871. ;; (jao-load-path "haskell-mode")
  1872. (use-package haskell-mode
  1873. :ensure t
  1874. :custom
  1875. ((inferior-haskell-find-project-root t)
  1876. (haskell-check-remember-last-command-p nil)
  1877. (haskell-completing-read-function 'completing-read)
  1878. (haskell-font-lock-symbols nil)
  1879. (haskell-hoogle-command "hoogle")
  1880. (haskell-interactive-popup-errors t)
  1881. (haskell-process-auto-import-loaded-modules t)
  1882. (haskell-process-log t)
  1883. (haskell-process-suggest-remove-import-lines t)
  1884. (haskell-process-suggest-hoogle-imports t)
  1885. (haskell-process-type 'cabal-repl)
  1886. (haskell-process-use-presentation-mode t)
  1887. (haskell-stylish-on-save nil)
  1888. (haskell-tags-on-save t))
  1889. :init
  1890. ;; For use with M-x align
  1891. (require 'align)
  1892. (add-to-list 'align-rules-list
  1893. '(haskell-types
  1894. (regexp . "\\(\\s-+\\)\\(::\\|∷\\)\\s-+")
  1895. (modes quote (haskell-mode haskell-literate-mode))))
  1896. (add-to-list 'align-rules-list
  1897. '(haskell-assignment
  1898. (regexp . "\\(\\s-+\\)=\\s-+")
  1899. (modes quote (haskell-mode haskell-literate-mode))))
  1900. (add-to-list 'align-rules-list
  1901. '(haskell-arrows
  1902. (regexp . "\\(\\s-+\\)\\(->\\|→\\)\\s-+")
  1903. (modes quote (haskell-mode haskell-literate-mode))))
  1904. (add-to-list 'align-rules-list
  1905. '(haskell-left-arrows
  1906. (regexp . "\\(\\s-+\\)\\(<-\\|←\\)\\s-+")
  1907. (modes quote (haskell-mode haskell-literate-mode))))
  1908. :config
  1909. (defun jao-haskell-hoogle (no-info)
  1910. (interactive "P")
  1911. (haskell-hoogle (format "%s" (haskell-ident-at-point)) (not no-info)))
  1912. (put 'haskell-process-args-cabal-repl
  1913. 'safe-local-variable
  1914. (apply-partially #'seq-every-p #'stringp))
  1915. (defun jao-haskell-eldoc (cb)
  1916. (let ((msg (or (haskell-doc-current-info--interaction t)
  1917. (haskell-doc-sym-doc (haskell-ident-at-point))
  1918. "")))
  1919. (funcall cb (replace-regexp-in-string "[\n ]+" " " msg))))
  1920. (setq tags-revert-without-query t)
  1921. (defun jao-haskell-mode ()
  1922. (require 'haskell-doc)
  1923. (setq-local eldoc-documentation-function 'eldoc-documentation-default
  1924. eldoc-documentation-functions '(jao-haskell-eldoc))
  1925. (eldoc-mode))
  1926. (dolist (h '(jao-haskell-mode
  1927. haskell-decl-scan-mode
  1928. haskell-indentation-mode
  1929. interactive-haskell-mode))
  1930. (add-hook 'haskell-mode-hook h))
  1931. (add-hook 'haskell-presentation-mode-hook (lambda () (whitespace-mode -1)))
  1932. :bind (:map haskell-mode-map
  1933. (("C-c C-d" . jao-haskell-hoogle)
  1934. ("C-c C-s" . haskell-session-change-target)
  1935. ("C-c h" . haskell-hoogle)
  1936. ("C-c t" . haskell-doc-show-type)
  1937. ("C-c C-e" . haskell-command-insert-language-pragma)
  1938. ("C-M-n" . flymake-goto-next-error)
  1939. ("C-M-p" . flymake-goto-prev-error)
  1940. ("<f3>" . haskell-session-kill))))
  1941. (use-package hlint-refactor
  1942. :ensure t
  1943. :after haskell-mode
  1944. :hook ((haskell-mode . hlint-refactor-mode))
  1945. :bind (:map haskell-mode-map (("C-M-h" . 'hlint-refactor-refactor-at-point)
  1946. ("C-M-S-h" . 'hlint-refactor-refactor-buffer)))
  1947. :diminish)
  1948. (use-package flymake-hlint
  1949. :ensure t
  1950. :after haskell-mode
  1951. :hook ((haskell-mode . flymake-hlint-load)))
  1952. (use-package consult-hoogle
  1953. :ensure t)
  1954. (require 'haskell)
  1955. (diminish 'interactive-haskell-mode " λ")
  1956. (diminish 'haskell-doc-mode)
  1957. (diminish 'haskell-decl-scan-mode)
  1958. (jao-define-attached-buffer "\\*hoogle\\*.*")
  1959. (jao-define-attached-buffer '(major-mode . haskell-interactive-mode) 0.33)
  1960. (jao-define-attached-buffer '(major-mode . haskell-presentation-mode) 0.25)
  1961. ;;;;; transient
  1962. (jao-transient-major-mode haskell
  1963. ["Imports"
  1964. ("in" "Navigate imports" haskell-navigate-imports)
  1965. ("if" "Format imports" haskell-mode-format-imports)
  1966. ("is" "Sort imports" haskell-sort-imports)
  1967. ("ia" "Align imports" haskell-align-imports)]
  1968. ["Session"
  1969. ("s" "Change the session's target" haskell-session-change-target)]
  1970. ["Code"
  1971. ("e" "insert language pragma" haskell-command-insert-language-pragma)
  1972. ("v" "visit cabal file" haskell-cabal-visit-file)
  1973. ("h" "hoogle" jao-haskell-hoogle)
  1974. ("t" "show type" haskell-doc-show-type)]
  1975. ["Flymake"
  1976. ("n" "next error" flymake-goto-next-error)
  1977. ("p" "previous error" flymake-goto-prev-error)])
  1978. ;;;; Pie
  1979. (jao-load-path "pie")
  1980. (use-package pie
  1981. :demand t
  1982. :commands (pie-mode))
  1983. ;;;; Prolog
  1984. ;; (use-package ediprolog :ensure t)
  1985. (use-package prolog
  1986. :ensure t
  1987. :commands (run-prolog prolog-mode mercury-mode)
  1988. :init (progn
  1989. (setq prolog-system 'swi)
  1990. (add-to-list 'auto-mode-alist '("\\.pl$" . prolog-mode))
  1991. (setq prolog-consult-string '((t "[%f].")))
  1992. (setq prolog-program-name
  1993. '(((getenv "EPROLOG") (eval (getenv "EPROLOG")))
  1994. (eclipse "eclipse")
  1995. (mercury nil)
  1996. (sicstus "sicstus")
  1997. (swi "swipl")
  1998. (t "prolog")))))
  1999. ;;;; Python
  2000. (use-package virtualenvwrapper
  2001. :ensure t
  2002. :config
  2003. (venv-initialize-eshell)
  2004. (jao-compilation-env "VIRTUAL_ENV"))
  2005. ;;; Text/data formats
  2006. ;;;; json
  2007. (use-package json-mode :ensure t)
  2008. ;;;; yaml
  2009. (use-package yaml-mode :disabled t :ensure t)
  2010. ;;; Graphics
  2011. ;;;; images
  2012. (setq image-use-external-converter t
  2013. image-cache-eviction-delay 120)
  2014. (setq widget-image-enable nil)
  2015. ;;;; gnuplot
  2016. (use-package gnuplot
  2017. :disabled t
  2018. :ensure t
  2019. :commands (gnuplot-mode gnuplot-make-buffer)
  2020. :init (add-to-list 'auto-mode-alist '("\\.gp$" . gnuplot-mode)))
  2021. ;;; Network
  2022. ;;;; nm applet
  2023. (jao-shell-def-exec jao-nm-applet "nm-applet")
  2024. (defun jao-toggle-nm-applet ()
  2025. (interactive)
  2026. (or (jao-shell-kill-p "nm-applet") (jao-nm-applet)))
  2027. ;;;; bluetooth
  2028. (use-package bluetooth :ensure t)
  2029. ;;;; vpn
  2030. (use-package jao-mullvad :demand t)
  2031. ;;;; ssh
  2032. (use-package tramp)
  2033. (defun jao-tramp-hosts ()
  2034. (seq-uniq
  2035. (mapcan (lambda (x)
  2036. (remove nil (mapcar 'cadr (apply (car x) (cdr x)))))
  2037. (tramp-get-completion-function "ssh"))
  2038. #'string=))
  2039. (defun jao-ssh (&optional scratch)
  2040. (interactive "P")
  2041. (let ((h (completing-read "Host: " (jao-tramp-hosts))))
  2042. (when scratch (jao-afio-goto-scratch))
  2043. (jao-exec-in-term (format "ssh %s" h) (format "*ssh %s*" h))))
  2044. ;;; Chats
  2045. ;;;; circe
  2046. (defvar jao-libera-channels ())
  2047. (defvar jao-oftc-channels ())
  2048. (defvar jao-bitlbee-channels ())
  2049. (defvar jao-slack-channels ())
  2050. (use-package circe
  2051. :ensure t
  2052. :bind (:map circe-channel-mode-map
  2053. (("C-c C-a" . lui-track-jump-to-indicator)))
  2054. :init
  2055. (setq circe-chat-buffer-name "{target}"
  2056. circe-default-realname "https://jao.io"
  2057. circe-default-part-message ""
  2058. circe-default-quit-message ""
  2059. circe-ignore-list nil
  2060. circe-server-coding-system '(undecided . undecided)
  2061. circe-server-killed-confirmation 'ask-and-kill-all
  2062. circe-server-auto-join-default-type :after-auth
  2063. circe-format-say "({nick}) {body}"
  2064. circe-format-self-say "(jao) {body}"
  2065. circe-new-buffer-behavior 'ignore
  2066. circe-new-buffer-behavior-ignore-auto-joins t
  2067. circe-nickserv-ghost-style 'after-auth
  2068. circe-prompt-string ": "
  2069. circe-completion-suffix ", "
  2070. circe-reduce-lurker-spam t
  2071. circe-lagmon-mode-line-format-string "" ;; "%.0f "
  2072. circe-lagmon-mode-line-unknown-lag-string "" ;; "? "
  2073. circe-lagmon-timer-tick 120
  2074. circe-lagmon-reconnect-interval 180
  2075. lui-max-buffer-size 30000
  2076. lui-fill-column 80
  2077. lui-time-stamp-position 'right
  2078. lui-time-stamp-format "%H:%M"
  2079. lui-flyspell-p nil
  2080. lui-track-indicator (if window-system 'fringe 'bar)
  2081. lui-track-behavior 'before-tracking-next-buffer)
  2082. :config
  2083. (defsubst jao-circe-nick-no () (length (circe-channel-nicks)))
  2084. (define-minor-mode jao-circe-user-number-mode ""
  2085. :lighter (:eval (format " [%s]" (jao-circe-nick-no))))
  2086. (defun jao-circe-channel-hook ()
  2087. (when jao-mode-line-in-minibuffer
  2088. (setq header-line-format
  2089. '(" %b" (:eval (format " - %s nicks" (jao-circe-nick-no))))))
  2090. (jao-circe-user-number-mode 1))
  2091. (add-hook 'circe-channel-mode-hook #'jao-circe-channel-hook)
  2092. (defun circe-command-RECOVER (&rest _ignore)
  2093. "Recover nick"
  2094. (jao-with-auth "freenode" u p
  2095. (circe-command-MSG "nickserv" (format "IDENTIFY %s %s" u p))
  2096. (circe-command-MSG "nickserv" (format "GHOST %s" u))
  2097. (circe-command-MSG "nickserv" (format "RELEASE %s" u))
  2098. (circe-command-NICK u)))
  2099. (defun circe-command-NNICKS (&rest _)
  2100. "Echo number of nicks"
  2101. (circe-display-server-message
  2102. (format "%d nicks in this channel" (jao-circe-nick-no))))
  2103. (defun circe-command-SENDFILE (line)
  2104. "/sendfile for localslackirc"
  2105. (circe-command-QUOTE (format "sendfile %s" line)))
  2106. (advice-add 'circe-command-NAMES :after #'circe-command-NNICKS)
  2107. (setq circe-network-options
  2108. (list (jao-with-auth "libera" u p
  2109. (list "Libera Chat" :nick u :channels jao-libera-channels
  2110. :tls t :sasl-username u :sasl-password p))
  2111. (jao-with-auth "oftc" u p
  2112. (list "OFTC"
  2113. :nick u :channels jao-oftc-channels :nickserv-password p
  2114. :tls t :sasl-username u :sasl-password p))
  2115. (jao-with-auth "bitlbee" u p
  2116. (list "Bitlbee" :host "127.0.0.1" :nick u
  2117. :channels jao-bitlbee-channels :lagmon-disabled t
  2118. :nickserv-password u :user p))
  2119. (list "localslack" :host "127.0.0.1" :nick "jao"
  2120. :channels jao-slack-channels :port 9007
  2121. :lagmon-disabled t)
  2122. (list "recoveryou" :host "127.0.0.1" :nick "jao"
  2123. :port 9008 :lagmon-disabled t)))
  2124. (jao-shorten-modes 'circe-channel-mode
  2125. 'circe-server-mode
  2126. 'circe-query-mode)
  2127. (enable-circe-display-images)
  2128. (enable-lui-track)
  2129. (circe-lagmon-mode))
  2130. ;;;; telegram
  2131. (use-package telega
  2132. :ensure t
  2133. :custom
  2134. (telega-use-tracking-for '(unmuted) ;; '(or unmuted mention)
  2135. telega-rainbow-color-custom-for nil
  2136. telega-msg-rainbow-title nil
  2137. telega-sticker-set-download t
  2138. telega-symbol-checkmark "·"
  2139. telega-symbol-heavy-checkmark "×"
  2140. telega-symbol-verified "*")
  2141. :config
  2142. (define-key global-map (kbd "C-c C-t") telega-prefix-map)
  2143. (setq telega-chat-show-avatars nil
  2144. telega-chat-prompt-insexp '(telega-ins "> ")
  2145. telega-completing-read-function #'completing-read
  2146. telega-root-show-avatars nil
  2147. telega-emoji-use-images nil
  2148. telega-temp-dir "/tmp/telega"
  2149. telega-symbol-horizontal-bar
  2150. (propertize "-" 'face 'jao-themes-f00)
  2151. telega-symbol-vertical-bar
  2152. (propertize "| " 'face 'jao-themes-dimm)
  2153. telega-mode-line-string-format
  2154. '(:eval (telega-mode-line-unread-unmuted))
  2155. telega-use-images (display-graphic-p)
  2156. telega-open-file-function #'jao--see
  2157. telega-open-message-as-file
  2158. (unless (display-graphic-p) '(photo video animation)))
  2159. (with-eval-after-load "tracking"
  2160. (jao-shorten-modes 'telega-chat-mode)
  2161. (jao-tracking-faces 'telega-tracking))
  2162. (telega-mode-line-mode 1))
  2163. (defun jao-telega ()
  2164. (interactive)
  2165. (jao-tracking-go-to-chats)
  2166. (if (get-buffer telega-root-buffer-name)
  2167. (pop-to-buffer telega-root-buffer-name)
  2168. (telega)))
  2169. ;;;; ement
  2170. (use-package ement
  2171. :disabled t
  2172. :ensure t
  2173. :init (setq ement-save-sessions t
  2174. ement-sessions-file (locate-user-emacs-file "cache/ement.el")
  2175. ement-room-avatars nil
  2176. ement-notify-dbus-p nil
  2177. ement-room-left-margin-width 0
  2178. ement-room-right-margin-width 11
  2179. ement-room-timestamp-format "%H:%M"
  2180. ement-room-timestamp-header-format "­­--------")
  2181. :custom ((ement-room-message-format-spec "(%S) %B%r%R %t"))
  2182. :config
  2183. (defun jao-ement-track (event room session)
  2184. (when (ement-notify--room-unread-p event room session)
  2185. (when-let ((n (ement-room--buffer-name room))
  2186. (b (get-buffer n)))
  2187. (tracking-add-buffer b))))
  2188. (add-hook 'ement-event-hook #'jao-ement-track)
  2189. (jao-shorten-modes 'ement-room-mode)
  2190. (jao-tracking-cleaner "^\\*Ement Room: \\(.+\\)\\*" "@\\1"))
  2191. ;;;; mastodon
  2192. (use-package mastodon
  2193. :ensure t
  2194. :init
  2195. (setq mastodon-instance-url "https://fosstodon.org"
  2196. mastodon-active-user "jao@gnu.org"
  2197. mastodon-tl-position-after-update nil
  2198. mastodon-toot-display-orig-in-reply-buffer t)
  2199. :config
  2200. ;; (defun jao-mastodon--setup ()
  2201. ;; (setq-local scroll-margin 12))
  2202. ;; (add-hook 'mastodon-mode-hook #'jao-mastodon--setup)
  2203. (with-eval-after-load "ewww"
  2204. (define-key eww-mode-map (kbd "T") #'jao-mastodon-toot-url)))
  2205. (defun jao-mastodon-toot-url ()
  2206. (interactive)
  2207. (when-let (url (jao-url-around-point t))
  2208. (jao-tracking-go-to-chats)
  2209. (mastodon-toot--compose-buffer nil nil nil url)))
  2210. (defun jao-mastodon ()
  2211. (interactive)
  2212. (jao-afio-goto-chats)
  2213. (mastodon))
  2214. ;; https://0x0.st/XJ14.txt
  2215. (jao-transient-major-mode mastodon
  2216. ["Timelines"
  2217. ("H" "home" mastodon-tl--get-home-timeline)
  2218. ("L" "local" mastodon-tl--get-local-timeline)
  2219. ("F" "federated" mastodon-tl--get-federated-timeline)
  2220. ("K" "bookmarks" mastodon-profile--view-bookmarks)
  2221. ("V" "favorites" mastodon-profile--view-favourites)
  2222. ("'" "followed tags" mastodon-tl--followed-tags-timeline)
  2223. ("@" "mentions" mastodon-notifications--get-mentions)
  2224. ("N" "notifications" mastodon-notifications-get)
  2225. ("\\" "of remote host" mastodon-tl--get-remote-local-timeline)]
  2226. ;; u mastodon-tl--update
  2227. ["Search"
  2228. ("s" "search" mastodon-search--query)
  2229. ("#" "tagged" mastodon-tl--get-tag-timeline)
  2230. ("\"" "followed tags" mastodon-tl--list-followed-tags)
  2231. ("I" "filter" mastodon-views--view-filters)
  2232. ("X" "lists" mastodon-views--view-lists)]
  2233. ["Toots"
  2234. ("n" "next" mastodon-tl--goto-next-item :transient t)
  2235. ("p" "prev" mastodon-tl--goto-prev-item :transient t)
  2236. ("c" "spoiler" mastodon-tl--toggle-spoiler-text-in-toot :transient t)
  2237. ("T" "thread" mastodon-tl--thread)
  2238. ("b" "(un)boost" mastodon-toot--toggle-boost :transient t)
  2239. ("f" "(un)fav" mastodon-toot--toggle-favourite :transient t)
  2240. ("i" "(un)pin" mastodon-toot--pin-toot-toggle :transient t)
  2241. ("k" "(un)bookmark" mastodon-toot--toggle-bookmark :transient t)
  2242. ("v" "vote" mastodon-tl--poll-vote)]
  2243. ;; Z mastodon-tl--report-to-mods
  2244. ;; o mastodon-toot--open-toot-url
  2245. ["Own Toots"
  2246. ("r" "replay" mastodon-toot--reply)
  2247. ("t" "write" mastodon-toot)
  2248. ("e" "edit" mastodon-toot--edit-toot-at-point)
  2249. ("d" "delete" mastodon-toot--delete-toot)
  2250. ("D" "del & redraft" mastodon-toot--delete-and-redraft-toot)
  2251. ("E" "show edits" mastodon-toot--view-toot-edits)]
  2252. ;; S mastodon-views--view-scheduled-toots
  2253. ["Users"
  2254. ("W" "follow" mastodon-tl--follow-user)
  2255. ("R" "follow req" mastodon-views--view-follow-requests)
  2256. ("G" "suggestions" mastodon-views--view-follow-suggestions)
  2257. ("M" "mute user" mastodon-tl--mute-user)
  2258. ("B" "block user" mastodon-tl--block-user)
  2259. ("m" "message user" mastodon-tl--dm-user)
  2260. ;; ""
  2261. ;; ("," "favouriters" mastodon-toot--list-toot-favouriters)
  2262. ;; ("." "boosters" mastodon-toot--list-toot-boosters)
  2263. ]
  2264. ;; S-RET mastodon-tl--unmute-user
  2265. ;; C-S-b mastodon-tl--unblock-user
  2266. ["Profiles"
  2267. ("A" "author" mastodon-profile--get-toot-author)
  2268. ("P" "any user" mastodon-profile--show-user)
  2269. ("O" "own" mastodon-profile--my-profile)
  2270. ("U" "update own" mastodon-profile--update-user-profile-note)]
  2271. ["Misc"
  2272. ("C" "copy URL" mastodon-toot--copy-toot-url)
  2273. ("?" "help" describe-mode)
  2274. ("q" "quit" transient-quit-one)])
  2275. ;;;; startup
  2276. (defun jao-chats (&optional p)
  2277. (interactive "P")
  2278. (when (or p (y-or-n-p "Connect to telegram? "))
  2279. (telega))
  2280. (when (and (fboundp 'ement-connect) (or p (y-or-n-p "Connect to matrix? ")))
  2281. (unless (get-buffer "*Ement Rooms*")
  2282. (jao-with-auth "matrix.org" u p (ement-connect :user-id u :password p))))
  2283. (when (and (fboundp 'mastodon) (or p (y-or-n-p "Connect to mastodon? ")))
  2284. (mastodon))
  2285. (when (or p (y-or-n-p "Connect to libera? "))
  2286. (unless (get-buffer "irc.libera.chat:6697")
  2287. (circe "Libera Chat")))
  2288. (when (or p (y-or-n-p "Connect to localslack? "))
  2289. (unless (get-buffer "127.0.0.1:9007")
  2290. (circe "localslack")))
  2291. (when (or p (y-or-n-p "Connect to recoveryou? "))
  2292. (unless (get-buffer "127.0.0.1:9008")
  2293. (circe "recoveryou"))))
  2294. (defun jao-all-chats ()
  2295. (interactive)
  2296. (when jao-tracking-use-scratch
  2297. (jao-afio-goto-chats)
  2298. (delete-other-windows))
  2299. (jao-chats t))
  2300. (defun jao-chats-telega ()
  2301. (interactive)
  2302. (jao-buffer-same-mode '(telega-root-mode telega-chat-mode)))
  2303. (defun jao-chats-slack ()
  2304. (interactive)
  2305. (jao-buffer-same-mode 'slack-message-buffer-mode))
  2306. (defun jao-chats-irc ()
  2307. (interactive)
  2308. (jao-buffer-same-mode '(circe-channel-mode circe-query-mode erc-mode)))
  2309. ;;;; consult narrowing
  2310. (defvar jao-chat-buffer-source
  2311. (list :name "chats"
  2312. :category 'buffer
  2313. :action (lambda (b) (jao-afio-pop-to-buffer 0 b))
  2314. :hidden t
  2315. :narrow (cons ?c "chats")
  2316. :items (jao-consult--mode-buffers 'erc-mode
  2317. 'circe-channel-mode
  2318. 'circe-query-mode
  2319. 'signel-chat-mode
  2320. 'slack-message-buffer-mode
  2321. 'slack-thread-message-buffer-mode
  2322. 'telega-root-mode
  2323. 'telega-chat-mode
  2324. 'ement-room-mode
  2325. 'ement-room-list-mode)))
  2326. (with-eval-after-load "consult"
  2327. (jao-consult-add-buffer-source 'jao-chat-buffer-source))
  2328. ;;; Multimedia
  2329. ;;;; video
  2330. (use-package ready-player :ensure t)
  2331. (ready-player-mode 1)
  2332. ;;;; mixer
  2333. (defun jao-mixer-get-level (&optional dev nomsg)
  2334. (interactive)
  2335. (let* ((dev (or dev "Master"))
  2336. (s (shell-command-to-string (format "amixer sget %s" dev)))
  2337. (s (car (last (split-string s "\n" t)))))
  2338. (when (string-match ".*Front .*\\[\\([0-9]+\\)%\\] .*" s)
  2339. (let ((level (match-string 1 s)))
  2340. (unless nomsg (message "%s level: %s%%" dev level))
  2341. (string-to-number level)))))
  2342. (defun jao-mixer-set (dev v)
  2343. (jao-shell-exec* t "amixer" "sset" dev v)
  2344. (jao-mixer-get-level dev))
  2345. (defun jao-mixer-master-toggle ()
  2346. (interactive)
  2347. (jao-mixer-set "Master" "toggle"))
  2348. (defun jao-mixer-master-up ()
  2349. (interactive)
  2350. (jao-mixer-set "Master" "10%+"))
  2351. (defun jao-mixer-master-down ()
  2352. (interactive)
  2353. (jao-mixer-set "Master" "10%-"))
  2354. (defun jao-mixer-capture-up ()
  2355. (interactive)
  2356. (jao-mixer-set "Capture" "10%+"))
  2357. (defun jao-mixer-capture-down ()
  2358. (interactive)
  2359. (jao-mixer-set "Capture" "10%-"))
  2360. (jao-shell-def-exec jao-audio-applet "pasystray")
  2361. (defun jao-toggle-audio-applet ()
  2362. (interactive)
  2363. (or (jao-shell-kill-p "paystray") (jao-audio-applet)))
  2364. (global-set-key (kbd "<f4>") #'jao-toggle-audio-applet)
  2365. ;;;; streaming aliases
  2366. (defalias 'jao-streaming-list #'ignore)
  2367. (defalias 'jao-streaming-like #'ignore)
  2368. (defalias 'jao-streaming-dislike #'ignore)
  2369. (defalias 'jao-streaming-toggle-shuffle #'ignore)
  2370. (defalias 'jao-streaming-lyrics #'ignore)
  2371. (defalias 'jao-streaming-toggle #'ignore)
  2372. (defalias 'jao-streaming-next #'ignore)
  2373. (defalias 'jao-streaming-prev #'ignore)
  2374. (defalias 'jao-streaming-current #'ignore)
  2375. (defalias 'jao-streaming-seek #'ignore)
  2376. (defalias 'jao-streaming-seek-back #'ignore)
  2377. (defalias 'jao-streaming-volume #'ignore)
  2378. (defalias 'jao-streaming-volume-down #'ignore)
  2379. ;;;; mpris
  2380. (defun jao-mpris-lyrics (&optional force)
  2381. (interactive "P")
  2382. (jao-show-lyrics force #'jao-mpris-artist-title))
  2383. (defun jao-mpris-mopidy-p () (string= "mopidy "jao-mpris-player))
  2384. (defun jao-mpc-mopidy-playlist ()
  2385. (interactive)
  2386. (jao-mpc-show-playlist jao-mopidy-port))
  2387. (use-package jao-mpris :demand t)
  2388. (defun jao-mpris-setup-aliases ()
  2389. (setq espotify-play-uri-function #'espotify-play-uri-with-dbus)
  2390. ;; (setq jao-mpris-player "mopidy")
  2391. (defalias 'jao-streaming-list #'jao-mpc-mopidy-playlist)
  2392. (defalias 'jao-streaming-lyrics #'jao-mpris-lyrics)
  2393. (defalias 'jao-streaming-toggle #'jao-mpris-play-pause)
  2394. (defalias 'jao-streaming-next #'jao-mpris-next)
  2395. (defalias 'jao-streaming-prev #'jao-mpris-previous)
  2396. (defalias 'jao-streaming-current #'jao-mpris-show-osd)
  2397. (defalias 'jao-streaming-seek #'jao-mpris-seek)
  2398. (defalias 'jao-streaming-seek-back #'jao-mpris-seek-back)
  2399. (defalias 'jao-streaming-volume #'jao-mpris-vol)
  2400. (defalias 'jao-streaming-volume-down #'jao-mpris-vol-down))
  2401. (jao-mpris-register "playerctld" :session 70)
  2402. ;; (jao-mpris-register "mopidy" :session 70)
  2403. ;;;; mpc
  2404. (use-package jao-mpc
  2405. :demand t
  2406. :commands jao-mpc-setup)
  2407. (defvar jao-mopidy-port 6669)
  2408. (defvar jao-mpc-last-port jao-mpc-port)
  2409. (defun jao-mpc-toggle-port ()
  2410. (interactive)
  2411. (setq jao-mpc-port
  2412. (if (equal jao-mpc-port jao-mopidy-port) 6600 jao-mopidy-port)
  2413. jao-mpc-last-port jao-mpc-port))
  2414. (defsubst jao-mpc-mopidy-p () (equal jao-mpc-last-port jao-mopidy-port))
  2415. (jao-mpc-setup jao-mopidy-port 70)
  2416. (defun jao-mpc-pport (&optional mop)
  2417. (cond ((or mop (jao-mpc-playing-p jao-mopidy-port)) jao-mopidy-port)
  2418. ((jao-mpc-playing-p) 6600)
  2419. (t jao-mpc-last-port)))
  2420. (defmacro jao-defun-play (name &optional mpc-name)
  2421. (let ((arg (gensym)))
  2422. `(defun ,(intern (format "jao-player-%s" name)) (&optional ,arg)
  2423. (interactive "P")
  2424. (,(intern (format "jao-mpc-%s" (or mpc-name name)))
  2425. (setq jao-mpc-last-port (jao-mpc-pport ,arg))))))
  2426. (jao-defun-play toggle)
  2427. (jao-defun-play next)
  2428. (jao-defun-play previous)
  2429. (jao-defun-play stop)
  2430. (jao-defun-play echo echo-current-times)
  2431. (jao-defun-play list show-playlist)
  2432. (jao-defun-play info lyrics-track-data)
  2433. (jao-defun-play browse show-albums)
  2434. (jao-defun-play select-album)
  2435. (defun jao-player-seek (delta) (jao-mpc-seek delta (jao-mpc-pport)))
  2436. (defalias 'jao-player-connect 'jao-mpc-connect)
  2437. (defalias 'jao-player-play 'jao-mpc-play)
  2438. ;;;; spotify
  2439. (jao-load-path "espotify")
  2440. (use-package espotify
  2441. :demand t
  2442. :init (setq espotify-service-name "mopidy"))
  2443. (use-package consult-spotify :demand t)
  2444. (defalias 'jao-streaming-album #'consult-spotify-album)
  2445. (defalias 'jao-streaming-track #'consult-spotify-track)
  2446. (defalias 'jao-streaming-artist #'consult-spotify-artist)
  2447. (defalias 'jao-streaming-playlist #'consult-spotify-playlist)
  2448. (jao-def-exec-in-term "ncmpcpp" "ncmpcpp" (jao-afio-goto-scratch))
  2449. ;;;; spt
  2450. (use-package jao-spt
  2451. :demand t
  2452. :config
  2453. (defun jao-spt-setup-aliases ()
  2454. (setq espotify-play-uri-function #'jao-spt-play-uri)
  2455. (defalias 'jao-streaming-list #'jao-term-spt)
  2456. (defalias 'jao-streaming-lyrics #'jao-spt-show-lyrics)
  2457. (defalias 'jao-streaming-toggle #'jao-spt-toggle)
  2458. (defalias 'jao-streaming-next #'jao-spt-next)
  2459. (defalias 'jao-streaming-prev #'jao-spt-previous)
  2460. (defalias 'jao-streaming-current #'jao-spt-echo-current)
  2461. (defalias 'jao-streaming-seek #'jao-spt-seek)
  2462. (defalias 'jao-streaming-seek-back #'jao-spt-seek-back)
  2463. (defalias 'jao-streaming-volume #'jao-spt-vol)
  2464. (defalias 'jao-streaming-volume-down #'jao-spt-vol-down)
  2465. (defalias 'jao-streaming-like #'jao-spt-like)
  2466. (defalias 'jao-streaming-dislike #'jao-spt-dislike)
  2467. (defalias 'jao-streaming-toggle-shuffle #'jao-spt-toggle-shuffle)))
  2468. (jao-def-exec-in-term "spt" "spt" (jao-afio-goto-scratch))
  2469. (defvar jao-spt-on t)
  2470. (defun jao-streaming-toggle-player ()
  2471. (interactive)
  2472. (if jao-spt-on
  2473. (progn (setq jao-mpris-player "playerctld")
  2474. (require 'jao-mpris)
  2475. (jao-mpris-setup-aliases))
  2476. (jao-spt-setup-aliases)
  2477. (setq jao-mpris-player "spt"))
  2478. (setq jao-spt-on (not jao-spt-on))
  2479. (message "%s activated " jao-mpris-player))
  2480. (jao-streaming-toggle-player)
  2481. ;;;; music transients
  2482. (require 'jao-lyrics)
  2483. (setq jao-lyrics-info-function #'jao-player-info)
  2484. (defun jao-player-seek-10 () (interactive) (jao-player-seek 10))
  2485. (defun jao-player-seek--10 () (interactive) (jao-player-seek -10))
  2486. (defun jao-streaming-clear () (interactive) (jao-mpc-clear jao-mopidy-port))
  2487. (defun jao-streaming-echo-current ()
  2488. (interactive)
  2489. (jao-mpc-echo-current jao-mopidy-port))
  2490. (defun jao-streaming-show-playlist ()
  2491. (interactive)
  2492. (jao-mpc-show-playlist jao-mopidy-port))
  2493. (use-package jao-random-album
  2494. :demand t
  2495. :config
  2496. (defun jao--notify-album (album)
  2497. (unless jao-minibuffer-mode
  2498. (jao-notify album "Next album" jao-notify-audio-icon))
  2499. (jao-minibuffer-refresh))
  2500. (setq jao-random-album-notify #'jao--notify-album))
  2501. (defun jao-toggle-pasystray-applet ()
  2502. (interactive)
  2503. (or (jao-shell-kill-p "pasystray") (jao-shell-exec "pasystray")))
  2504. (transient-define-prefix jao-transient-streaming ()
  2505. [:description
  2506. (lambda () (format "Streaming using %s" jao-mpris-player))
  2507. ["Search" :if jao-mpris-mopidy-p
  2508. ("a" "album" jao-streaming-album)
  2509. ("A" "artist" jao-streaming-artist)
  2510. ("t" "track" jao-streaming-track)
  2511. ("P" "playlist" jao-streaming-playlist)]
  2512. ["Play"
  2513. ("s" "toggle" jao-streaming-toggle)
  2514. ("n" "next" jao-streaming-next)
  2515. ("p" "previous" jao-streaming-prev)
  2516. ("T" "toggle player" jao-streaming-toggle-player)]
  2517. ["Seek & shout"
  2518. ("f" "seek fwd" jao-streaming-seek :transient t)
  2519. ("F" "seek bwd" jao-streaming-seek-back :transient t)
  2520. ("u" "up" jao-streaming-volume :transient t)
  2521. ("d" "down" jao-streaming-volume-down :transient t)]
  2522. ["Browse"
  2523. ("l" "playing list" jao-streaming-list :if jao-mpris-mopidy-p)
  2524. ("L" "lyrics" jao-streaming-lyrics)
  2525. ("w" "currently playing" jao-streaming-current)]
  2526. ["Act" :if jao-mpris-mopidy-p
  2527. ("k" "like" jao-streaming-like)
  2528. ("K" "dislike" jao-streaming-dislike)
  2529. ("S" "toggle shuffle" jao-streaming-toggle-shuffle)]])
  2530. (transient-define-prefix jao-transient-media ()
  2531. [["Play"
  2532. ("m" "toggle" jao-player-toggle)
  2533. ("n" "next" jao-player-next)
  2534. ("p" "previous" jao-player-previous)
  2535. ("s" "select album" jao-player-select-album)]
  2536. ["Seek and search"
  2537. ("f" "seek fwd" jao-player-seek-10 :transient t)
  2538. ("F" "seek bwd" jao-player-seek--10 :transient t)
  2539. ("a" "search album" jao-mpc-select-album)
  2540. ("S" "play stream" jao-mpc-play-stream)]
  2541. ["Browse"
  2542. ("b" "browse" jao-player-browse)
  2543. ("l" "show play list" jao-player-list)
  2544. ("L" "show lyrics" jao-show-lyrics)
  2545. ("w" "now playing" jao-player-echo)]
  2546. [:description
  2547. (lambda ()
  2548. (message "%s %s"
  2549. (if (jao-mpc-mopidy-p) "mopidy" "mpd")
  2550. (if (jao-mpc-playing-p)
  2551. (jao-mpc--current-timestr t)
  2552. (jao-mpc--current-str)))
  2553. (format "Master %s%%" (jao-mixer-get-level nil t)))
  2554. ("d" "down" jao-mixer-master-down :transient t)
  2555. ("u" "up" jao-mixer-master-up :transient t)
  2556. ("M" "toggle" jao-mixer-master-toggle)]
  2557. [:description
  2558. (lambda () (format "Capture %s%%" (jao-mixer-get-level "Capture" t)))
  2559. ("D" "down" jao-mixer-capture-down :transient t)
  2560. ("U" "up" jao-mixer-capture-up :transient t)]
  2561. ["Utilities"
  2562. ("c" "reconnect to mpd" jao-player-connect)
  2563. ("N" "next random album" jao-random-album-next)
  2564. ("r" (lambda ()
  2565. (concat (if jao-random-album-active "dis" "en") "able random album"))
  2566. jao-random-album-toggle)
  2567. ;; ("P" (lambda () (concat "Toggle to " (if (jao-mpc-mopidy-p) "mpd" "mopidy")))
  2568. ;; jao-mpc-toggle-port)
  2569. ("P" "pasystray" jao-toggle-pasystray-applet)]])
  2570. (global-set-key (kbd "s-m") #'jao-transient-media)
  2571. ;;; Graphical window system
  2572. ;;;; x11 utils
  2573. (defun jao-xdotool (arg-or-wait &rest args)
  2574. (apply 'jao-shell-exec*
  2575. (if (stringp arg-or-wait) "xdotool" arg-or-wait)
  2576. (if (stringp arg-or-wait) arg-or-wait "xdotool")
  2577. args))
  2578. (defsubst jao-xdotool-string (&rest args)
  2579. (apply 'jao-shell-string "xdotool" args))
  2580. (defsubst jao-x11-focused-id () (jao-xdotool-string "getwindowfocus"))
  2581. (defsubst jao-x11-window-name (&optional wid)
  2582. (jao-xdotool-string "getwindowname" (or wid (jao-x11-focused-id))))
  2583. (defsubst jao-x11-search-window (title)
  2584. (jao-xdotool-string "search" "--name" title))
  2585. (defsubst jao-x11-goto-ws (n) (jao-xdotool t "set_desktop" (format "%s" n)))
  2586. ;;;; exwm
  2587. (defvar jao-exwm-enabled nil)
  2588. (defun jao-exwm-enabled-p () jao-exwm-enabled)
  2589. (defun jao-exwm-enable ()
  2590. (require 'jao-custom-exwm)
  2591. (setq jao-exwm-enabled t)
  2592. (display-time-mode -1)
  2593. (jao-ednc-setup 95)
  2594. (exwm-enable)
  2595. (x-change-window-property "_XMONAD_TRAYPAD" "" nil nil nil nil 0)
  2596. (jao-mode-line-add-to-minibuffer-left 90)
  2597. (jao-xmobar-restart)
  2598. (jao-trisect t))
  2599. ;;;; xmonad
  2600. (defvar jao-xmonad-enabled (string= "xmonad" (or (getenv "wm") "")))
  2601. (defun jao-xmonad-enabled-p () jao-xmonad-enabled)
  2602. (defun jao-xmonad-enable ()
  2603. (setq jao-browse-doc-use-emacs-p (display-graphic-p))
  2604. (setq jao-mode-line-in-minibuffer nil)
  2605. (display-battery-mode -1)
  2606. (jao-trisect)
  2607. (message "Welcome to xmonad"))
  2608. (when jao-xmonad-enabled
  2609. (add-hook 'after-init-hook #'jao-xmonad-enable))
  2610. ;;;; wayland
  2611. (use-package jao-wayland :demand t)
  2612. (defun jao-wayland-enable ()
  2613. (interactive)
  2614. (defalias 'x-change-window-property #'ignore)
  2615. (jao-trisect)
  2616. (message "Welcome to wayland"))
  2617. (defun jao-river-enable ()
  2618. (jao-wayland-enable)
  2619. (when (jao-shell-running-p "i3bar-river")
  2620. (jao-tracking-set-log ""))
  2621. (message "Welcome to river"))
  2622. (when jao-river-enabled
  2623. (add-hook 'after-init-hook #'jao-river-enable t))
  2624. (when jao-sway-enabled
  2625. (add-hook 'after-init-hook #'jao-wayland-enable t))
  2626. ;;;; wallpaper
  2627. (defvar jao-wallpaper-dir "~/.wallpapers/")
  2628. (defvar jao-wallpaper-random-candidates
  2629. '("wallpaper.jpg" "wallpaper2.jpg"))
  2630. (defvar jao-wallpaper-random-candidates-light
  2631. '("wallpaper.jpg" "wallpaper2.jpg"))
  2632. (defvar jao-wallpaper-random-wake t
  2633. "Set to t for getting a new wallpaper on awaking from sleep")
  2634. (defun jao-set-wallpaper (&optional path)
  2635. (interactive)
  2636. (let ((current (format "~/.wallpaper.%s" (jao-colors-scheme))))
  2637. (when-let ((f (or (and path (expand-file-name path))
  2638. (read-file-name "Image: "
  2639. jao-wallpaper-dir
  2640. (file-symlink-p current)
  2641. t))))
  2642. (make-symbolic-link f current t)
  2643. (cond (jao-river-enabled (jao-river-set-wallpaper f))
  2644. (jao-sway-enabled (jao-sway-set-wallpaper f))
  2645. (t (shell-command-to-string (format "xwallpaper --zoom %s" f)))))))
  2646. (defun jao-set-random-wallpaper ()
  2647. (interactive)
  2648. (when (or (called-interactively-p 'interactive)
  2649. jao-wallpaper-random-wake)
  2650. (let* ((ws (if (jao-colors-scheme-dark-p)
  2651. jao-wallpaper-random-candidates
  2652. jao-wallpaper-random-candidates-light))
  2653. (f (seq-random-elt ws)))
  2654. (jao-set-wallpaper (expand-file-name f jao-wallpaper-dir))
  2655. (message "%s" f))))
  2656. (add-to-list 'jao-sleep-awake-functions #'jao-set-random-wallpaper)
  2657. ;;;; screensaver and lock
  2658. (defun jao-screensaver-enabled ()
  2659. (string= (jao-shell-string "xdg-screensaver status") "enabled"))
  2660. (defvar jao-screensaver--wid nil)
  2661. (defun jao-screensaver-toggle ()
  2662. (interactive)
  2663. (if (jao-screensaver-enabled)
  2664. (let ((wid (jao-x11-focused-id)))
  2665. (setq jao-screensaver--wid wid)
  2666. (jao-shell-exec* t "xdg-screensaver" "suspend" wid))
  2667. (jao-shell-exec* t "xdg-screensaver" "resume" jao-screensaver--wid)
  2668. (setq jao-screensaver--wid nil))
  2669. (jao-notify (format "Screensaver %s"
  2670. (jao-shell-string "xdg-screensaver status"))))
  2671. (jao-shell-def-exec jao-xlock-screen "xdg-screensaver" "activate")
  2672. (jao-shell-def-exec jao-suspend "sudo" "systemctl" "suspend")
  2673. (jao-shell-def-exec jao-poweroff "sudo" "systemctl" "poweroff")
  2674. (defun jao-lock-screen ()
  2675. (interactive)
  2676. (if jao-wayland-enabled
  2677. (shell-command "swaylock -i ~/.lockimage")
  2678. (jao-xlock-screen)))
  2679. (transient-define-prefix jao-transient-sleep ()
  2680. ["Sleep"
  2681. ("l" "lock screen" jao-lock-screen)
  2682. ("z" "sleep" jao-suspend)
  2683. ("u" (lambda ()
  2684. (if (jao-screensaver-enabled) "suspend screensaver" "resume screensaver"))
  2685. jao-screensaver-toggle)
  2686. ("poof" "power-off" jao-poweroff)])
  2687. ;;;; X clipboard
  2688. (setq select-enable-clipboard t
  2689. select-enable-primary t
  2690. selection-timeout 100
  2691. xterm-select-active-regions t)
  2692. (use-package xclip
  2693. :ensure t
  2694. :init (setq xclip-method (if jao-wayland-enabled 'wl-copy 'xclip)))
  2695. (unless (display-graphic-p) (xclip-mode 1))
  2696. ;;;; pop-up frames
  2697. (defun jao-open-in-x-frame (&optional width height)
  2698. (interactive)
  2699. (make-frame `((window-system . x)
  2700. (name . "emacs popup")
  2701. (width . ,(or width (window-width)))
  2702. (height . ,(or height (window-height)))))
  2703. (define-key (current-local-map) "q" #'delete-frame))
  2704. ;;;; xmobar
  2705. (defun jao-xmobar-kill ()
  2706. (interactive)
  2707. (shell-command "killall xmobar-single"))
  2708. (defun jao-xmobar-restart ()
  2709. (interactive)
  2710. (jao-xmobar-kill)
  2711. (start-process "" nil "xmobar-single" "-d"))
  2712. (use-package tab-bar
  2713. :init (setq tab-bar-close-button-show nil
  2714. tab-bar-show (> emacs-major-version 28)
  2715. tab-bar-format ()))
  2716. (use-package xmobar
  2717. :init (setq xmobar-tab-bar t
  2718. xmobar-tab-split "*"
  2719. xmobar-tab-bar-format
  2720. (if window-system
  2721. '(xmobar-left-string
  2722. tab-bar-format-align-right
  2723. xmobar-right-string)
  2724. '(xmobar-left-string
  2725. xmobar-elastic-space
  2726. xmobar-right-string))
  2727. xmobar-command
  2728. (if window-system '("xmobar-emacs" "-TAnsi") "xmobar-emacs")))
  2729. ;;; Global transients
  2730. (defun jao-list-packages ()
  2731. (interactive)
  2732. (jao-afio-goto-scratch)
  2733. (package-list-packages))
  2734. (defun jao-window-system-p ()
  2735. (or jao-exwm-enabled jao-xmonad-enabled jao-wayland-enabled))
  2736. (defun jao-x11-p () (or jao-exwm-enabled jao-xmonad-enabled))
  2737. (defun jao-reveal ()
  2738. (interactive)
  2739. (cond ((or outline-minor-mode (derived-mode-p 'outline-mode ))
  2740. (outline-show-entry))
  2741. ((derived-mode-p 'org-mode) (org-reveal))))
  2742. (jao-def-exec-in-term "aptitude" "aptitude" (jao-afio-goto-scratch))
  2743. (jao-def-exec-in-term "htop" "htop" (jao-afio-goto-scratch))
  2744. (transient-define-prefix jao-transient-utils ()
  2745. "Global operations."
  2746. [["Notes"
  2747. ("n" "create new note" jao-org-notes-create)
  2748. ("/" "open note" jao-org-notes-open)
  2749. ("\\" "open note by tags" jao-org-notes-consult-tags)
  2750. ("g" "ripgrep notes" jao-org-notes-consult-ripgrep)]
  2751. ["Documents"
  2752. ("dd" "go to doc" jao-select-pdf :if display-graphic-p)
  2753. ("do" "open doc" jao-open-doc)
  2754. ("dr" "search docs with recoll" jao-recoll-consult-docs)]
  2755. ["Monitors"
  2756. ("p" "htop" jao-term-htop)
  2757. ("P" "pasytray" jao-toggle-pasystray-applet)
  2758. ("x" "restart i3bar" jao-river-restart-i3bar :if jao-river-enabled-p)
  2759. ("x" "restart xmobar" jao-xmobar-restart :if jao-exwm-enabled-p)
  2760. ("x" "kill xmobar" jao-xmobar-kill :if jao-xmonad-enabled-p)]
  2761. ["Network"
  2762. ("s" "ssh" jao-ssh)
  2763. ("b" "bluetooth" bluetooth-list-devices)
  2764. ("c" "connect chats" jao-all-chats)
  2765. ("m" "proton bridge" run-proton-bridge)
  2766. ("v" "view video" jao-view-video)]
  2767. ["Chats"
  2768. ("t" "telegram" jao-chats-telega)
  2769. ("i" "irc" jao-chats-irc)
  2770. ("M" "mastodon" jao-mastodon)
  2771. ("T" "telegram rooster" jao-telega)]
  2772. ["Window system" :if jao-window-system-p
  2773. ("w" "set wallpaper" jao-set-wallpaper)
  2774. ("W" "set radom wallpaper" jao-set-random-wallpaper)
  2775. ("B u" (lambda ()
  2776. (let ((b (jao-brightness)))
  2777. (format "bright up %s" (and (string-match ".*\\((.+)\\).*" b)
  2778. (match-string 1 b)))))
  2779. jao-bright-up :transient t)
  2780. ("B d" "bright down" jao-bright-down :transient t)]
  2781. ["Helpers"
  2782. ("a" "aptitude" jao-term-aptitude)
  2783. ("l" "packages" jao-list-packages)
  2784. ("r" "reveal" jao-reveal)
  2785. ("k" (lambda () (concat "keyboard" (when (jao-kb-toggled-p) "*")))
  2786. jao-kb-toggle :if jao-x11-p)]])
  2787. (global-set-key (kbd "s-w") #'jao-transient-utils)
  2788. ;;; Global key bindings
  2789. (defun jao-global-keybindings ()
  2790. (interactive)
  2791. (global-set-key (kbd "<f2>") #'magit-status)
  2792. (global-set-key (kbd "C-x p") #'jao-prev-window)
  2793. (global-set-key (kbd "C-x o") 'other-window)
  2794. (global-set-key "\C-cj" #'join-line)
  2795. (global-set-key "\C-cn" #'next-error)
  2796. (global-set-key "\C-cq" #'auto-fill-mode)
  2797. (global-set-key "\C-xr\M-w" #'kill-rectangle-save)
  2798. (global-set-key "\C-c\C-z" #'comment-or-uncomment-region)
  2799. (global-set-key "\C-z" #'comment-or-uncomment-region))
  2800. (jao-global-keybindings)
  2801. ;;; Last minute (post.el)
  2802. (jao-load-site-el "post")