(when (or (string= (system-name) "fsociety") (string= (system-name) "heisenberg")) (add-to-list 'load-path "~/.guix-profile/share/emacs/site-lisp") (guix-emacs-autoload-packages)) (defconst my-package-list '(org-snooze all-the-icons all-the-icons-dired all-the-icons-ivy-rich toc-org general doom-themes doom-modeline counsel which-key ivy ivy-rich helpful org org-modern visual-fill-column rainbow-delimiters flycheck lsp-mode lsp-ui json-mode rjsx-mode typescript-mode python-mode pyvenv company company-box magit elfeed elfeed-goodies paredit corfu monkeytype sudo-edit exwm exwm-mff exwm-firefox-core consult alsamixer simple-httpd circe eshell-syntax-highlighting pdf-tools org-superstar mastodon dashboard org-auto-tangle)) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("org" . "https://orgmode.org/elpa/") ("elpa" . "https://elpa.gnu.org/packages/"))) (package-initialize) (unless package-archive-contents (package-refresh-contents)) (defvar my-missing-packages '() "List populated at each startup. Contains the list of packages that need to be installed.") (dolist (p my-package-list) (when (not (package-installed-p p)) (add-to-list 'my-missing-packages p))) (when my-missing-packages (message "Emacs is now refreshing its package database...") (package-refresh-contents) ;; Install the missing packages (dolist (p my-missing-packages) (message "Installing `%s' .." p) (package-install p)) (setq my-missing-packages '())) (unless (package-installed-p 'use-package) (package-install 'use-package)) (setq inhibit-startup-message nil) ;; Transparency (set-frame-parameter (selected-frame) 'alpha '(90 90)) (add-to-list 'default-frame-alist '(alpha 90 90)) (add-hook 'dired-mode-hook 'all-the-icons-dired-mode) (scroll-bar-mode -1) (tool-bar-mode -1) (tooltip-mode -1) (set-fringe-mode 10) (menu-bar-mode -1) (blink-cursor-mode -1) (menu-bar--visual-line-mode-enable) (setq visible-bell t) (column-number-mode) (global-display-line-numbers-mode 0) (menu-bar--display-line-numbers-mode-relative) ;;Disable line numbers for some modes (dolist (mode '(pdf-view-mode-hook org-mode-hook term-mode-hook shell-mode-hook eshell-mode-hook vterm-mode-hook elfeed)) (add-hook mode (lambda () (display-line-numbers-mode 0)))) (defvar apollo/default-font-size 140) (set-face-attribute 'default nil :font "JetBrains Mono" :height apollo/default-font-size) (set-face-attribute 'fixed-pitch nil :font "JetBrains Mono" :height apollo/default-font-size) (set-face-attribute 'variable-pitch nil :font "JetBrains Mono" :height apollo/default-font-size :weight 'regular) (require 'dashboard) (require 'all-the-icons) (dashboard-setup-startup-hook) (setq dashboard-items '((recents . 5) (bookmarks . 5))) (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")) dashboard-item-names '(("Recent Files:" . "Recent Files:") ("Bookmarks:" . "Study:"))) ;; Set the banner (setq dashboard-startup-banner "~/dotfiles/pictures/medicine/plague-doctor-s.png") ;; Set the title (setq dashboard-banner-logo-title "Is that a flying flower?") ;; (setq dashboard-init-info "Bring me your sick and wounded!") (setq dashboard-set-init-info t dashboard-center-content t dashboard-set-navigator t dashboard-set-heading-icons t dashboard-set-file-icons t dashboard-show-shortcuts nil dashboard-set-footer t dashboard-footer-messages '("Welcome to the Church Of Emacs") dashboard-footer-icon (all-the-icons-octicon "broadcast" :height 1.15 :v-adjust -0.05 :face 'font-lock-keyword-face)) (load-theme 'doom-ayu-dark t) (doom-modeline-mode 1) (setq doom-modeline-height 35) (use-package ivy :diminish :bind (("C-s" . swiper) :map ivy-minibuffer-map ("TAB" . ivy-alt-done) ("C-l" . ivy-alt-done) ("C-j" . ivy-next-line) ("C-k" . ivy-previous-line) :map ivy-switch-buffer-map ("C-k" . ivy-previous-line) ("C-l" . ivy-done) ("C-d" . ivy-switch-buffer-kill) :map ivy-reverse-i-search-map ("C-k" . ivy-previous-line) ("C-d" . ivy-reverse-i-search-kill)) :config (ivy-mode 1) (setq ivy-use-selectable-prompt t)) (ivy-rich-mode 1) (all-the-icons-ivy-rich-mode 1) (use-package helpful :custom (counsel-describe-function-function #'helpful-callable) (counsel-describe-variable-function #'helpful-variable) :bind ([remap describe-function] . counsel-describe-function) ([remap describe-command] . helpful-command) ([remap describe-variable] . counsel-describe-variable) ([remap describe-key] . helpful-key)) (define-key dired-mode-map "b" 'dired-up-directory) ;;; all-the-icons-dired.el --- Shows icons for each file in dired mode -*- lexical-binding: t; -*- ;;; Code: (require 'cl-lib) (require 'dired) (require 'all-the-icons) (defface all-the-icons-dired-dir-face '((((background dark)) :foreground "white") (((background light)) :foreground "black")) "Face for the directory icon" :group 'all-the-icons-faces) (defcustom all-the-icons-dired-v-adjust 0.01 "The default vertical adjustment of the icon in the dired buffer." :group 'all-the-icons :type 'number) (defvar all-the-icons-dired-mode) (defun all-the-icons-dired--add-overlay (pos string) "Add overlay to display STRING at POS." (let ((ov (make-overlay (1- pos) pos))) (overlay-put ov 'all-the-icons-dired-overlay t) (overlay-put ov 'after-string string))) (defun all-the-icons-dired--overlays-in (beg end) "Get all all-the-icons-dired overlays between BEG to END." (cl-remove-if-not (lambda (ov) (overlay-get ov 'all-the-icons-dired-overlay)) (overlays-in beg end))) (defun all-the-icons-dired--overlays-at (pos) "Get all-the-icons-dired overlays at POS." (apply #'all-the-icons-dired--overlays-in `(,pos ,pos))) (defun all-the-icons-dired--remove-all-overlays () "Remove all `all-the-icons-dired' overlays." (save-restriction (widen) (mapc #'delete-overlay (all-the-icons-dired--overlays-in (point-min) (point-max))))) (defun all-the-icons-dired--refresh () "Display the icons of files in a dired buffer." (all-the-icons-dired--remove-all-overlays) (save-excursion (goto-char (point-min)) (while (not (eobp)) (when (dired-move-to-filename nil) (let ((file (dired-get-filename 'relative 'noerror))) (when file (let ((icon (if (file-directory-p file) (all-the-icons-icon-for-dir file :face 'all-the-icons-dired-dir-face :v-adjust all-the-icons-dired-v-adjust) (all-the-icons-icon-for-file file :v-adjust all-the-icons-dired-v-adjust)))) (if (member file '("." "..")) (all-the-icons-dired--add-overlay (point) " \t") (all-the-icons-dired--add-overlay (point) (concat icon "\t"))))))) (forward-line 1)))) (defun all-the-icons-dired--refresh-advice (fn &rest args) "Advice function for FN with ARGS." (apply fn args) (when all-the-icons-dired-mode (all-the-icons-dired--refresh))) (defun all-the-icons-dired--setup () "Setup `all-the-icons-dired'." (when (derived-mode-p 'dired-mode) (setq-local tab-width 1) (advice-add 'dired-readin :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-revert :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-internal-do-deletions :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-insert-subdir :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-do-kill-lines :around #'all-the-icons-dired--refresh-advice) (with-eval-after-load 'dired-narrow (advice-add 'dired-narrow--internal :around #'all-the-icons-dired--refresh-advice)) (all-the-icons-dired--refresh))) (defun all-the-icons-dired--teardown () "Functions used as advice when redisplaying buffer." (advice-remove 'dired-readin #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-revert #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-internal-do-deletions #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-narrow--internal #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-insert-subdir #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-do-kill-lines #'all-the-icons-dired--refresh-advice) (all-the-icons-dired--remove-all-overlays)) ;;;###autoload (define-minor-mode all-the-icons-dired-mode "Display all-the-icons icon for each files in a dired buffer." :lighter " all-the-icons-dired-mode" (when (and (derived-mode-p 'dired-mode) (display-graphic-p)) (if all-the-icons-dired-mode (all-the-icons-dired--setup) (all-the-icons-dired--teardown)))) (add-hook 'dired-mode-hook 'all-the-icons-dired-mode) (use-package vterm :ensure nil :config ;; Check if it's one of my guix systems to load from ;; ~/.guix-profile. Otherwise we use /bin/zsh. (if (or (string= (system-name) "fsociety") (string= (system-name) "heisenberg")) (setq vterm-shell "~/.guix-profile/bin/zsh") (setq vterm-shell "/bin/zsh"))) (use-package eshell :ensure nil :bind (("C-c e" . 'eshell)) :config (defvar eshell-path-env (getenv "~/.local/bin"))) (defun with-face (str &rest face-plist) (propertize str 'face face-plist)) (defun apollo-eshell-prompt () (let ((winter-blue "#3F3B6C") (white-summer "#E5E5CB") (green-night "#03C988") (orange-summer "#FFB100") (green-summer "#A3BB98") (summer-sea "#2192FF") (black "#000000")) (concat (with-face (concat "[" user-login-name) :foreground orange-summer :background black) (with-face "@" :foreground orange-summer :background black) (with-face (concat system-name "]\n") :foreground orange-summer :background black) (with-face (concat "|" (eshell/pwd) ) :foreground "#F0E9D2" :background winter-blue) (with-face (format-time-string " | %H:%M" (current-time)) :background winter-blue :foreground "#888") (with-face "\n -> ")))) ;; (setq eshell-prompt-function 'apollo-eshell-prompt) ;; (setq eshell-highlight-prompt t) (require 'seq) (eval-when-compile (require 'cl-lib) (require 'subr-x) (require 'env) (require 'json)) (defgroup chatgpt nil "ChatGPT frontend." :group 'convenience :prefix "chatgpt-") (defcustom chatgpt-max-tokens 300 "Upper limit on the number of tokens the API will return." :type 'integer) (defvar chatgpt-buffer "*ChatGPT*" "Title of the buffer used to store the results of an OpenAI API query.") (define-error 'chatgpt-error "An error related to the ChatGPT emacs package") (define-error 'chatgpt-parsing-error "An error caused by a failure to parse an OpenAI API Response") (defmacro chatgpt-show-results-buffer-if-active () "Show the results in other window if necessary." `(if (and (not ;; visible (get-buffer-window chatgpt-buffer)) (called-interactively-p 'interactive)) (lambda (&optional buf) (ignore buf) (with-current-buffer buf (view-mode t)) (switch-to-buffer-other-window chatgpt-buffer)) #'identity)) ;;;###autoload (defun chatgpt-prompt (prompt callback) "Query OpenAI with PROMPT calling the CALLBACK function on the resulting buffer. Returns buffer containing the text from this query" (interactive (list (read-string "Prompt ChatGPT with: ") (lambda (buf) (with-current-buffer buf (view-mode t)) (switch-to-buffer-other-window chatgpt-buffer)))) (chatgpt--query-open-api prompt (lambda (results) (with-current-buffer (get-buffer-create chatgpt-buffer) ;; Erase contents of buffer after receiving response (read-only-mode -1) (erase-buffer) (insert results) ;; Return the chatgpt output buffer for non interactive usage (funcall callback (current-buffer)))))) ;;;###autoload (defun chatgpt-fix-region (BEG END) "Takes a region BEG to END asks ChatGPT to explain whats wrong with it. It then displays the answer in the `chatgpt-buffer'." (interactive "r") (let ((current-code (buffer-substring BEG END))) (chatgpt-prompt (chatgpt--append-to-prompt current-code "Why doesn't this code work?") (chatgpt-show-results-buffer-if-active)))) ;;;###autoload (defun chatgpt-explain-region (BEG END) "Takes a region BEG to END asks ChatGPT what it does. The answer in the displays in `chatgpt-buffer'." (interactive "r") (let ((current-code (buffer-substring BEG END))) (chatgpt-prompt (chatgpt--append-to-prompt current-code "What does this code do?") (chatgpt-show-results-buffer-if-active)))) ;;;###autoload (defun chatgpt-gen-tests-for-region (BEG END) "Takes a region BEG to END asks ChatGPT to write a test for it. It then displays the answer in the `chatgpt-buffer'." (interactive "r") (let ((current-code (buffer-substring BEG END))) (chatgpt-prompt (chatgpt--append-to-prompt current-code "Write me a tests for this code") (chatgpt-show-results-buffer-if-active)))) ;; TODO currently just says what changed but doesn't wanna show the code it's self ;; (defun chatgpt-optimize-region (BEG END) ;; "Takes a region BEG to END asks ChatGPT to optimize it for speed. ;; It then displays the answer in the `chatgpt-buffer'." ;; (interactive "r") ;; (let ((current-code (buffer-substring BEG END))) ;; (chatgpt-prompt (chatgpt--append-to-prompt ;; current-code ;; "Refactor this code for speed and tell me what you changed and why it's faster") ;; (chatgpt-show-results-buffer-if-active)))) ;;;###autoload (defun chatgpt-refactor-region (BEG END) "Takes a region BEG to END asks ChatGPT refactor it. It then displays the answer in the `chatgpt-buffer'." (interactive "r") (let ((current-code (buffer-substring BEG END))) (chatgpt-prompt (chatgpt--append-to-prompt current-code "Refactor this code and tell me what you changed") (chatgpt-show-results-buffer-if-active)))) ;;;###autoload (defun chatgpt-prompt-region (BEG END) "Prompt ChatGPT with the region BEG END. It then displays the results in a separate buffer `chatgpt-buffer'." (interactive "r") (chatgpt-prompt (buffer-substring BEG END) ;; Show the results if not already being viewed (chatgpt-show-results-buffer-if-active))) ;;;###autoload (defun chatgpt-prompt-region-and-replace (BEG END) "Replace region from BEG to END with the response from the ChatGPT API. The region is BEG and until END" (interactive "r") (let ((og-buf (current-buffer))) (chatgpt-prompt (buffer-substring BEG END) (lambda (buf) (save-excursion (with-current-buffer og-buf (delete-region BEG END) (goto-char BEG) (insert (with-current-buffer buf (buffer-string))))))))) (defun chatgpt--append-to-prompt (prompt comment-str) "Append the string COMMENT-STR extra information to a PROMPT as a comment." (concat prompt "\n" comment-start " " comment-str)) (defun chatgpt--extract-text-from-query (query-result) "Extract the resulting text from a given OpenAI response QUERY-RESULT." (condition-case err (thread-last query-result (assoc-default 'choices) seq-first (assoc-default 'text) string-trim) (error (signal 'chatgpt-parsing-error err)))) (defun chatgpt--parse-response (status callback) "Ignoring STATUS and parse the response executing the CALLBACK function on the resulting string." (ignore status) ;; All this is ran inside the buffer containing the response (goto-char 0) (re-search-forward "^$") (funcall callback (chatgpt--extract-text-from-query (json-read)))) (defun chatgpt--query-open-api (prompt callback) "Send a string PROMPT to OpenAI API and pass the resulting buffer to CALLBACK. The environment variable OPENAI_API_KEY is used as your API key You can register an account here https://beta.openai.com/docs/introduction/key-concepts" (let* ((api-key (getenv secret-api)) (url-request-method (encode-coding-string "POST" 'us-ascii)) (url-request-extra-headers `(("Content-Type" . "application/json") ("Authorization" . ,(format "Bearer %s" api-key)))) (url-request-data (json-encode `(("model" . "text-davinci-003") ("prompt" . ,prompt) ("max_tokens" . ,chatgpt-max-tokens) ("temperature" . 0))))) (cl-assert (not (string= "" api-key)) t "Current contents of the environmental variable OPENAI_API_KEY are '%s' which is not an appropriate OpenAI token please ensure you have the correctly set the OPENAI_API_KEY variable" api-key) (url-retrieve "https://api.openai.com/v1/completions" 'chatgpt--parse-response (list callback)))) (defun apollo/html-boostrap-boilerplate () "Insert html boilerplate with boostrap link." (interactive) (insert "