init.el 108 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330
  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. ;;; Windows
  762. ;;;; splitting and switch
  763. (setq split-height-threshold 80
  764. split-width-threshold 144
  765. display-buffer-avoid-small-windows 20)
  766. (setq switch-to-buffer-preserve-window-point nil
  767. switch-to-buffer-obey-display-actions t
  768. switch-to-prev-buffer-skip 'this) ;; don't switch to a
  769. ;; buffer already visible in
  770. ;; this frame
  771. (global-set-key (kbd "C-x _") #'delete-other-windows-vertically)
  772. ;;;; first window
  773. (defvar jao-first-window--from nil)
  774. (defun jao-first-window ()
  775. "Go to previous windows in frame, remembering where we were."
  776. (interactive)
  777. (let ((cb (current-buffer)))
  778. (if (eq (get-buffer-window cb) (select-window (frame-first-window)))
  779. (when jao-first-window--from (pop-to-buffer jao-first-window--from))
  780. (setq jao-first-window--from cb))))
  781. (global-set-key (kbd "s-a") #'jao-first-window)
  782. (global-set-key (kbd "M-a") #'jao-first-window)
  783. ;;;; window navigation (custom)
  784. (defun jao-nth-window (n)
  785. (if (zerop n)
  786. 'jao-first-window
  787. `(lambda ()
  788. (interactive)
  789. (select-window (frame-first-window))
  790. (dotimes (x ,n) (other-window 1)))))
  791. (defun jao-prev-window ()
  792. "Go to previous window."
  793. (interactive)
  794. (other-window -1))
  795. (defvar jao-prev-window-repeat-map
  796. (let ((map (make-sparse-keymap)))
  797. (define-key map "p" 'jao-prev-window)
  798. (define-key map "P" (lambda ()
  799. (interactive)
  800. (setq repeat-map 'jao-prev-window-repeat-map)
  801. (other-window 1)))
  802. map)
  803. "Keymap to repeat `prev-window' key sequences. Used in `repeat-mode'.")
  804. (put 'jao-prev-window 'repeat-map jao-prev-window-repeat-map)
  805. (mapc (lambda (n)
  806. (global-set-key (format "\C-c%s" (1+ n)) (jao-nth-window n)))
  807. '(0 1 2 3 4 5 6 7 8))
  808. ;; transposing windows
  809. (defun transpose-windows (arg)
  810. "Transpose the buffers shown in two windows."
  811. (interactive "p")
  812. (let ((selector (if (>= arg 0) 'next-window 'previous-window)))
  813. (while (/= arg 0)
  814. (let ((this-win (window-buffer))
  815. (next-win (window-buffer (funcall selector))))
  816. (set-window-buffer (selected-window) next-win)
  817. (set-window-buffer (funcall selector) this-win)
  818. (select-window (funcall selector)))
  819. (setq arg (if (> arg 0) (1- arg) (1+ arg))))))
  820. (define-key ctl-x-4-map (kbd "t") 'transpose-windows)
  821. ;;;; winner mode
  822. (winner-mode 1)
  823. ;;; Frames
  824. ;;;; frame geometry
  825. (setq frame-resize-pixelwise t)
  826. (modify-all-frames-parameters
  827. `((horizontal-scroll-bars . nil)
  828. (vertical-scroll-bars . nil)
  829. (scroll-bar-width . 0)
  830. (menu-bar . nil)))
  831. ;;;; frame layout, title, etc
  832. (setq frame-title-format '("%b - emacs"))
  833. (use-package fringe)
  834. (fringe-mode)
  835. (menu-bar-mode -1)
  836. ;; (setting it to nil avoids mouse wrapping after other-frame)
  837. (setq focus-follows-mouse (and window-system t))
  838. (use-package scroll-bar)
  839. (set-scroll-bar-mode nil)
  840. (use-package tool-bar)
  841. (tool-bar-mode -1)
  842. (defalias 'jao-trisect 'jao-afio-trisect)
  843. (defun jao-bisect ()
  844. (interactive)
  845. (jao-trisect t)
  846. (other-window 1)
  847. (delete-window))
  848. ;;;; afio
  849. (use-package jao-afio
  850. :demand t
  851. :config (jao-afio-setup (not window-system))
  852. :bind (("C-c f" . 'jao-afio-goto-main)
  853. ("C-c g" . 'jao-afio-goto-mail)
  854. ("C-c w" . 'jao-afio-goto-www)
  855. ("C-c z" . 'jao-afio-goto-docs)
  856. ("C-c t" . 'jao-afio-goto-chats)
  857. ("C-c 0" . 'jao-afio-goto-scratch)
  858. ("M-o" . 'jao-afio-toggle)))
  859. (add-hook 'jao-afio-switch-hook 'jao-minibuffer-refresh t)
  860. (defun jao-current--frame-id ()
  861. (propertize (cond ((and (fboundp 'jao-exwm-enabled)
  862. (jao-exwm-enabled-p)
  863. (not (bound-and-true-p jao-exwm--use-afio))
  864. (boundp 'exwm-workspace-current-index))
  865. (format "F%s" exwm-workspace-current-index))
  866. (t jao-afio-use-frames (or (jao-afio-frame-name) ""))
  867. (t (format "%s" (or (jao-afio-frame-no) ""))))
  868. 'face 'font-lock-warning-face))
  869. (jao-minibuffer-add-variable '(jao-current--frame-id) 100)
  870. ;;; Writing and writing modes
  871. ;;;; copyright notices
  872. (setq copyright-year-ranges t)
  873. (add-hook 'write-file-functions 'copyright-update)
  874. ;;;; indent on yank
  875. (defvar jao-auto-indent-modes
  876. '(emacs-lisp-mode ;; clojure-mode
  877. scheme-mode objc-mode
  878. tuareg-mode c-mode c++-mode
  879. tcl-mode sql-mode
  880. perl-mode cperl-mode
  881. java-mode jde-mode
  882. LaTeX-mode TeX-mode))
  883. (defadvice yank (after indent-region activate)
  884. (if (member major-mode jao-auto-indent-modes)
  885. (indent-region (region-beginning) (region-end) nil)))
  886. ;;;; org mode
  887. (require 'jao-custom-org)
  888. ;;;; blog
  889. (require 'jao-custom-blog)
  890. ;;;; text-ish mode settings
  891. ;; SENTENCES separated by just one space
  892. (setq sentence-end "[.?!][]\"')]*\\($\\|\t\\| \\)[ \t\n]*")
  893. (setq sentence-end-double-space t)
  894. ;; copy rectangle
  895. (defun kill-rectangle-save (start end)
  896. "Save the region-rectangle as the last killed one."
  897. (interactive "r")
  898. (require 'rect) ; Make sure killed-rectangle is defvar'ed.
  899. (setq killed-rectangle (extract-rectangle start end))
  900. (message "Rectangle saved"))
  901. ;; text mode, autoinserts and write hooks
  902. (setq default-major-mode 'text-mode)
  903. (add-hook 'text-mode-hook 'turn-on-auto-fill)
  904. ;;;; dictionaries
  905. (use-package dictionary
  906. :init (setq dictionary-use-single-buffer t
  907. dictionary-server "localhost")
  908. :commands (dictionary-search
  909. dictionary-match-words
  910. dictionary-lookup-definition
  911. dictionary
  912. dictionary-mouse-popup-matching-words
  913. dictionary-popup-matching-words
  914. dictionary-tooltip-mode
  915. global-dictionary-tooltip-mode)
  916. :bind (("C-c d" . dictionary-search)))
  917. (use-package ispell
  918. :custom ((ispell-personal-dictionary
  919. (expand-file-name "~/.emacs.d/ispell.dict"))))
  920. (use-package reverso
  921. :ensure t
  922. :init (setq reverso-languages '(english spanish french german)))
  923. ;; (use-package wordreference
  924. ;; :ensure t
  925. ;; :init (setq wordreference-target-lang "es"
  926. ;; wordreference-source-lang "en")
  927. ;; :bind (("C-c D" . wordreference-search)))
  928. ;;;; markdown
  929. (use-package markdown-mode
  930. :ensure t
  931. :init (setq markdown-command '("pandoc" "--from=markdown" "--to=html5")
  932. markdown-asymmetric-header t
  933. markdown-enable-wiki-links t
  934. markdown-wiki-link-fontify-missing t
  935. markdown-enable-math nil ;; toggle with M-x markdown-toggle-math
  936. markdown-link-space-sub-char "-"
  937. markdown-gfm-additional-languages '("whizzml" "flatline")
  938. markdown-hide-urls t
  939. markdown-hide-markup nil
  940. markdown-fontify-code-blocks-natively t
  941. markdown-fontify-whole-heading-line t
  942. markdown-unordered-list-item-prefix t)
  943. :hook (markdown-mode . outline-minor-mode)
  944. :config
  945. (dolist (u '("doc" "message" "notmuch"))
  946. (add-to-list 'markdown-uri-types u))
  947. (use-package markdown-toc :ensure t))
  948. ;; used by markdown mode to edit code blocks
  949. (use-package edit-indirect :ensure t)
  950. (dolist (ext '("\\.md$" "\\.markdown$"))
  951. (add-to-list 'auto-mode-alist (cons ext 'markdown-mode)))
  952. ;;;; TeX and LaTex
  953. (use-package tex-site
  954. :ensure auctex
  955. :init
  956. (setq TeX-auto-save t)
  957. (setq TeX-parse-self t)
  958. (setq TeX-a4-paper t)
  959. (setq TeX-auto-local ".tex-auto-local")
  960. ;; Preferred view format: dvi, ps, pdf, pdfs
  961. (setq TeX-view-format "pdf")
  962. (setq-default TeX-master "../main") ; nil to ask
  963. (setq TeX-view-program-selection
  964. ;; '((output-dvi "open")
  965. ;; (output-pdf "open")
  966. ;; (output-html "open"))
  967. '(((output-dvi has-no-display-manager) "dvi2tty")
  968. ((output-dvi style-pstricks) "dvips and gv")
  969. (output-dvi "xdvi")
  970. (output-pdf "xdg-open")
  971. (output-html "xdg-open")))
  972. ;; to make RefTeX faster for large documents, try these:
  973. (setq reftex-enable-partial-scans t)
  974. (setq reftex-save-parse-info t)
  975. (setq reftex-use-multiple-selection-buffers t)
  976. ;; to integrate with AUCTeX
  977. (setq reftex-plug-into-AUCTeX t)
  978. (setq reftex-ref-style-default-list
  979. '("Hyperref" "Varioref" "Fancyref"))
  980. (setq LaTeX-command "latex -shell-escape")
  981. (setq LaTeX-biblatex-use-Biber t)
  982. (setq bibtex-dialect 'biblatex)
  983. :config
  984. (add-hook 'TeX-after-compilation-finished-functions 'TeX-revert-document-buffer)
  985. (add-hook 'LaTeX-mode-hook 'turn-on-reftex))
  986. ;;; Browsing
  987. ;;;; variables
  988. (defvar jao-browse-doc-use-emacs-p t)
  989. (defvar jao-browse-url-function nil)
  990. (defvar jao-browse-url-external-function nil)
  991. ;;;; url around point
  992. (defun jao-url-around-point (&optional current-url)
  993. (or (and (fboundp 'w3m-anchor) (w3m-anchor))
  994. (shr-url-at-point nil)
  995. (ffap-url-at-point)
  996. (thing-at-point 'url)
  997. (when current-url
  998. (or (and (fboundp 'w3m-anchor) (w3m-anchor))
  999. (and (derived-mode-p 'eww-mode) (plist-get eww-data :url))))))
  1000. (defun jao--url-prompt (&optional prefix)
  1001. (let* ((def (jao-url-around-point t))
  1002. (prompt (concat prefix "URL" (if def (format " (%s): " def) ": "))))
  1003. (read-string prompt nil nil def)))
  1004. ;;;; downloads using wget
  1005. (defun jao-wget--get-title (filename)
  1006. (or (and (derived-mode-p 'w3m-mode) (w3m-current-title))
  1007. (plist-get eww-data :title)
  1008. (and (not (string-blank-p (or filename "")))
  1009. (subst-char-in-string ?- ? (capitalize (file-name-base filename))))))
  1010. (defun jao-wget (url &optional user pwd)
  1011. "Download URL using wget and kill a link for an org note."
  1012. (let* ((def (file-name-nondirectory url))
  1013. (pmt (format "Save %s to: " url))
  1014. (read-file-name-function nil)
  1015. (dest (expand-file-name
  1016. (read-file-name pmt jao-sink-dir nil nil def)))
  1017. (title (jao-wget--get-title dest))
  1018. (src-url (or (jao-url-around-point t) (file-name-directory url)))
  1019. (auth (when (and user pwd)
  1020. `(,(format "--http-user=%s" user)
  1021. ,(format "--http-password=%s" pwd))))
  1022. (lnk (concat "doc:" (file-name-nondirectory dest))))
  1023. (switch-to-buffer-other-window (get-buffer-create "*downloads*"))
  1024. (erase-buffer)
  1025. (kill-new (format "%s (from %s)"
  1026. (org-link-make-string lnk title)
  1027. (org-link-make-string src-url "here")))
  1028. (apply 'make-term `("downloads" "wget" nil ,@auth "-O" ,dest ,url))))
  1029. (defun jao-download (url &optional pws)
  1030. "Download URL using wget"
  1031. (interactive (list (jao--url-prompt)))
  1032. (when url
  1033. (let ((usr (and pws (read-string "Login name: ")))
  1034. (pwd (and pws (read-passwd "Password: "))))
  1035. (jao-wget url usr pwd))))
  1036. (with-eval-after-load "embark"
  1037. (define-key embark-url-map (kbd "d") #'jao-download))
  1038. ;;;; video
  1039. (defvar jao-video--url-rx
  1040. (format "^https?://\\(?:www\\.\\)?%s/.+"
  1041. (regexp-opt '("youtu.be"
  1042. "youtube.com"
  1043. "blip.tv"
  1044. "vimeo.com"
  1045. "infoq.com")
  1046. t)))
  1047. (defvar jao-video--ext-rx
  1048. (format "^https?://.+/.+\\.%s" (regexp-opt '("mp3" "webm" "mp4"))))
  1049. (defun jao-video--url-p (url)
  1050. (or (string-match-p jao-video--url-rx url)
  1051. (string-match-p jao-video--ext-rx url)))
  1052. (defun jao--remote-run (url prg)
  1053. (let ((args (format "%s %s" prg (shell-quote-argument url))))
  1054. (start-process-shell-command prg nil args)))
  1055. (defun jao--mpv (url &rest _args) (jao--remote-run url "mpv"))
  1056. (defun jao--vlc (url &rest _args) (jao--remote-run url "vlc"))
  1057. (defvar jao--video-player 'jao--mpv)
  1058. (defun jao-view-video (url)
  1059. "Tries to stream a video from the current or given URL"
  1060. (interactive (list (jao--url-prompt "Video ")))
  1061. (when url (funcall jao--video-player url)))
  1062. (defun jao-maybe-view-video (url &rest _ignored)
  1063. (interactive)
  1064. (if (y-or-n-p "View video (y) or web page (n)? ")
  1065. (jao-view-video url)
  1066. (funcall jao-browse-url-function url)))
  1067. ;;;; web browsers
  1068. (defun jao-www--buffer-p (b)
  1069. (with-current-buffer b
  1070. (or (derived-mode-p 'w3m-mode 'eww-mode)
  1071. (and (boundp 'exwm-class-name)
  1072. (member exwm-class-name '("vlc" "mpv"))))))
  1073. (require 'jao-custom-eww)
  1074. ;; (require 'jao-custom-w3m)
  1075. ;;;; browse-url
  1076. (require 'browse-url)
  1077. (setq browse-url-generic-program "~/bin/firehog")
  1078. (defun jao-browse-with-external-browser (&rest url)
  1079. "Browse with external hogging"
  1080. (interactive "s")
  1081. (let ((url (or (car url) (jao-url-around-point))))
  1082. (if (not url)
  1083. (message "No URL at point")
  1084. (cond ((and (jao-exwm-enabled-p) (fboundp 'jao-exwm-firefox))
  1085. (jao-exwm-firefox))
  1086. (jao-river-enabled (jao-river-to-ws 2))
  1087. (jao-sway-enabled (jao-sway-firefox)))
  1088. (browse-url-generic url))))
  1089. (setq jao-browse-url-external-function 'jao-browse-with-external-browser)
  1090. (defun jao--fln (url)
  1091. (shell-quote-argument
  1092. (if (string-match "^[^:]*:/*?\\(/?[^/].*\\)" url)
  1093. (match-string-no-properties 1 url)
  1094. url)))
  1095. (defun jao--browse-doc (url &rest _ignored)
  1096. (let* ((url (substring-no-properties url))
  1097. (file (jao--fln url)))
  1098. (when file
  1099. (unless (file-exists-p file)
  1100. (error "File %s does not exist" file))
  1101. (jao-open-doc file))))
  1102. (defun jao--make-file-rx (exts)
  1103. (format "file:/?/?.+\\.%s$" (regexp-opt exts)))
  1104. (defvar jao--see-exts (jao--make-file-rx '("jpg" "jpeg" "png")))
  1105. (defvar jao--doc-exts
  1106. (jao--make-file-rx '("ps" "ps.gz" "pdf" "dvi" "djvu" "chm")))
  1107. (defvar jao-browse-url-wget-exts
  1108. '("ps" "pdf" "dvi" "djvu" "zip" "gz" "tgz"))
  1109. (defvar jao-browse-external-domains
  1110. '("github.com" "gitlab.com" "slack.com" "spotify.com" "drive.google.com"
  1111. "meet.google.com" "docs.google.com" "x.com" "twitter.com"
  1112. "t.com" "linkedin.com" "bigml.com" "slack.com" "zoom.us"))
  1113. (defvar jao-browse--external-regexp
  1114. (format "https?://.*%s\\(/.*\\)?"
  1115. (regexp-opt jao-browse-external-domains)))
  1116. (defun jao-wget--regexp ()
  1117. (concat "^http[s]?://.+\\(\\."
  1118. (mapconcat 'identity jao-browse-url-wget-exts "\\|\\.")
  1119. "\\)\\'"))
  1120. (defun jao--see (url &rest _r)
  1121. (start-process-shell-command "see" nil (format "see %s" (jao--fln url))))
  1122. (defun jao--find-file-other-window (url &rest _)
  1123. (find-file-other-window (jao--fln url)))
  1124. (defvar jao-browse--sound-rx
  1125. (format "^https?://.*/.*\\.%s" (regexp-opt '("mp3" "flv"))))
  1126. (defun jao-browse-play-sound-url (url &rest _)
  1127. (jao-mpc-add-or-play-url url))
  1128. (defun jao-browse-url-browse (&rest args)
  1129. (apply jao-browse-url-function args))
  1130. (setq browse-url-handlers
  1131. `((jao-video--url-p . jao-maybe-view-video)
  1132. (,jao--doc-exts . jao--browse-doc)
  1133. (,jao--see-exts . jao--see)
  1134. ("^file://?.+\\.html?$" . ,jao-browse-url-function)
  1135. ("^file://?" . jao--find-file-other-window)
  1136. (,jao-browse--external-regexp . ,jao-browse-url-external-function)
  1137. ("^https?://.*\\.gotomeeting\\.com\\.*" . browse-url-chrome)
  1138. (,jao-browse--sound-rx . jao-browse-play-sound-url)
  1139. (,(jao-wget--regexp) . jao-download)
  1140. ("." . jao-browse-url-browse)))
  1141. (when (< emacs-major-version 28)
  1142. (setf (alist-get 'jao-video--url-p browse-url-handlers nil t) nil)
  1143. (setq browse-url-browser-function browse-url-handlers))
  1144. ;;;; subscribe to rss using r2e
  1145. (autoload 'View-quit "view")
  1146. (defun jao-rss--find-url ()
  1147. (save-excursion
  1148. (when (derived-mode-p 'w3m-mode 'eww-mode)
  1149. (if (fboundp 'w3m-view-source) (w3m-view-source) (eww-view-source)))
  1150. (goto-char (point-min))
  1151. (when (re-search-forward
  1152. "type=\"application/\\(?:atom\\|rss\\)\\+xml\" +" nil t)
  1153. (let ((url (save-excursion
  1154. (when (re-search-forward
  1155. "href=\"\\([^\n\"]+\\)\"" nil t)
  1156. (match-string-no-properties 1))))
  1157. (title (when (re-search-forward
  1158. "\\(?:title=\"\\([^\n\"]+\\)\" +\\)" nil t)
  1159. (match-string-no-properties 1))))
  1160. (cond ((derived-mode-p 'w3m-view-mode) (w3m-view-source))
  1161. ((string-match-p ".*\\*eww-source\\b.*" (buffer-name))
  1162. (View-quit)))
  1163. (when url (cons url (or title "")))))))
  1164. (defun jao-rss2e-append (name url mbox)
  1165. (with-current-buffer (find-file-noselect "~/.config/rss2email.cfg")
  1166. (goto-char (point-max))
  1167. (insert "[feed." name "]\nurl = " url)
  1168. (insert "\nto = " mbox "+" name "@localhost")
  1169. (insert "\nmaildir-mailbox = " mbox "\n\n")
  1170. (save-buffer)))
  1171. (defun jao-rss--feeds-dirs ()
  1172. (mapcar (lambda (d) (cadr (split-string d "\\.")))
  1173. (directory-files "~/.emacs.d/gnus/Mail/" nil "^feeds")))
  1174. (defun jao-rss-subscribe (url)
  1175. "Subscribe to a given RSS URL. If URL not given, look for it."
  1176. (interactive (list (or (jao-url-around-point)
  1177. (jao-rss--find-url)
  1178. (read-string "Feed URL: "))))
  1179. (let* ((url+title (ensure-list url))
  1180. (url (car url+title))
  1181. (title (cdr url+title)))
  1182. (unless url (error "No feeds found"))
  1183. (let ((url (if (string-match "^feed:" url) (substring url 5) url)))
  1184. (when (y-or-n-p (format "Subscribe to <%s>? " url))
  1185. (let* ((name (read-string "Feed name: " title))
  1186. (cats (cons "prog" (jao-notmuch--subtags "feeds")))
  1187. (cat (completing-read "Category: " cats nil t))
  1188. (subs (format "r2e add %s '%s' feeds.%s@localhost"
  1189. name url cat)))
  1190. ;; (jao-rss2e-append name url cat)
  1191. (shell-command-to-string subs)
  1192. (shell-command (format "r2e run %s" name)))))))
  1193. ;;; PDFs and other docs
  1194. ;;;; open pdfs
  1195. (use-package jao-pdf :demand t)
  1196. (use-package saveplace-pdf-view
  1197. :ensure t
  1198. :demand t
  1199. :after doc-view)
  1200. (setq jao-open-doc-fun 'jao-find-or-open)
  1201. (setq jao-org-open-pdf-fun 'jao-find-or-open)
  1202. (defun jao-zathura-open (file page)
  1203. (let ((id (jao-x11-search-window (jao-pdf-zathura-title-rx file))))
  1204. (if (string-blank-p id)
  1205. (progn
  1206. (when jao-xmonad-enabled (jao-x11-goto-ws 2))
  1207. (jao-shell-exec (jao-pdf-zathura-open-cmd file page)))
  1208. (let* ((page (if page (format " && xdotool type %dg" page) ""))
  1209. (cmd (format "xdotool windowactivate %s%s" id page)))
  1210. (jao-shell-exec cmd t)))))
  1211. (defun jao-x11-zathura-goto-org (&optional title no-ask)
  1212. (let ((title (or title (jao-shell-string "xdotool"
  1213. "getactivewindow"
  1214. "getwindowname"))))
  1215. (jao-org-open-from-zathura title no-ask)))
  1216. (defun jao-find-or-open (file &optional page height)
  1217. (cond ((and jao-browse-doc-use-emacs-p window-system)
  1218. (let* ((buffs (buffer-list))
  1219. (b (catch 'done
  1220. (while buffs
  1221. (when (string-equal (buffer-file-name (car buffs)) file)
  1222. (throw 'done (car buffs)))
  1223. (setq buffs (cdr buffs))))))
  1224. (jao-afio-goto-docs)
  1225. (if b (pop-to-buffer b) (find-file file))
  1226. (when page (jao-doc-view-goto-page page height))))
  1227. (jao-river-enabled (jao-river-open-with-zathura file page))
  1228. (jao-sway-enabled (jao-sway-open-with-zathura file page))
  1229. (t (jao-zathura-open file page))))
  1230. (defun jao-open-doc (&optional file page height)
  1231. (interactive)
  1232. (when-let (file (or file
  1233. (read-file-name "Document: "
  1234. (concat jao-org-dir "/doc/"))))
  1235. (funcall jao-open-doc-fun file page height)))
  1236. (defun jao-select-pdf ()
  1237. (interactive)
  1238. (jao-buffer-same-mode '(pdf-view-mode doc-view-mode)
  1239. #'jao-afio-goto-docs))
  1240. (defun jao-open-with-zathura ()
  1241. (interactive)
  1242. (when-let (f buffer-file-name)
  1243. (let ((p (jao-doc-view-current-page)))
  1244. (cond (jao-river-enabled (jao-river-open-with-zathura f p))
  1245. (jao-sway-enabled (jao-sway-open-with-zathura f p))
  1246. (t (jao-zathura-open f p))))))
  1247. ;; doc:// links for browse-url
  1248. (defun jao-open-doc-url (url &rest _)
  1249. (when (string-match "doc://\\([^?]+\\)\\(\\?.*\\)?" url)
  1250. (let ((file (match-string 1 url))
  1251. (page (when-let* ((qs (match-string 2 url))
  1252. (long (> (length qs) 1))
  1253. (ps (url-parse-query-string (substring qs 1)))
  1254. (pn (cadr (assoc "page" ps))))
  1255. (string-to-number pn))))
  1256. (jao-open-doc (expand-file-name (concat "doc/" file) jao-org-dir) page))))
  1257. (add-to-list 'browse-url-handlers (cons "^doc://.+" 'jao-open-doc-url))
  1258. ;;;; doc-view
  1259. (use-package doc-view
  1260. :init
  1261. (setq doc-view-cache-directory "~/.emacs.d/cache/docview"
  1262. doc-view-resolution 110
  1263. doc-view-continuous t
  1264. doc-view-conversion-refresh-interval 1
  1265. doc-view-mupdf-use-svg t)
  1266. :hook ((doc-view-mode . jao-doc-session-mark))
  1267. :bind (:map doc-view-mode-map
  1268. ("j" . doc-view-next-line-or-next-page)
  1269. ("J" . doc-view-scroll-up-or-next-page)
  1270. ("k" . doc-view-previous-line-or-previous-page)
  1271. ("K" . doc-view-scroll-down-or-previous-page)
  1272. ("z" . jao-open-with-zathura)))
  1273. (use-package jao-doc-session :demand t)
  1274. (use-package jao-doc-view
  1275. :demand t
  1276. :bind (:map doc-view-mode-map
  1277. ("b" . jao-doc-view-back)
  1278. ("B" . jao-doc-view-forward)
  1279. ("S" . jao-doc-session-save)
  1280. ("u" . jao-doc-view-visit-url)))
  1281. ;;;; epub
  1282. (use-package nov
  1283. :ensure t
  1284. :after doc-view
  1285. :init (setq nov-variable-pitch t
  1286. nov-text-width nil)
  1287. :config
  1288. (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
  1289. (defun jao-nov-register-session ()
  1290. (jao-doc-session-mark nov-file-name))
  1291. (add-hook 'nov-mode-hook #'jao-nov-register-session))
  1292. ;;;; transient
  1293. (defun jao-org-pdf-goto-org-linking ()
  1294. (interactive)
  1295. (jao-org-pdf-goto-org 4))
  1296. (jao-transient-major-mode doc-view
  1297. ["Notes"
  1298. ("o" "notes file" jao-org-pdf-goto-org)
  1299. ("O" "notes file, linking" jao-org-pdf-goto-org-linking)]
  1300. ["Navigation"
  1301. ("b" "back jump" jao-doc-view-back)
  1302. ("B" "forward jump" jao-doc-view-back)
  1303. ("u" "visit URL" jao-doc-view-visit-url)]
  1304. ["Slices"
  1305. ("cb" "bounding box" doc-view-set-slice-from-bounding-box)
  1306. ("cm" "using mouse" doc-view-set-slice-using-mouse)]
  1307. ["Session"
  1308. ("s" "load session" jao-afio-open-pdf-session)
  1309. ("S" "save session" jao-doc-session-save)
  1310. ("d" "visit cache directory" doc-view-dired-cache)]
  1311. ["External viewers"
  1312. ("z" "open with zathura" jao-open-with-zathura)])
  1313. (with-eval-after-load "pdf-view"
  1314. (jao-transient-major-mode pdf-view
  1315. ["Notes"
  1316. ("o" "notes file" jao-org-pdf-goto-org)
  1317. ("O" "notes file, linking" jao-org-pdf-goto-org-linking)]
  1318. ["Navigation"
  1319. ("b" "back jump" pdf-history-backward)
  1320. ("f" "forward jump" pdf-history-forward)]
  1321. ["Session"
  1322. ("s" "load session" jao-afio-open-pdf-session)
  1323. ("S" "save session" jao-doc-session-save)]
  1324. ["External viewers"
  1325. ("z" "open with zathura" jao-open-with-zathura)]))
  1326. ;; (transient-get-suffix 'jao-transient-pdf-view '(0 -1))
  1327. ;;; Email
  1328. (require 'jao-custom-email)
  1329. ;;; Shells and terms
  1330. ;;;; shell modes
  1331. (setq sh-basic-offset 2)
  1332. ;; translates ANSI colors into text-properties, for eshell
  1333. (autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)
  1334. (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
  1335. (defvar jao-use-vterm nil)
  1336. (defvar jao-use-eat nil)
  1337. (add-to-list 'display-buffer-alist
  1338. '("\\*Async Shell Command\\*" (display-buffer-no-window)))
  1339. ;;;; eat
  1340. (use-package eat
  1341. :ensure t
  1342. :commands jao-exec-in-term
  1343. :init (setq jao-use-eat t
  1344. eat-kill-buffer-on-exit t
  1345. eat-enable-yank-to-terminal t)
  1346. :hook ((eshell-mode . eat-eshell-mode)
  1347. (eshell-mode . eat-eshell-visual-command-mode))
  1348. :diminish ((eat-eshell-mode . "")))
  1349. ;;;; term
  1350. (defvar-local jao-term--cmd nil)
  1351. (defun jao-term--find (cmd)
  1352. (seq-find (lambda (b)
  1353. (with-current-buffer b
  1354. (and (derived-mode-p 'eat-mode 'term-mode 'vterm-mode)
  1355. (string= (or jao-term--cmd "") cmd))))
  1356. (buffer-list)))
  1357. (defun jao-exec-in-term (cmd &optional name)
  1358. (interactive "SCommand")
  1359. (require 'eat nil t)
  1360. (cond ((and jao-use-vterm (fboundp 'jao-exec-in-vterm))
  1361. (jao-exec-in-vterm cmd name))
  1362. (jao-use-eat (let ((eat-term-name "xterm-256color"))
  1363. (with-current-buffer (eat cmd t)
  1364. (setq-local jao-term--cmd cmd))))
  1365. (t (ansi-term "bash" name)
  1366. (set-process-sentinel (get-buffer-process (current-buffer))
  1367. (lambda (process event)
  1368. (when (string= event "finished\n")
  1369. (kill-buffer (process-buffer process)))))
  1370. (setq-local jao-term--cmd cmd)
  1371. (term-send-string nil (concat cmd " ; exit\n")))))
  1372. (defmacro jao-def-exec-in-term (name cmd &rest prelude)
  1373. `(defun ,(intern (format "jao-term-%s" name)) (&optional term)
  1374. (interactive "P")
  1375. ,@prelude
  1376. (let ((jao-use-vterm (if term (not jao-use-vterm) jao-use-vterm)))
  1377. (if-let ((b (jao-term--find ,cmd)))
  1378. (pop-to-buffer b)
  1379. (jao-exec-in-term ,cmd ,(format "*%s*" name))))))
  1380. ;;;; eshell
  1381. ;;;;; basic custom
  1382. (use-package eshell
  1383. :init
  1384. (setq eshell-directory-name "~/.emacs.d/eshell"
  1385. eshell-hist-ignoredups 'erase
  1386. eshell-history-size 1000000
  1387. eshell-error-if-no-glob nil)
  1388. (defun jao-eshell--outline ()
  1389. (setq-local outline-regexp eshell-prompt-regexp))
  1390. :config (setq eshell-prompt-repeat-map nil)
  1391. :hook (eshell-mode . jao-eshell--outline))
  1392. ;;;;; colors
  1393. (autoload 'ansi-color-apply "ansi-color")
  1394. ;; (add-hook 'eshell-preoutput-filter-functions 'ansi-color-filter-apply)
  1395. (add-hook 'eshell-preoutput-filter-functions 'ansi-color-apply)
  1396. (use-package eshell-syntax-highlighting
  1397. :after esh-mode
  1398. :ensure t
  1399. :config
  1400. ;; Enable in all Eshell buffers.
  1401. (eshell-syntax-highlighting-global-mode +1))
  1402. ;;;;; visual commands
  1403. (require 'em-term)
  1404. (dolist (c '("editor" "more" "wget" "dict" "vim" "links" "w3m" "guile"
  1405. "zmore" "pager" "aptitude" "su" "htop" "top"
  1406. "screen" "whizzml" "iex" "spt"))
  1407. (add-to-list 'eshell-visual-commands c))
  1408. (setq eshell-visual-subcommands '(("git" "log" "diff" "show")
  1409. ("sudo" "vim")
  1410. ("rebar3" "shell"))
  1411. eshell-destroy-buffer-when-process-dies nil
  1412. eshell-escape-control-x t)
  1413. ;;;;; bol
  1414. (defun jao-eshell-maybe-bol ()
  1415. (interactive)
  1416. (let ((p (point)))
  1417. (eshell-bol)
  1418. (if (= p (point))
  1419. (beginning-of-line))))
  1420. ;;;;; prompt
  1421. ;; tracking git repos
  1422. (defun jao-eshell--git-dirty ()
  1423. (shell-command-to-string "git diff-index --quiet HEAD -- || echo -n '*'"))
  1424. (use-package git-ps1-mode
  1425. :ensure t
  1426. :init (setq git-ps1-mode-showupstream "1"
  1427. git-ps1-mode-showdirtystate "1"))
  1428. (defun jao-eshell--git-info ()
  1429. (if (fboundp 'git-ps1-mode-get-current)
  1430. (git-ps1-mode-get-current)
  1431. (let ((desc (shell-command-to-string "git branch --no-color")))
  1432. (when (string-match "^* \\(\\<.+\\>\\)" desc)
  1433. (format "%s%s" (match-string 1 desc) (jao-eshell--git-dirty))))))
  1434. (defun jao-eshell--git-current-branch (suffix)
  1435. (let ((desc (or (jao-eshell--git-info) "")))
  1436. (cond ((and (string-empty-p desc) suffix) (format " (%s)" suffix))
  1437. ((string-empty-p (or suffix "")) (format " (%s)" desc))
  1438. (t (format " (%s %s)" desc suffix)))))
  1439. (defun jao-eshell--virtualenv ()
  1440. (let ((venv (getenv "VIRTUAL_ENV")))
  1441. (when (and venv (string-match ".*/\\([^/]+\\)/$" venv))
  1442. (match-string-no-properties 1 venv))))
  1443. (defun jao-eshell-prompt-function ()
  1444. (let* ((venv (jao-eshell--virtualenv))
  1445. (venv (if venv (format "%s" venv) "")))
  1446. (concat (abbreviate-file-name (eshell/pwd))
  1447. (jao-eshell--git-current-branch venv)
  1448. (if (= (user-uid) 0) " # " " $ "))))
  1449. (setq eshell-prompt-function 'jao-eshell-prompt-function)
  1450. ;;;;; in-term
  1451. (defun eshell/in-term (prog &rest args)
  1452. (switch-to-buffer
  1453. (apply #'make-term (format "in-term %s %s" prog args) prog nil args))
  1454. (term-mode)
  1455. (term-char-mode))
  1456. ;;;;; dir navigation
  1457. (use-package eshell-up
  1458. :ensure t
  1459. :config (setq eshell-up-print-parent-dir t))
  1460. (use-package eshell-autojump :ensure t)
  1461. ;;;;; completion
  1462. (defun jao-eshell-completion-capf ()
  1463. (let* ((b (save-excursion (eshell-bol) (point)))
  1464. (c (bash-completion-dynamic-complete-nocomint b (point) t)))
  1465. (when (and c (listp c))
  1466. (append c '(:exclusive no)))))
  1467. (defun jao-eshell--set-up-completion ()
  1468. (setq-local completion-styles '(basic partial-completion)
  1469. completion-at-point-functions
  1470. '(jao-eshell-completion-capf
  1471. pcomplete-completions-at-point t)))
  1472. (use-package bash-completion
  1473. :ensure t
  1474. :hook (eshell-mode . jao-eshell--set-up-completion))
  1475. ;;;;; toggle
  1476. (use-package jao-eshell-here
  1477. :demand t
  1478. :config (jao-define-attached-buffer "^\\*eshell" 0.5)
  1479. :bind (("<f1>" . jao-eshell-here-toggle)
  1480. ("C-<f1>" . jao-eshell-here-toggle-new)))
  1481. ;;;;; workarounds
  1482. ;; at some point, bash completion started insertig the TAB
  1483. ;; after the commands ends
  1484. (defun jao-eshell--clean-prompt ()
  1485. (eshell-bol)
  1486. (ignore-errors (kill-line)))
  1487. (add-hook 'eshell-after-prompt-hook 'jao-eshell--clean-prompt)
  1488. ;;;;; keybindings
  1489. (defun jao-eshell--kbds ()
  1490. (define-key eshell-mode-map "\C-a" 'jao-eshell-maybe-bol)
  1491. (define-key eshell-mode-map "\C-ci" 'consult-outline))
  1492. (jao-eshell--kbds)
  1493. ;;; Version control and CI
  1494. ;;;; vc options
  1495. (setq vc-follow-symlinks t)
  1496. (setq auto-revert-check-vc-info nil)
  1497. ;;;; diff fringe indicators (diff-hl)
  1498. (use-package diff-hl
  1499. :ensure t
  1500. :custom ((diff-hl-draw-borders nil)
  1501. (diff-hl-side 'right)
  1502. (diff-hl-margin-symbols-alist
  1503. '((insert . "█")
  1504. (delete . "█")
  1505. (change . "█")
  1506. (unknown . "█")
  1507. (ignored . "█"))))
  1508. :config
  1509. (map-keymap (lambda (_k cmd)
  1510. (put cmd 'repeat-map 'diff-hl-command-map))
  1511. diff-hl-command-map)
  1512. (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
  1513. (global-diff-hl-mode 1)
  1514. (unless (display-graphic-p) (diff-hl-margin-mode 1))
  1515. ;;;; magit/forge
  1516. (use-package magit
  1517. :ensure t
  1518. :commands magit-status
  1519. :init
  1520. (setq magit-status-initial-section nil
  1521. magit-define-global-key-bindings nil
  1522. magit-completing-read-function 'magit-builtin-completing-read
  1523. magit-display-buffer-function
  1524. 'magit-display-buffer-fullcolumn-most-v1
  1525. magit-delete-by-moving-to-trash nil
  1526. magit-last-seen-setup-instructions "1.4.0"
  1527. magit-log-edit-confirm-cancellation t
  1528. magit-omit-untracked-dir-contents t
  1529. magit-process-connection-type nil
  1530. magit-push-always-verify nil
  1531. magit-repository-directories
  1532. '(("/home/jao/usr/bigml" . 2)
  1533. ("/home/jao/usr/jao" . 3)
  1534. ("/usr/local/src" . 1))
  1535. magit-save-repository-buffers 'dontask
  1536. magit-section-visibility-indicator '("…" . t)
  1537. magit-status-buffer-switch-function 'switch-to-buffer
  1538. magit-status-show-hashes-in-headers t))
  1539. ;;;; forge
  1540. (use-package forge
  1541. :ensure t
  1542. :after magit
  1543. :init
  1544. (setq forge-topic-list-limit (cons 100 -1)
  1545. forge-pull-notifications nil)
  1546. :config
  1547. (use-package embark-vc :ensure t)
  1548. :bind ((:map forge-topic-mode-map ("M-w" . copy-region-as-kill))))
  1549. ;;;; code reviews
  1550. (use-package code-review
  1551. :disabled t
  1552. :ensure t
  1553. :after forge
  1554. :bind (:map magit-status-mode-map
  1555. ("C-c C-r" . code-review-forge-pr-at-point)))
  1556. ;;;; other git packages
  1557. (use-package git-timemachine :ensure t)
  1558. (use-package consult-git-log-grep
  1559. :ensure t
  1560. :custom (consult-git-log-grep-open-function #'magit-show-commit)
  1561. :bind (("C-c K" . consult-git-grep)))
  1562. ;; git config --local git-link.remote / git-link.branch
  1563. (use-package git-link :ensure t)
  1564. (use-package git-modes :ensure t)
  1565. ;;;; jenkins
  1566. (use-package jenkins
  1567. :ensure t
  1568. :init
  1569. ;; one also needs jenkins-api-token, jenkins-username and jenkins-url
  1570. ;; optionally: jenkins-colwidth-id, jenkins-colwidth-last-status
  1571. (setq jenkins-colwidth-name 35)
  1572. :config
  1573. (defun jao-jenkins-first-job (&rest _)
  1574. (interactive)
  1575. (goto-char (point-min))
  1576. (when (re-search-forward "^- Job" nil t)
  1577. (goto-char (match-beginning 0))))
  1578. (add-hook 'jenkins-job-view-mode-hook #'jao-jenkins-first-job)
  1579. (advice-add 'jenkins-job-render :after #'jao-jenkins-first-job)
  1580. (defun jenkins-refresh-console-output ()
  1581. (interactive)
  1582. (let ((n (buffer-name)))
  1583. (when (string-match "\\*jenkins-console-\\([^-]+\\)-\\(.+\\)\\*$" n)
  1584. (jenkins-get-console-output (match-string 1 n) (match-string 2 n))
  1585. (goto-char (point-max)))))
  1586. :bind (:map jenkins-job-view-mode-map
  1587. (("n" . next-line)
  1588. ("p" . previous-line)
  1589. ("f" . jao-jenkins-first-job)
  1590. ("RET" . jenkins--show-console-output-from-job-screen))
  1591. :map jenkins-console-output-mode-map
  1592. (("n" . next-line)
  1593. ("p" . previous-line)
  1594. ("g" . jenkins-refresh-console-output))))
  1595. ;;; Programming
  1596. ;;;; automatic modes
  1597. (add-to-list 'auto-mode-alist '("\\.mix\\'" . hexl-mode))
  1598. (add-to-list 'auto-mode-alist '("\\.m4\\'" . m4-mode))
  1599. (add-to-list 'auto-mode-alist '("\\.am\\'" . makefile-mode))
  1600. (add-to-list 'auto-mode-alist '("\\.pl\\'\\|\\.pm\\'" . cperl-mode))
  1601. ;;;; symbol overlay
  1602. (use-package symbol-overlay
  1603. :ensure t
  1604. :config
  1605. (defun jao-symbol-reveal (&rest _)
  1606. (when outline-minor-mode (outline-show-entry)))
  1607. (advice-add 'symbol-overlay-basic-jump :after 'jao-symbol-reveal)
  1608. (defun jao-symbol-put-and-next ()
  1609. (interactive)
  1610. (symbol-overlay-put)
  1611. (symbol-overlay-jump-next))
  1612. (defun jao-symbol-put-and-prev ()
  1613. (interactive)
  1614. (symbol-overlay-put)
  1615. (symbol-overlay-jump-prev))
  1616. :bind (:map prog-mode-map (("M-i" . symbol-overlay-put)
  1617. ("M-n" . jao-symbol-put-and-next)
  1618. ("M-p" . jao-symbol-put-and-prev)))
  1619. :hook (prog-mode . symbol-overlay-mode)
  1620. :diminish " ^")
  1621. ;;;; eglot
  1622. (use-package eglot
  1623. :bind (:map eglot-mode-map (("C-h ." . jao-eldoc-toggle))))
  1624. ;;;; paredit and parens
  1625. (require 'paren)
  1626. (show-paren-mode t)
  1627. (setq show-paren-context-when-offscreen t
  1628. show-paren-when-point-inside-paren nil)
  1629. (use-package paredit
  1630. :ensure t
  1631. :commands paredit-mode
  1632. :hook ((pie-mode . paredit-mode)
  1633. (scheme-mode . paredit-mode)
  1634. (clojure-mode . paredit-mode)
  1635. (emacs-lisp-mode . paredit-mode)
  1636. ;; (eval-expression-minibuffer-setup . paredit-mode)
  1637. (lisp-interaction-mode . disable-paredit-mode))
  1638. :diminish ((paredit-mode . " þ")))
  1639. ;;;; diff/ediff
  1640. (setq ediff-split-window-function 'split-window-horizontally)
  1641. (setq ediff-make-buffers-readonly-at-startup nil)
  1642. (setq ediff-window-setup-function 'ediff-setup-windows-plain)
  1643. (setq ediff-keep-variants nil)
  1644. ;;;; compilation
  1645. ;;;;; compilation mode options
  1646. (require 'compile)
  1647. (setq compilation-scroll-output t)
  1648. (setq compilation-error-regexp-alist
  1649. (remove 'omake compilation-error-regexp-alist))
  1650. ;; (add-hook 'compilation-mode-hook #'visual-line-mode)
  1651. ;;;;; mode line (no "Compiling"!)
  1652. (require 'compile)
  1653. (diminish 'compilation-minor-mode " ‡")
  1654. (when (< emacs-major-version 27)
  1655. (setcdr (assq 'compilation-in-progress minor-mode-alist) '(" ‡")))
  1656. (when (> emacs-major-version 26)
  1657. (setcdr (assq 'compilation-in-progress mode-line-modes) '("‡ ")))
  1658. ;;;;; colorizing compilation buffer
  1659. (setq compilation-message-face 'default)
  1660. (require 'ansi-color)
  1661. (defun endless/colorize-compilation ()
  1662. "Colorize from `compilation-filter-start' to `point'."
  1663. (let ((inhibit-read-only t))
  1664. (ansi-color-apply-on-region
  1665. compilation-filter-start (point))))
  1666. (add-hook 'compilation-filter-hook #'endless/colorize-compilation)
  1667. ;;;;; compilation commands
  1668. (use-package jao-compilation
  1669. :commands jao-compilation-setup
  1670. :bind (("C-c C" . compile)
  1671. ("C-c c" . jao-compile)))
  1672. (jao-compilation-setup)
  1673. ;;;;; next error
  1674. (setq next-error-find-buffer-function
  1675. #'next-error-buffer-on-selected-frame
  1676. next-error-verbose t)
  1677. ;;;; flymake
  1678. (use-package flymake
  1679. :ensure t
  1680. :custom ((flymake-mode-line-format '(" " flymake-mode-line-counters)))
  1681. :config
  1682. (jao-define-attached-buffer "^\\*Flymake diagnostics .*\\*\\'")
  1683. (transient-define-prefix jao-transient-flymake ()
  1684. ["Flymake"
  1685. ("d" "show diagnostics" flymake-show-buffer-diagnostics)
  1686. ("i" "show diagnostic" flymake-show-diagnostic)
  1687. ("n" "next error" flymake-goto-next-error)
  1688. ("p" "previous error" flymake-goto-prev-error)
  1689. ("c" "consult flymake" consult-flymake)])
  1690. :bind (:map flymake-mode-map (("M-m" . jao-transient-flymake))))
  1691. ;;;; workarounds
  1692. (setq c-type-finder-time-slot nil)
  1693. ;;;; outline minor mode
  1694. (use-package outline
  1695. :init (setq outline-minor-mode-use-buttons nil
  1696. outline-minor-mode-use-margins nil
  1697. outline-minor-mode-cycle t))
  1698. (defvar-local jao-outline-folded nil)
  1699. (dolist (v '(4 5 outline-show-only-headings))
  1700. (add-to-list 'safe-local-variable-values `(outline-default-state . ,v)))
  1701. (defun jao-outline-minor-mode-hide-all (&optional arg)
  1702. (interactive "P")
  1703. (outline-hide-sublevels (if arg 5 4)))
  1704. (defun jao-outline-minor-expand-all ()
  1705. (when jao-outline-minor-mode (outline-show-all)))
  1706. (defun jao-outline-minor-mode-toogle-fold (&optional arg)
  1707. (interactive "P")
  1708. (if (setq jao-outline-folded (not jao-outline-folded))
  1709. (jao-outline-minor-mode-hide-all arg)
  1710. (jao-outline-minor-expand-all)))
  1711. (use-package outline-minor-faces
  1712. :ensure t
  1713. :after outline)
  1714. (define-minor-mode jao-outline-minor-mode
  1715. "Minor outline mode for programming languages"
  1716. :lighter ""
  1717. :keymap `((,(kbd "C-c C-n") . outline-next-visible-heading)
  1718. (,(kbd "C-c C-p") . outline-previous-visible-heading)
  1719. (,(kbd "C-c o") . consult-outline)
  1720. (,(kbd "<f3>") . jao-outline-minor-mode-toogle-fold))
  1721. (if jao-outline-minor-mode
  1722. (progn (setq-local outline-level #'outline-level
  1723. outline-regexp (format "[%s]\\{3,\\} " comment-start))
  1724. (outline-minor-mode 1)
  1725. (outline-minor-faces-mode 1))
  1726. (outline-minor-mode -1)
  1727. (outline-minor-faces-mode -1)))
  1728. (add-hook 'find-function-after-hook #'jao-outline-minor-expand-all)
  1729. ;;; Programming languages
  1730. ;;;; Elisp
  1731. (add-hook 'emacs-lisp-mode-hook #'jao-outline-minor-mode)
  1732. (use-package edit-list :ensure t)
  1733. (use-package package-lint :ensure t)
  1734. ;; (use-package tree-inspector :ensure t)
  1735. (defun elisp-disassemble (function)
  1736. (interactive (list (function-called-at-point)))
  1737. (disassemble function))
  1738. (defun elisp-pp (sexp)
  1739. (with-output-to-temp-buffer "*Pp Eval Output*"
  1740. (pp sexp)
  1741. (with-current-buffer standard-output
  1742. (emacs-lisp-mode))))
  1743. (defun elisp-macroexpand (form)
  1744. (interactive (list (form-at-point 'sexp)))
  1745. (elisp-pp (macroexpand form)))
  1746. (defun elisp-macroexpand-all (form)
  1747. (interactive (list (form-at-point 'sexp)))
  1748. (elisp-pp (macroexpand-all form)))
  1749. (defun elisp-find-definition (name)
  1750. (interactive (list (thing-at-point 'symbol)))
  1751. (cond (name
  1752. (let ((symbol (intern-soft name))
  1753. (search (lambda (fun sym)
  1754. (let* ((r (save-excursion (funcall fun sym)))
  1755. (buffer (car r))
  1756. (point (cdr r)))
  1757. (cond ((not point)
  1758. (error "Found no definition for %s in %s"
  1759. name buffer))
  1760. (t
  1761. (switch-to-buffer buffer)
  1762. (goto-char point)
  1763. (recenter 1)))))))
  1764. (cond ((fboundp symbol)
  1765. (xref-push-marker-stack)
  1766. (funcall search 'find-function-noselect symbol))
  1767. ((boundp symbol)
  1768. (xref-push-marker-stack)
  1769. (funcall search 'find-variable-noselect symbol))
  1770. (t
  1771. (message "Symbol not bound: %S" symbol)))))
  1772. (t (message "No symbol at point"))))
  1773. (defun elisp-bytecompile-and-load ()
  1774. (interactive)
  1775. (or buffer-file-name
  1776. (error "The buffer must be saved in a file first"))
  1777. (require 'bytecomp)
  1778. ;; Recompile if file or buffer has changed since last compilation.
  1779. (when (and (buffer-modified-p)
  1780. (y-or-n-p (format "save buffer %s first? " (buffer-name))))
  1781. (save-buffer))
  1782. (let ((filename (expand-file-name buffer-file-name)))
  1783. (with-temp-buffer
  1784. (byte-compile-file filename))))
  1785. (use-package elisp-mode
  1786. :bind (:map emacs-lisp-mode-map
  1787. (("C-c C-M" . emacs-lisp-macroexpand)
  1788. ("C-c C-m" . elisp-macroexpand-all)
  1789. ("C-c C-k" . elisp-bytecompile-and-load)
  1790. ;; ("C-c C-p" . pp-eval-last-sexp)
  1791. ("M-." . elisp-find-definition)
  1792. ("M-," . pop-tag-mark)
  1793. ("C-c <" . lc-show-package-summary))))
  1794. ;;;; Clojure
  1795. (use-package clojure-mode
  1796. :ensure t
  1797. :config
  1798. (defun jao-clojure--fix-things ()
  1799. (setq-local completion-styles '(basic partial-completion emacs22))
  1800. (eldoc-mode 1)
  1801. (setq mode-name "λ"))
  1802. :hook (clojure-mode . jao-clojure--fix-things))
  1803. (use-package cider
  1804. :ensure t
  1805. :commands cider-mode
  1806. :init (setq cider-annotate-completion-candidates t
  1807. cider-auto-select-error-buffer nil
  1808. cider-auto-select-test-report-buffer nil
  1809. cider-eldoc-display-for-symbol-at-point t
  1810. cider-eldoc-ns-function #'identity ;; #'cider-last-ns-segment
  1811. cider-enrich-classpath nil
  1812. cider-lein-parameters "repl :headless :host localhost"
  1813. cider-mode-line " ÷"
  1814. cider-prompt-for-symbol nil
  1815. cider-repl-history-file
  1816. (expand-file-name "~/.emacs.d/cache/cider.history")
  1817. cider-repl-pop-to-buffer-on-connect nil
  1818. cider-repl-use-pretty-printing t
  1819. cider-show-error-buffer 'except-in-repl
  1820. cider-test-show-report-on-success nil
  1821. cider-use-fringe-indicators nil
  1822. cider-use-overlays nil
  1823. clojure-docstring-fill-column 72
  1824. nrepl-prompt-to-kill-server-buffer-on-quit nil)
  1825. :bind (("<f3>" . cider-selector)))
  1826. (with-eval-after-load "cider-test"
  1827. (advice-add 'cider-scale-background-color :override
  1828. (lambda () (frame-parameter nil 'background-color)))
  1829. (setq cider-test-items-background-color
  1830. (frame-parameter nil 'background-color)))
  1831. (use-package cider-macroexpansion
  1832. :after cider
  1833. :diminish " µ")
  1834. ;;;; Geiser
  1835. (defun jao-org--set-geiser-impl () (setq-local geiser-repl--impl 'guile))
  1836. (add-hook 'org-mode-hook #'jao-org--set-geiser-impl)
  1837. (jao-load-path "geiser")
  1838. (use-package geiser
  1839. :init
  1840. (setq geiser-repl-history-filename "~/.emacs.d/cache/geiser-history"
  1841. geiser-repl-startup-time 20000
  1842. geiser-debug-auto-display-images t
  1843. geiser-log-verbose t)
  1844. :config
  1845. (dolist (m '(geiser-repl-mode geiser-doc-mode geiser-debug-mode))
  1846. (jao-define-attached-buffer `(major-mode . ,m) 0.4)))
  1847. (jao-load-path "geiser-guile")
  1848. (use-package geiser-guile)
  1849. (jao-load-path "geiser-chez")
  1850. (use-package geiser-chez)
  1851. ;; (jao-load-path "geiser/mit")
  1852. ;; (use-package geiser-mit)
  1853. ;; (jao-load-path "geiser/chicken")
  1854. ;; (use-package geiser-chicken)
  1855. ;; (jao-load-path "geiser/chibi")
  1856. ;; (use-package geiser-chibi)
  1857. ;; (jao-load-path "geiser/gambit")
  1858. ;; (use-package geiser-gambit)
  1859. ;; (jao-load-path "geiser/gauche")
  1860. ;; (use-package geiser-gauche)
  1861. ;;;; Haskell
  1862. ;;;;; packages
  1863. ;; (jao-load-path "haskell-mode")
  1864. (use-package haskell-mode
  1865. :ensure t
  1866. :custom
  1867. ((inferior-haskell-find-project-root t)
  1868. (haskell-check-remember-last-command-p nil)
  1869. (haskell-completing-read-function 'completing-read)
  1870. (haskell-font-lock-symbols nil)
  1871. (haskell-hoogle-command "hoogle")
  1872. (haskell-interactive-popup-errors t)
  1873. (haskell-process-auto-import-loaded-modules t)
  1874. (haskell-process-log t)
  1875. (haskell-process-suggest-remove-import-lines t)
  1876. (haskell-process-suggest-hoogle-imports t)
  1877. (haskell-process-type 'cabal-repl)
  1878. (haskell-process-use-presentation-mode t)
  1879. (haskell-stylish-on-save nil)
  1880. (haskell-tags-on-save t))
  1881. :init
  1882. ;; For use with M-x align
  1883. (require 'align)
  1884. (add-to-list 'align-rules-list
  1885. '(haskell-types
  1886. (regexp . "\\(\\s-+\\)\\(::\\|∷\\)\\s-+")
  1887. (modes quote (haskell-mode haskell-literate-mode))))
  1888. (add-to-list 'align-rules-list
  1889. '(haskell-assignment
  1890. (regexp . "\\(\\s-+\\)=\\s-+")
  1891. (modes quote (haskell-mode haskell-literate-mode))))
  1892. (add-to-list 'align-rules-list
  1893. '(haskell-arrows
  1894. (regexp . "\\(\\s-+\\)\\(->\\|→\\)\\s-+")
  1895. (modes quote (haskell-mode haskell-literate-mode))))
  1896. (add-to-list 'align-rules-list
  1897. '(haskell-left-arrows
  1898. (regexp . "\\(\\s-+\\)\\(<-\\|←\\)\\s-+")
  1899. (modes quote (haskell-mode haskell-literate-mode))))
  1900. :config
  1901. (defun jao-haskell-hoogle (no-info)
  1902. (interactive "P")
  1903. (haskell-hoogle (format "%s" (haskell-ident-at-point)) (not no-info)))
  1904. (put 'haskell-process-args-cabal-repl
  1905. 'safe-local-variable
  1906. (apply-partially #'seq-every-p #'stringp))
  1907. (defun jao-haskell-eldoc (cb)
  1908. (let ((msg (or (haskell-doc-current-info--interaction t)
  1909. (haskell-doc-sym-doc (haskell-ident-at-point))
  1910. "")))
  1911. (funcall cb (replace-regexp-in-string "[\n ]+" " " msg))))
  1912. (setq tags-revert-without-query t)
  1913. (defun jao-haskell-mode ()
  1914. (require 'haskell-doc)
  1915. (setq-local eldoc-documentation-function 'eldoc-documentation-default
  1916. eldoc-documentation-functions '(jao-haskell-eldoc))
  1917. (eldoc-mode))
  1918. (dolist (h '(jao-haskell-mode
  1919. haskell-decl-scan-mode
  1920. haskell-indentation-mode
  1921. interactive-haskell-mode))
  1922. (add-hook 'haskell-mode-hook h))
  1923. (add-hook 'haskell-presentation-mode-hook (lambda () (whitespace-mode -1)))
  1924. :bind (:map haskell-mode-map
  1925. (("C-c C-d" . jao-haskell-hoogle)
  1926. ("C-c C-s" . haskell-session-change-target)
  1927. ("C-c h" . haskell-hoogle)
  1928. ("C-c t" . haskell-doc-show-type)
  1929. ("C-c C-e" . haskell-command-insert-language-pragma)
  1930. ("C-M-n" . flymake-goto-next-error)
  1931. ("C-M-p" . flymake-goto-prev-error)
  1932. ("<f3>" . haskell-session-kill))))
  1933. (use-package hlint-refactor
  1934. :ensure t
  1935. :after haskell-mode
  1936. :hook ((haskell-mode . hlint-refactor-mode))
  1937. :bind (:map haskell-mode-map (("C-M-h" . 'hlint-refactor-refactor-at-point)
  1938. ("C-M-S-h" . 'hlint-refactor-refactor-buffer)))
  1939. :diminish)
  1940. (use-package flymake-hlint
  1941. :ensure t
  1942. :after haskell-mode
  1943. :hook ((haskell-mode . flymake-hlint-load)))
  1944. (use-package consult-hoogle
  1945. :ensure t)
  1946. (require 'haskell)
  1947. (diminish 'interactive-haskell-mode " λ")
  1948. (diminish 'haskell-doc-mode)
  1949. (diminish 'haskell-decl-scan-mode)
  1950. (jao-define-attached-buffer "\\*hoogle\\*.*")
  1951. (jao-define-attached-buffer '(major-mode . haskell-interactive-mode) 0.33)
  1952. (jao-define-attached-buffer '(major-mode . haskell-presentation-mode) 0.25)
  1953. ;;;;; transient
  1954. (jao-transient-major-mode haskell
  1955. ["Imports"
  1956. ("in" "Navigate imports" haskell-navigate-imports)
  1957. ("if" "Format imports" haskell-mode-format-imports)
  1958. ("is" "Sort imports" haskell-sort-imports)
  1959. ("ia" "Align imports" haskell-align-imports)]
  1960. ["Session"
  1961. ("s" "Change the session's target" haskell-session-change-target)]
  1962. ["Code"
  1963. ("e" "insert language pragma" haskell-command-insert-language-pragma)
  1964. ("v" "visit cabal file" haskell-cabal-visit-file)
  1965. ("h" "hoogle" jao-haskell-hoogle)
  1966. ("t" "show type" haskell-doc-show-type)]
  1967. ["Flymake"
  1968. ("n" "next error" flymake-goto-next-error)
  1969. ("p" "previous error" flymake-goto-prev-error)])
  1970. ;;;; Pie
  1971. (jao-load-path "pie")
  1972. (use-package pie
  1973. :demand t
  1974. :commands (pie-mode))
  1975. ;;;; Prolog
  1976. ;; (use-package ediprolog :ensure t)
  1977. (use-package prolog
  1978. :ensure t
  1979. :commands (run-prolog prolog-mode mercury-mode)
  1980. :init (progn
  1981. (setq prolog-system 'swi)
  1982. (add-to-list 'auto-mode-alist '("\\.pl$" . prolog-mode))
  1983. (setq prolog-consult-string '((t "[%f].")))
  1984. (setq prolog-program-name
  1985. '(((getenv "EPROLOG") (eval (getenv "EPROLOG")))
  1986. (eclipse "eclipse")
  1987. (mercury nil)
  1988. (sicstus "sicstus")
  1989. (swi "swipl")
  1990. (t "prolog")))))
  1991. ;;;; Python
  1992. (use-package virtualenvwrapper
  1993. :ensure t
  1994. :config
  1995. (venv-initialize-eshell)
  1996. (jao-compilation-env "VIRTUAL_ENV"))
  1997. ;;; Text/data formats
  1998. ;;;; json
  1999. (use-package json-mode :ensure t)
  2000. ;;;; yaml
  2001. (use-package yaml-mode :disabled t :ensure t)
  2002. ;;; Graphics
  2003. ;;;; images
  2004. (setq image-use-external-converter t
  2005. image-cache-eviction-delay 120)
  2006. (setq widget-image-enable nil)
  2007. ;;;; gnuplot
  2008. (use-package gnuplot
  2009. :disabled t
  2010. :ensure t
  2011. :commands (gnuplot-mode gnuplot-make-buffer)
  2012. :init (add-to-list 'auto-mode-alist '("\\.gp$" . gnuplot-mode)))
  2013. ;;; Network
  2014. ;;;; nm applet
  2015. (jao-shell-def-exec jao-nm-applet "nm-applet")
  2016. (defun jao-toggle-nm-applet ()
  2017. (interactive)
  2018. (or (jao-shell-kill-p "nm-applet") (jao-nm-applet)))
  2019. ;;;; bluetooth
  2020. (use-package bluetooth :ensure t)
  2021. ;;;; vpn
  2022. (use-package jao-mullvad :demand t)
  2023. ;;;; ssh
  2024. (use-package tramp)
  2025. (defun jao-tramp-hosts ()
  2026. (seq-uniq
  2027. (mapcan (lambda (x)
  2028. (remove nil (mapcar 'cadr (apply (car x) (cdr x)))))
  2029. (tramp-get-completion-function "ssh"))
  2030. #'string=))
  2031. (defun jao-ssh (&optional scratch)
  2032. (interactive "P")
  2033. (let ((h (completing-read "Host: " (jao-tramp-hosts))))
  2034. (when scratch (jao-afio-goto-scratch))
  2035. (jao-exec-in-term (format "ssh %s" h) (format "*ssh %s*" h))))
  2036. ;;; Chats
  2037. ;;;; circe
  2038. (defvar jao-libera-channels ())
  2039. (defvar jao-oftc-channels ())
  2040. (defvar jao-bitlbee-channels ())
  2041. (defvar jao-slack-channels ())
  2042. (use-package circe
  2043. :ensure t
  2044. :bind (:map circe-channel-mode-map
  2045. (("C-c C-a" . lui-track-jump-to-indicator)))
  2046. :init
  2047. (setq circe-chat-buffer-name "{target}"
  2048. circe-default-realname "https://jao.io"
  2049. circe-default-part-message ""
  2050. circe-default-quit-message ""
  2051. circe-ignore-list nil
  2052. circe-server-coding-system '(undecided . undecided)
  2053. circe-server-killed-confirmation 'ask-and-kill-all
  2054. circe-server-auto-join-default-type :after-auth
  2055. circe-format-say "({nick}) {body}"
  2056. circe-format-self-say "(jao) {body}"
  2057. circe-new-buffer-behavior 'ignore
  2058. circe-new-buffer-behavior-ignore-auto-joins t
  2059. circe-nickserv-ghost-style 'after-auth
  2060. circe-prompt-string ": "
  2061. circe-completion-suffix ", "
  2062. circe-reduce-lurker-spam t
  2063. circe-lagmon-mode-line-format-string "" ;; "%.0f "
  2064. circe-lagmon-mode-line-unknown-lag-string "" ;; "? "
  2065. circe-lagmon-timer-tick 120
  2066. circe-lagmon-reconnect-interval 180
  2067. lui-max-buffer-size 30000
  2068. lui-fill-column 80
  2069. lui-time-stamp-position 'right
  2070. lui-time-stamp-format "%H:%M"
  2071. lui-flyspell-p nil
  2072. lui-track-indicator (if window-system 'fringe 'bar)
  2073. lui-track-behavior 'before-tracking-next-buffer)
  2074. :config
  2075. (defsubst jao-circe-nick-no () (length (circe-channel-nicks)))
  2076. (define-minor-mode jao-circe-user-number-mode ""
  2077. :lighter (:eval (format " [%s]" (jao-circe-nick-no))))
  2078. (defun jao-circe-channel-hook ()
  2079. (when jao-mode-line-in-minibuffer
  2080. (setq header-line-format
  2081. '(" %b" (:eval (format " - %s nicks" (jao-circe-nick-no))))))
  2082. (jao-circe-user-number-mode 1))
  2083. (add-hook 'circe-channel-mode-hook #'jao-circe-channel-hook)
  2084. (defun circe-command-RECOVER (&rest _ignore)
  2085. "Recover nick"
  2086. (jao-with-auth "freenode" u p
  2087. (circe-command-MSG "nickserv" (format "IDENTIFY %s %s" u p))
  2088. (circe-command-MSG "nickserv" (format "GHOST %s" u))
  2089. (circe-command-MSG "nickserv" (format "RELEASE %s" u))
  2090. (circe-command-NICK u)))
  2091. (defun circe-command-NNICKS (&rest _)
  2092. "Echo number of nicks"
  2093. (circe-display-server-message
  2094. (format "%d nicks in this channel" (jao-circe-nick-no))))
  2095. (defun circe-command-SENDFILE (line)
  2096. "/sendfile for localslackirc"
  2097. (circe-command-QUOTE (format "sendfile %s" line)))
  2098. (advice-add 'circe-command-NAMES :after #'circe-command-NNICKS)
  2099. (setq circe-network-options
  2100. (list (jao-with-auth "libera" u p
  2101. (list "Libera Chat" :nick u :channels jao-libera-channels
  2102. :tls t :sasl-username u :sasl-password p))
  2103. (jao-with-auth "oftc" u p
  2104. (list "OFTC"
  2105. :nick u :channels jao-oftc-channels :nickserv-password p
  2106. :tls t :sasl-username u :sasl-password p))
  2107. (jao-with-auth "bitlbee" u p
  2108. (list "Bitlbee" :host "127.0.0.1" :nick u
  2109. :channels jao-bitlbee-channels :lagmon-disabled t
  2110. :nickserv-password u :user p))
  2111. (list "localslack" :host "127.0.0.1" :nick "jao"
  2112. :channels jao-slack-channels :port 9007
  2113. :lagmon-disabled t)
  2114. (list "recoveryou" :host "127.0.0.1" :nick "jao"
  2115. :port 9008 :lagmon-disabled t)))
  2116. (jao-shorten-modes 'circe-channel-mode
  2117. 'circe-server-mode
  2118. 'circe-query-mode)
  2119. (enable-circe-display-images)
  2120. (enable-lui-track)
  2121. (circe-lagmon-mode))
  2122. ;;;; telegram
  2123. (use-package telega
  2124. :ensure t
  2125. :custom
  2126. (telega-use-tracking-for '(unmuted) ;; '(or unmuted mention)
  2127. telega-rainbow-color-custom-for nil
  2128. telega-msg-rainbow-title nil
  2129. telega-sticker-set-download t
  2130. telega-symbol-checkmark "·"
  2131. telega-symbol-heavy-checkmark "×"
  2132. telega-symbol-verified "*")
  2133. :config
  2134. (define-key global-map (kbd "C-c C-t") telega-prefix-map)
  2135. (setq telega-chat-show-avatars nil
  2136. telega-chat-prompt-insexp '(telega-ins "> ")
  2137. telega-completing-read-function #'completing-read
  2138. telega-root-show-avatars nil
  2139. telega-emoji-use-images nil
  2140. telega-temp-dir "/tmp/telega"
  2141. telega-symbol-horizontal-bar
  2142. (propertize "-" 'face 'jao-themes-f00)
  2143. telega-symbol-vertical-bar
  2144. (propertize "| " 'face 'jao-themes-dimm)
  2145. telega-mode-line-string-format
  2146. '(:eval (telega-mode-line-unread-unmuted))
  2147. telega-use-images (display-graphic-p)
  2148. telega-open-file-function #'jao--see
  2149. telega-open-message-as-file
  2150. (unless (display-graphic-p) '(photo video animation)))
  2151. (with-eval-after-load "tracking"
  2152. (jao-shorten-modes 'telega-chat-mode)
  2153. (jao-tracking-faces 'telega-tracking))
  2154. (telega-mode-line-mode 1))
  2155. (defun jao-telega ()
  2156. (interactive)
  2157. (jao-tracking-go-to-chats)
  2158. (if (get-buffer telega-root-buffer-name)
  2159. (pop-to-buffer telega-root-buffer-name)
  2160. (telega)))
  2161. ;;;; ement
  2162. (use-package ement
  2163. :disabled t
  2164. :ensure t
  2165. :init (setq ement-save-sessions t
  2166. ement-sessions-file (locate-user-emacs-file "cache/ement.el")
  2167. ement-room-avatars nil
  2168. ement-notify-dbus-p nil
  2169. ement-room-left-margin-width 0
  2170. ement-room-right-margin-width 11
  2171. ement-room-timestamp-format "%H:%M"
  2172. ement-room-timestamp-header-format "­­--------")
  2173. :custom ((ement-room-message-format-spec "(%S) %B%r%R %t"))
  2174. :config
  2175. (defun jao-ement-track (event room session)
  2176. (when (ement-notify--room-unread-p event room session)
  2177. (when-let ((n (ement-room--buffer-name room))
  2178. (b (get-buffer n)))
  2179. (tracking-add-buffer b))))
  2180. (add-hook 'ement-event-hook #'jao-ement-track)
  2181. (jao-shorten-modes 'ement-room-mode)
  2182. (jao-tracking-cleaner "^\\*Ement Room: \\(.+\\)\\*" "@\\1"))
  2183. ;;;; mastodon
  2184. (use-package mastodon
  2185. :ensure t
  2186. :init
  2187. (setq mastodon-instance-url "https://fosstodon.org"
  2188. mastodon-active-user "jao@gnu.org"
  2189. mastodon-tl-position-after-update nil
  2190. mastodon-toot-display-orig-in-reply-buffer t)
  2191. :config
  2192. ;; (defun jao-mastodon--setup ()
  2193. ;; (setq-local scroll-margin 12))
  2194. ;; (add-hook 'mastodon-mode-hook #'jao-mastodon--setup)
  2195. (with-eval-after-load "ewww"
  2196. (define-key eww-mode-map (kbd "T") #'jao-mastodon-toot-url)))
  2197. (defun jao-mastodon-toot-url ()
  2198. (interactive)
  2199. (when-let (url (jao-url-around-point t))
  2200. (jao-tracking-go-to-chats)
  2201. (mastodon-toot--compose-buffer nil nil nil url)))
  2202. (defun jao-mastodon ()
  2203. (interactive)
  2204. (jao-afio-goto-chats)
  2205. (mastodon))
  2206. ;; https://0x0.st/XJ14.txt
  2207. (jao-transient-major-mode mastodon
  2208. ["Timelines"
  2209. ("H" "home" mastodon-tl--get-home-timeline)
  2210. ("L" "local" mastodon-tl--get-local-timeline)
  2211. ("F" "federated" mastodon-tl--get-federated-timeline)
  2212. ("K" "bookmarks" mastodon-profile--view-bookmarks)
  2213. ("V" "favorites" mastodon-profile--view-favourites)
  2214. ("'" "followed tags" mastodon-tl--followed-tags-timeline)
  2215. ("@" "mentions" mastodon-notifications--get-mentions)
  2216. ("N" "notifications" mastodon-notifications-get)
  2217. ("\\" "of remote host" mastodon-tl--get-remote-local-timeline)]
  2218. ;; u mastodon-tl--update
  2219. ["Search"
  2220. ("s" "search" mastodon-search--query)
  2221. ("#" "tagged" mastodon-tl--get-tag-timeline)
  2222. ("\"" "followed tags" mastodon-tl--list-followed-tags)
  2223. ("I" "filter" mastodon-views--view-filters)
  2224. ("X" "lists" mastodon-views--view-lists)]
  2225. ["Toots"
  2226. ("n" "next" mastodon-tl--goto-next-item :transient t)
  2227. ("p" "prev" mastodon-tl--goto-prev-item :transient t)
  2228. ("c" "spoiler" mastodon-tl--toggle-spoiler-text-in-toot :transient t)
  2229. ("T" "thread" mastodon-tl--thread)
  2230. ("b" "(un)boost" mastodon-toot--toggle-boost :transient t)
  2231. ("f" "(un)fav" mastodon-toot--toggle-favourite :transient t)
  2232. ("i" "(un)pin" mastodon-toot--pin-toot-toggle :transient t)
  2233. ("k" "(un)bookmark" mastodon-toot--toggle-bookmark :transient t)
  2234. ("v" "vote" mastodon-tl--poll-vote)]
  2235. ;; Z mastodon-tl--report-to-mods
  2236. ;; o mastodon-toot--open-toot-url
  2237. ["Own Toots"
  2238. ("r" "replay" mastodon-toot--reply)
  2239. ("t" "write" mastodon-toot)
  2240. ("e" "edit" mastodon-toot--edit-toot-at-point)
  2241. ("d" "delete" mastodon-toot--delete-toot)
  2242. ("D" "del & redraft" mastodon-toot--delete-and-redraft-toot)
  2243. ("E" "show edits" mastodon-toot--view-toot-edits)]
  2244. ;; S mastodon-views--view-scheduled-toots
  2245. ["Users"
  2246. ("W" "follow" mastodon-tl--follow-user)
  2247. ("R" "follow req" mastodon-views--view-follow-requests)
  2248. ("G" "suggestions" mastodon-views--view-follow-suggestions)
  2249. ("M" "mute user" mastodon-tl--mute-user)
  2250. ("B" "block user" mastodon-tl--block-user)
  2251. ("m" "message user" mastodon-tl--dm-user)
  2252. ""
  2253. ("," "favouriters" mastodon-toot--list-toot-favouriters)
  2254. ("." "boosters" mastodon-toot--list-toot-boosters)]
  2255. ;; S-RET mastodon-tl--unmute-user
  2256. ;; C-S-b mastodon-tl--unblock-user
  2257. ["Profiles"
  2258. ("A" "author" mastodon-profile--get-toot-author)
  2259. ("P" "any user" mastodon-profile--show-user)
  2260. ("O" "own" mastodon-profile--my-profile)
  2261. ("U" "update own" mastodon-profile--update-user-profile-note)]
  2262. ["Misc"
  2263. ("C" "copy URL" mastodon-toot--copy-toot-url)
  2264. ("?" "help" describe-mode)
  2265. ("q" "quit" transient-quit-one)])
  2266. ;;;; startup
  2267. (defun jao-chats (&optional p)
  2268. (interactive "P")
  2269. (when (or p (y-or-n-p "Connect to telegram? "))
  2270. (telega))
  2271. (when (and (fboundp 'ement-connect) (or p (y-or-n-p "Connect to matrix? ")))
  2272. (unless (get-buffer "*Ement Rooms*")
  2273. (jao-with-auth "matrix.org" u p (ement-connect :user-id u :password p))))
  2274. (when (and (fboundp 'mastodon) (or p (y-or-n-p "Connect to mastodon? ")))
  2275. (mastodon))
  2276. (when (or p (y-or-n-p "Connect to libera? "))
  2277. (unless (get-buffer "irc.libera.chat:6697")
  2278. (circe "Libera Chat")))
  2279. (when (or p (y-or-n-p "Connect to localslack? "))
  2280. (unless (get-buffer "127.0.0.1:9007")
  2281. (circe "localslack")))
  2282. (when (or p (y-or-n-p "Connect to recoveryou? "))
  2283. (unless (get-buffer "127.0.0.1:9008")
  2284. (circe "recoveryou"))))
  2285. (defun jao-all-chats ()
  2286. (interactive)
  2287. (when jao-tracking-use-scratch
  2288. (jao-afio-goto-chats)
  2289. (delete-other-windows))
  2290. (jao-chats t))
  2291. (defun jao-chats-telega ()
  2292. (interactive)
  2293. (jao-buffer-same-mode '(telega-root-mode telega-chat-mode)))
  2294. (defun jao-chats-slack ()
  2295. (interactive)
  2296. (jao-buffer-same-mode 'slack-message-buffer-mode))
  2297. (defun jao-chats-irc ()
  2298. (interactive)
  2299. (jao-buffer-same-mode '(circe-channel-mode circe-query-mode erc-mode)))
  2300. ;;;; consult narrowing
  2301. (defvar jao-chat-buffer-source
  2302. (list :name "chats"
  2303. :category 'buffer
  2304. :action (lambda (b) (jao-afio-pop-to-buffer 0 b))
  2305. :hidden t
  2306. :narrow (cons ?c "chats")
  2307. :items (jao-consult--mode-buffers 'erc-mode
  2308. 'circe-channel-mode
  2309. 'circe-query-mode
  2310. 'signel-chat-mode
  2311. 'slack-message-buffer-mode
  2312. 'slack-thread-message-buffer-mode
  2313. 'telega-root-mode
  2314. 'telega-chat-mode
  2315. 'ement-room-mode
  2316. 'ement-room-list-mode)))
  2317. (with-eval-after-load "consult"
  2318. (jao-consult-add-buffer-source 'jao-chat-buffer-source))
  2319. ;;; Multimedia
  2320. ;;;; video
  2321. (use-package ready-player :ensure t)
  2322. (ready-player-mode 1)
  2323. ;;;; mixer
  2324. (defun jao-mixer-get-level (&optional dev nomsg)
  2325. (interactive)
  2326. (let* ((dev (or dev "Master"))
  2327. (s (shell-command-to-string (format "amixer sget %s" dev)))
  2328. (s (car (last (split-string s "\n" t)))))
  2329. (when (string-match ".*Front .*\\[\\([0-9]+\\)%\\] .*" s)
  2330. (let ((level (match-string 1 s)))
  2331. (unless nomsg (message "%s level: %s%%" dev level))
  2332. (string-to-number level)))))
  2333. (defun jao-mixer-set (dev v)
  2334. (jao-shell-exec* t "amixer" "sset" dev v)
  2335. (jao-mixer-get-level dev))
  2336. (defun jao-mixer-master-toggle ()
  2337. (interactive)
  2338. (jao-mixer-set "Master" "toggle"))
  2339. (defun jao-mixer-master-up ()
  2340. (interactive)
  2341. (jao-mixer-set "Master" "10%+"))
  2342. (defun jao-mixer-master-down ()
  2343. (interactive)
  2344. (jao-mixer-set "Master" "10%-"))
  2345. (defun jao-mixer-capture-up ()
  2346. (interactive)
  2347. (jao-mixer-set "Capture" "10%+"))
  2348. (defun jao-mixer-capture-down ()
  2349. (interactive)
  2350. (jao-mixer-set "Capture" "10%-"))
  2351. (jao-shell-def-exec jao-audio-applet "pasystray")
  2352. (defun jao-toggle-audio-applet ()
  2353. (interactive)
  2354. (or (jao-shell-kill-p "paystray") (jao-audio-applet)))
  2355. (global-set-key (kbd "<f4>") #'jao-toggle-audio-applet)
  2356. ;;;; streaming aliases
  2357. (defalias 'jao-streaming-list #'ignore)
  2358. (defalias 'jao-streaming-like #'ignore)
  2359. (defalias 'jao-streaming-dislike #'ignore)
  2360. (defalias 'jao-streaming-toggle-shuffle #'ignore)
  2361. (defalias 'jao-streaming-lyrics #'ignore)
  2362. (defalias 'jao-streaming-toggle #'ignore)
  2363. (defalias 'jao-streaming-next #'ignore)
  2364. (defalias 'jao-streaming-prev #'ignore)
  2365. (defalias 'jao-streaming-current #'ignore)
  2366. (defalias 'jao-streaming-seek #'ignore)
  2367. (defalias 'jao-streaming-seek-back #'ignore)
  2368. (defalias 'jao-streaming-volume #'ignore)
  2369. (defalias 'jao-streaming-volume-down #'ignore)
  2370. ;;;; mpris
  2371. (defun jao-mpris-lyrics (&optional force)
  2372. (interactive "P")
  2373. (jao-show-lyrics force #'jao-mpris-artist-title))
  2374. (defun jao-mpris-mopidy-p () (string= "mopidy "jao-mpris-player))
  2375. (defun jao-mpc-mopidy-playlist ()
  2376. (interactive)
  2377. (jao-mpc-show-playlist jao-mopidy-port))
  2378. (use-package jao-mpris :demand t)
  2379. (defun jao-mpris-setup-aliases ()
  2380. (setq espotify-play-uri-function #'espotify-play-uri-with-dbus)
  2381. ;; (setq jao-mpris-player "mopidy")
  2382. (defalias 'jao-streaming-list #'jao-mpc-mopidy-playlist)
  2383. (defalias 'jao-streaming-lyrics #'jao-mpris-lyrics)
  2384. (defalias 'jao-streaming-toggle #'jao-mpris-play-pause)
  2385. (defalias 'jao-streaming-next #'jao-mpris-next)
  2386. (defalias 'jao-streaming-prev #'jao-mpris-previous)
  2387. (defalias 'jao-streaming-current #'jao-mpris-show-osd)
  2388. (defalias 'jao-streaming-seek #'jao-mpris-seek)
  2389. (defalias 'jao-streaming-seek-back #'jao-mpris-seek-back)
  2390. (defalias 'jao-streaming-volume #'jao-mpris-vol)
  2391. (defalias 'jao-streaming-volume-down #'jao-mpris-vol-down))
  2392. (jao-mpris-register "playerctld" :session 70)
  2393. ;; (jao-mpris-register "mopidy" :session 70)
  2394. ;;;; mpc
  2395. (use-package jao-mpc
  2396. :demand t
  2397. :commands jao-mpc-setup)
  2398. (defvar jao-mopidy-port 6669)
  2399. (defvar jao-mpc-last-port jao-mpc-port)
  2400. (defun jao-mpc-toggle-port ()
  2401. (interactive)
  2402. (setq jao-mpc-port
  2403. (if (equal jao-mpc-port jao-mopidy-port) 6600 jao-mopidy-port)
  2404. jao-mpc-last-port jao-mpc-port))
  2405. (defsubst jao-mpc-mopidy-p () (equal jao-mpc-last-port jao-mopidy-port))
  2406. (jao-mpc-setup jao-mopidy-port 70)
  2407. (defun jao-mpc-pport (&optional mop)
  2408. (cond ((or mop (jao-mpc-playing-p jao-mopidy-port)) jao-mopidy-port)
  2409. ((jao-mpc-playing-p) 6600)
  2410. (t jao-mpc-last-port)))
  2411. (defmacro jao-defun-play (name &optional mpc-name)
  2412. (let ((arg (gensym)))
  2413. `(defun ,(intern (format "jao-player-%s" name)) (&optional ,arg)
  2414. (interactive "P")
  2415. (,(intern (format "jao-mpc-%s" (or mpc-name name)))
  2416. (setq jao-mpc-last-port (jao-mpc-pport ,arg))))))
  2417. (jao-defun-play toggle)
  2418. (jao-defun-play next)
  2419. (jao-defun-play previous)
  2420. (jao-defun-play stop)
  2421. (jao-defun-play echo echo-current-times)
  2422. (jao-defun-play list show-playlist)
  2423. (jao-defun-play info lyrics-track-data)
  2424. (jao-defun-play browse show-albums)
  2425. (jao-defun-play select-album)
  2426. (defun jao-player-seek (delta) (jao-mpc-seek delta (jao-mpc-pport)))
  2427. (defalias 'jao-player-connect 'jao-mpc-connect)
  2428. (defalias 'jao-player-play 'jao-mpc-play)
  2429. ;;;; spotify
  2430. (jao-load-path "espotify")
  2431. (use-package espotify
  2432. :demand t
  2433. :init (setq espotify-service-name "mopidy"))
  2434. (use-package consult-spotify :demand t)
  2435. (defalias 'jao-streaming-album #'consult-spotify-album)
  2436. (defalias 'jao-streaming-track #'consult-spotify-track)
  2437. (defalias 'jao-streaming-artist #'consult-spotify-artist)
  2438. (defalias 'jao-streaming-playlist #'consult-spotify-playlist)
  2439. (jao-def-exec-in-term "ncmpcpp" "ncmpcpp" (jao-afio-goto-scratch))
  2440. ;;;; spt
  2441. (use-package jao-spt
  2442. :demand t
  2443. :config
  2444. (defun jao-spt-setup-aliases ()
  2445. (setq espotify-play-uri-function #'jao-spt-play-uri)
  2446. (defalias 'jao-streaming-list #'jao-term-spt)
  2447. (defalias 'jao-streaming-lyrics #'jao-spt-show-lyrics)
  2448. (defalias 'jao-streaming-toggle #'jao-spt-toggle)
  2449. (defalias 'jao-streaming-next #'jao-spt-next)
  2450. (defalias 'jao-streaming-prev #'jao-spt-previous)
  2451. (defalias 'jao-streaming-current #'jao-spt-echo-current)
  2452. (defalias 'jao-streaming-seek #'jao-spt-seek)
  2453. (defalias 'jao-streaming-seek-back #'jao-spt-seek-back)
  2454. (defalias 'jao-streaming-volume #'jao-spt-vol)
  2455. (defalias 'jao-streaming-volume-down #'jao-spt-vol-down)
  2456. (defalias 'jao-streaming-like #'jao-spt-like)
  2457. (defalias 'jao-streaming-dislike #'jao-spt-dislike)
  2458. (defalias 'jao-streaming-toggle-shuffle #'jao-spt-toggle-shuffle)))
  2459. (jao-def-exec-in-term "spt" "spt" (jao-afio-goto-scratch))
  2460. (defvar jao-spt-on t)
  2461. (defun jao-streaming-toggle-player ()
  2462. (interactive)
  2463. (if jao-spt-on
  2464. (progn (setq jao-mpris-player "playerctld")
  2465. (require 'jao-mpris)
  2466. (jao-mpris-setup-aliases))
  2467. (jao-spt-setup-aliases)
  2468. (setq jao-mpris-player "spt"))
  2469. (setq jao-spt-on (not jao-spt-on))
  2470. (message "%s activated " jao-mpris-player))
  2471. (jao-streaming-toggle-player)
  2472. ;;;; music transients
  2473. (require 'jao-lyrics)
  2474. (setq jao-lyrics-info-function #'jao-player-info)
  2475. (defun jao-player-seek-10 () (interactive) (jao-player-seek 10))
  2476. (defun jao-player-seek--10 () (interactive) (jao-player-seek -10))
  2477. (defun jao-streaming-clear () (interactive) (jao-mpc-clear jao-mopidy-port))
  2478. (defun jao-streaming-echo-current ()
  2479. (interactive)
  2480. (jao-mpc-echo-current jao-mopidy-port))
  2481. (defun jao-streaming-show-playlist ()
  2482. (interactive)
  2483. (jao-mpc-show-playlist jao-mopidy-port))
  2484. (use-package jao-random-album
  2485. :demand t
  2486. :config
  2487. (defun jao--notify-album (album)
  2488. (jao-notify album "Next album" jao-notify-audio-icon)
  2489. (jao-minibuffer-refresh))
  2490. (setq jao-random-album-notify #'jao--notify-album))
  2491. (defun jao-toggle-pasystray-applet ()
  2492. (interactive)
  2493. (or (jao-shell-kill-p "pasystray") (jao-shell-exec "pasystray")))
  2494. (transient-define-prefix jao-transient-streaming ()
  2495. [:description
  2496. (lambda () (format "Streaming using %s" jao-mpris-player))
  2497. ["Search" :if jao-mpris-mopidy-p
  2498. ("a" "album" jao-streaming-album)
  2499. ("A" "artist" jao-streaming-artist)
  2500. ("t" "track" jao-streaming-track)
  2501. ("P" "playlist" jao-streaming-playlist)]
  2502. ["Play"
  2503. ("s" "toggle" jao-streaming-toggle)
  2504. ("n" "next" jao-streaming-next)
  2505. ("p" "previous" jao-streaming-prev)
  2506. ("T" "toggle player" jao-streaming-toggle-player)]
  2507. ["Seek & shout"
  2508. ("f" "seek fwd" jao-streaming-seek :transient t)
  2509. ("F" "seek bwd" jao-streaming-seek-back :transient t)
  2510. ("u" "up" jao-streaming-volume :transient t)
  2511. ("d" "down" jao-streaming-volume-down :transient t)]
  2512. ["Browse"
  2513. ("l" "playing list" jao-streaming-list :if jao-mpris-mopidy-p)
  2514. ("L" "lyrics" jao-streaming-lyrics)
  2515. ("w" "currently playing" jao-streaming-current)]
  2516. ["Act" :if jao-mpris-mopidy-p
  2517. ("k" "like" jao-streaming-like)
  2518. ("K" "dislike" jao-streaming-dislike)
  2519. ("S" "toggle shuffle" jao-streaming-toggle-shuffle)]])
  2520. (transient-define-prefix jao-transient-media ()
  2521. [["Play"
  2522. ("m" "toggle" jao-player-toggle)
  2523. ("n" "next" jao-player-next)
  2524. ("p" "previous" jao-player-previous)
  2525. ("s" "select album" jao-player-select-album)]
  2526. ["Seek and search"
  2527. ("f" "seek fwd" jao-player-seek-10 :transient t)
  2528. ("F" "seek bwd" jao-player-seek--10 :transient t)
  2529. ("a" "search album" jao-mpc-select-album)
  2530. ("S" "play stream" jao-mpc-play-stream)]
  2531. ["Browse"
  2532. ("b" "browse" jao-player-browse)
  2533. ("l" "show play list" jao-player-list)
  2534. ("L" "show lyrics" jao-show-lyrics)
  2535. ("w" "now playing" jao-player-echo)]
  2536. [:description
  2537. (lambda ()
  2538. (message "%s %s"
  2539. (if (jao-mpc-mopidy-p) "mopidy" "mpd")
  2540. (if (jao-mpc-playing-p)
  2541. (jao-mpc--current-timestr t)
  2542. (jao-mpc--current-str)))
  2543. (format "Master %s%%" (jao-mixer-get-level nil t)))
  2544. ("d" "down" jao-mixer-master-down :transient t)
  2545. ("u" "up" jao-mixer-master-up :transient t)
  2546. ("M" "toggle" jao-mixer-master-toggle)]
  2547. [:description
  2548. (lambda () (format "Capture %s%%" (jao-mixer-get-level "Capture" t)))
  2549. ("D" "down" jao-mixer-capture-down :transient t)
  2550. ("U" "up" jao-mixer-capture-up :transient t)]
  2551. ["Utilities"
  2552. ("c" "reconnect to mpd" jao-player-connect)
  2553. ("N" "next random album" jao-random-album-next)
  2554. ("r" (lambda ()
  2555. (concat (if jao-random-album-active "dis" "en") "able random album"))
  2556. jao-random-album-toggle)
  2557. ;; ("P" (lambda () (concat "Toggle to " (if (jao-mpc-mopidy-p) "mpd" "mopidy")))
  2558. ;; jao-mpc-toggle-port)
  2559. ("P" "pasystray" jao-toggle-pasystray-applet)]])
  2560. (global-set-key (kbd "s-m") #'jao-transient-media)
  2561. ;;; Graphical window system
  2562. ;;;; x11 utils
  2563. (defun jao-xdotool (arg-or-wait &rest args)
  2564. (apply 'jao-shell-exec*
  2565. (if (stringp arg-or-wait) "xdotool" arg-or-wait)
  2566. (if (stringp arg-or-wait) arg-or-wait "xdotool")
  2567. args))
  2568. (defsubst jao-xdotool-string (&rest args)
  2569. (apply 'jao-shell-string "xdotool" args))
  2570. (defsubst jao-x11-focused-id () (jao-xdotool-string "getwindowfocus"))
  2571. (defsubst jao-x11-window-name (&optional wid)
  2572. (jao-xdotool-string "getwindowname" (or wid (jao-x11-focused-id))))
  2573. (defsubst jao-x11-search-window (title)
  2574. (jao-xdotool-string "search" "--name" title))
  2575. (defsubst jao-x11-goto-ws (n) (jao-xdotool t "set_desktop" (format "%s" n)))
  2576. ;;;; exwm
  2577. (defvar jao-exwm-enabled nil)
  2578. (defun jao-exwm-enabled-p () jao-exwm-enabled)
  2579. (defun jao-exwm-enable ()
  2580. (require 'jao-custom-exwm)
  2581. (setq jao-exwm-enabled t)
  2582. (display-time-mode -1)
  2583. (jao-ednc-setup 95)
  2584. (exwm-enable)
  2585. (x-change-window-property "_XMONAD_TRAYPAD" "" nil nil nil nil 0)
  2586. (jao-mode-line-add-to-minibuffer-left 90)
  2587. (jao-xmobar-restart)
  2588. (jao-trisect t))
  2589. ;;;; xmonad
  2590. (defvar jao-xmonad-enabled (string= "xmonad" (or (getenv "wm") "")))
  2591. (defun jao-xmonad-enabled-p () jao-xmonad-enabled)
  2592. (defun jao-xmonad-enable ()
  2593. (setq jao-browse-doc-use-emacs-p (display-graphic-p))
  2594. (setq jao-mode-line-in-minibuffer nil)
  2595. (display-battery-mode -1)
  2596. (jao-trisect)
  2597. (message "Welcome to xmonad"))
  2598. (when jao-xmonad-enabled
  2599. (add-hook 'after-init-hook #'jao-xmonad-enable))
  2600. ;;;; wayland
  2601. (use-package jao-wayland :demand t)
  2602. (defun jao-wayland-enable ()
  2603. (interactive)
  2604. (defalias 'x-change-window-property #'ignore)
  2605. (jao-trisect)
  2606. (message "Welcome to wayland"))
  2607. (defun jao-river-enable ()
  2608. (jao-wayland-enable)
  2609. (when (jao-shell-running-p "i3bar-river")
  2610. (jao-tracking-set-log ""))
  2611. (message "Welcome to river"))
  2612. (when jao-river-enabled
  2613. (add-hook 'after-init-hook #'jao-river-enable t))
  2614. (when jao-sway-enabled
  2615. (add-hook 'after-init-hook #'jao-wayland-enable t))
  2616. ;;;; wallpaper
  2617. (defvar jao-wallpaper-dir "~/.wallpapers/")
  2618. (defvar jao-wallpaper-random-candidates
  2619. '("wallpaper.jpg" "wallpaper2.jpg"))
  2620. (defvar jao-wallpaper-random-candidates-light
  2621. '("wallpaper.jpg" "wallpaper2.jpg"))
  2622. (defvar jao-wallpaper-random-wake t
  2623. "Set to t for getting a new wallpaper on awaking from sleep")
  2624. (defun jao-set-wallpaper (&optional path)
  2625. (interactive)
  2626. (let ((current (format "~/.wallpaper.%s" (jao-colors-scheme))))
  2627. (when-let ((f (or (and path (expand-file-name path))
  2628. (read-file-name "Image: "
  2629. jao-wallpaper-dir
  2630. (file-symlink-p current)
  2631. t))))
  2632. (make-symbolic-link f current t)
  2633. (cond (jao-river-enabled (jao-river-set-wallpaper f))
  2634. (jao-sway-enabled (jao-sway-set-wallpaper f))
  2635. (t (shell-command-to-string (format "xwallpaper --zoom %s" f)))))))
  2636. (defun jao-set-random-wallpaper ()
  2637. (interactive)
  2638. (when (or (called-interactively-p 'interactive)
  2639. jao-wallpaper-random-wake)
  2640. (let* ((ws (if (jao-colors-scheme-dark-p)
  2641. jao-wallpaper-random-candidates
  2642. jao-wallpaper-random-candidates-light))
  2643. (f (seq-random-elt ws)))
  2644. (jao-set-wallpaper (expand-file-name f jao-wallpaper-dir))
  2645. (message "%s" f))))
  2646. (add-to-list 'jao-sleep-awake-functions #'jao-set-random-wallpaper)
  2647. ;;;; screensaver and lock
  2648. (defun jao-screensaver-enabled ()
  2649. (string= (jao-shell-string "xdg-screensaver status") "enabled"))
  2650. (defvar jao-screensaver--wid nil)
  2651. (defun jao-screensaver-toggle ()
  2652. (interactive)
  2653. (if (jao-screensaver-enabled)
  2654. (let ((wid (jao-x11-focused-id)))
  2655. (setq jao-screensaver--wid wid)
  2656. (jao-shell-exec* t "xdg-screensaver" "suspend" wid))
  2657. (jao-shell-exec* t "xdg-screensaver" "resume" jao-screensaver--wid)
  2658. (setq jao-screensaver--wid nil))
  2659. (jao-notify (format "Screensaver %s"
  2660. (jao-shell-string "xdg-screensaver status"))))
  2661. (jao-shell-def-exec jao-xlock-screen "xdg-screensaver" "activate")
  2662. (jao-shell-def-exec jao-suspend "sudo" "systemctl" "suspend")
  2663. (jao-shell-def-exec jao-poweroff "sudo" "systemctl" "poweroff")
  2664. (defun jao-lock-screen ()
  2665. (interactive)
  2666. (if jao-wayland-enabled
  2667. (shell-command "swaylock -i ~/.lockimage")
  2668. (jao-xlock-screen)))
  2669. (transient-define-prefix jao-transient-sleep ()
  2670. ["Sleep"
  2671. ("l" "lock screen" jao-lock-screen)
  2672. ("z" "sleep" jao-suspend)
  2673. ("u" (lambda ()
  2674. (if (jao-screensaver-enabled) "suspend screensaver" "resume screensaver"))
  2675. jao-screensaver-toggle)
  2676. ("poof" "power-off" jao-poweroff)])
  2677. ;;;; X clipboard
  2678. (setq select-enable-clipboard t
  2679. select-enable-primary t
  2680. selection-timeout 100
  2681. xterm-select-active-regions t)
  2682. (use-package xclip
  2683. :ensure t
  2684. :init (setq xclip-method (if jao-wayland-enabled 'wl-copy 'xclip)))
  2685. (unless (display-graphic-p) (xclip-mode 1))
  2686. ;;;; pop-up frames
  2687. (defun jao-open-in-x-frame (&optional width height)
  2688. (interactive)
  2689. (make-frame `((window-system . x)
  2690. (name . "emacs popup")
  2691. (width . ,(or width (window-width)))
  2692. (height . ,(or height (window-height)))))
  2693. (define-key (current-local-map) "q" #'delete-frame))
  2694. ;;;; xmobar
  2695. (defun jao-xmobar-kill ()
  2696. (interactive)
  2697. (shell-command "killall xmobar-single"))
  2698. (defun jao-xmobar-restart ()
  2699. (interactive)
  2700. (jao-xmobar-kill)
  2701. (start-process "" nil "xmobar-single" "-d"))
  2702. (use-package tab-bar
  2703. :init (setq tab-bar-close-button-show nil
  2704. tab-bar-show (> emacs-major-version 28)
  2705. tab-bar-format ()))
  2706. (use-package xmobar
  2707. :init (setq xmobar-tab-bar t
  2708. xmobar-tab-split "*"
  2709. xmobar-tab-bar-format
  2710. (if window-system
  2711. '(xmobar-left-string
  2712. tab-bar-format-align-right
  2713. xmobar-right-string)
  2714. '(xmobar-left-string
  2715. xmobar-elastic-space
  2716. xmobar-right-string))
  2717. xmobar-command
  2718. (if window-system '("xmobar-emacs" "-TAnsi") "xmobar-emacs")))
  2719. ;;; Global transients
  2720. (defun jao-list-packages ()
  2721. (interactive)
  2722. (jao-afio-goto-scratch)
  2723. (package-list-packages))
  2724. (defun jao-window-system-p ()
  2725. (or jao-exwm-enabled jao-xmonad-enabled jao-wayland-enabled))
  2726. (defun jao-x11-p () (or jao-exwm-enabled jao-xmonad-enabled))
  2727. (defun jao-reveal ()
  2728. (interactive)
  2729. (cond ((or outline-minor-mode (derived-mode-p 'outline-mode ))
  2730. (outline-show-entry))
  2731. ((derived-mode-p 'org-mode) (org-reveal))))
  2732. (jao-def-exec-in-term "aptitude" "aptitude" (jao-afio-goto-scratch))
  2733. (jao-def-exec-in-term "htop" "htop" (jao-afio-goto-scratch))
  2734. (transient-define-prefix jao-transient-utils ()
  2735. "Global operations."
  2736. [["Notes"
  2737. ("n" "create new note" jao-org-notes-create)
  2738. ("/" "open note" jao-org-notes-open)
  2739. ("\\" "open note by tags" jao-org-notes-consult-tags)
  2740. ("g" "ripgrep notes" jao-org-notes-consult-ripgrep)]
  2741. ["Documents"
  2742. ("dd" "go to doc" jao-select-pdf :if display-graphic-p)
  2743. ("do" "open doc" jao-open-doc)
  2744. ("dr" "search docs with recoll" jao-recoll-consult-docs)]
  2745. ["Monitors"
  2746. ("p" "htop" jao-term-htop)
  2747. ("P" "pasytray" jao-toggle-pasystray-applet)
  2748. ("x" "restart i3bar" jao-river-restart-i3bar :if jao-river-enabled-p)
  2749. ("x" "restart xmobar" jao-xmobar-restart :if jao-exwm-enabled-p)
  2750. ("x" "kill xmobar" jao-xmobar-kill :if jao-xmonad-enabled-p)]
  2751. ["Network"
  2752. ("s" "ssh" jao-ssh)
  2753. ("b" "bluetooth" bluetooth-list-devices)
  2754. ("c" "connect chats" jao-all-chats)
  2755. ("m" "proton bridge" run-proton-bridge)
  2756. ("v" "view video" jao-view-video)]
  2757. ["Chats"
  2758. ("t" "telegram" jao-chats-telega)
  2759. ("i" "irc" jao-chats-irc)
  2760. ("M" "mastodon" jao-mastodon)
  2761. ("T" "telegram rooster" jao-telega)]
  2762. ["Window system" :if jao-window-system-p
  2763. ("w" "set wallpaper" jao-set-wallpaper)
  2764. ("W" "set radom wallpaper" jao-set-random-wallpaper)
  2765. ("B u" (lambda ()
  2766. (let ((b (jao-brightness)))
  2767. (format "bright up %s" (and (string-match ".*\\((.+)\\).*" b)
  2768. (match-string 1 b)))))
  2769. jao-bright-up :transient t)
  2770. ("B d" "bright down" jao-bright-down :transient t)]
  2771. ["Helpers"
  2772. ("a" "aptitude" jao-term-aptitude)
  2773. ("l" "packages" jao-list-packages)
  2774. ("r" "reveal" jao-reveal)
  2775. ("k" (lambda () (concat "keyboard" (when (jao-kb-toggled-p) "*")))
  2776. jao-kb-toggle :if jao-x11-p)]])
  2777. (global-set-key (kbd "s-w") #'jao-transient-utils)
  2778. ;;; Global key bindings
  2779. (defun jao-global-keybindings ()
  2780. (interactive)
  2781. (global-set-key (kbd "<f2>") #'magit-status)
  2782. (global-set-key (kbd "C-x p") #'jao-prev-window)
  2783. (global-set-key (kbd "C-x o") 'other-window)
  2784. (global-set-key "\C-cj" #'join-line)
  2785. (global-set-key "\C-cn" #'next-error)
  2786. (global-set-key "\C-cq" #'auto-fill-mode)
  2787. (global-set-key "\C-xr\M-w" #'kill-rectangle-save)
  2788. (global-set-key "\C-c\C-z" #'comment-or-uncomment-region)
  2789. (global-set-key "\C-z" #'comment-or-uncomment-region))
  2790. (jao-global-keybindings)
  2791. ;;; Last minute (post.el)
  2792. (jao-load-site-el "post")