Compare commits

..

5 commits

Author SHA1 Message Date
Howard Abrams
a1118e0c2e Minor cleanup on eshell and remote terminals 2025-03-21 09:04:11 -07:00
Howard Abrams
9bb159c087 Pin the location for the Markdown linter 2025-03-21 09:04:11 -07:00
Howard Abrams
de618dfde7 Add ultra-scroll as a standard package 2025-03-21 09:04:11 -07:00
Howard Abrams
e7e61b4134 Use cl-case instead of case for Emacs 30 2025-03-21 09:04:11 -07:00
Howard Abrams
65ff19ba32 Migrate python from minor-leader to major-mode-hydra 2025-03-21 09:03:05 -07:00
9 changed files with 255 additions and 167 deletions

View file

@ -26,9 +26,9 @@ If I want to build from source (and not build from Homebrew), install all the de
libtiff jansson libpng librsvg gnutls cmake libtiff jansson libpng librsvg gnutls cmake
#+end_src #+end_src
To get the native compilation for Emacs working, install: To get the native compilation for Emacs working, I [[https://github.com/d12frosted/homebrew-emacs-plus/issues/680#issuecomment-2481633820][need to *un*-install]], as the new brew recipe will take care of this:
#+begin_src sh #+begin_src sh
brew install libgccjit brew uninstall libgccjit gcc
#+end_src #+end_src
Oh, and if we are still building with [[https://imagemagick.org/][ImageMagick]], install that first: Oh, and if we are still building with [[https://imagemagick.org/][ImageMagick]], install that first:

View file

@ -98,7 +98,8 @@
(defun org-confluence-checkbox (checkbox info) (defun org-confluence-checkbox (checkbox info)
"Format CHECKBOX into Confluence (even though Confluence won't take it. We take the CHECKBOX to be either 'on' or 'off' and we ignore INFO." "Format CHECKBOX into Confluence (even though Confluence won't take it. We take the CHECKBOX to be either 'on' or 'off' and we ignore INFO."
(case checkbox (on "(/)") (cl-case checkbox
(on "(/)")
(off "(x)") (off "(x)")
(trans "(-)") (trans "(-)")
(t ""))) (t "")))
@ -107,7 +108,7 @@
"Wrap a list with the html-ish stuff, but only if descriptive." "Wrap a list with the html-ish stuff, but only if descriptive."
(let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item (let* (arg1 ;; (assoc :counter (org-element-map plain-list 'item
(type (org-element-property :type plain-list))) (type (org-element-property :type plain-list)))
(case type (cl-case type
(descriptive (format "{html}<dl>\n%s\n</dl>{html}" contents)) (descriptive (format "{html}<dl>\n%s\n</dl>{html}" contents))
(otherwise contents)))) (otherwise contents))))
@ -120,7 +121,7 @@
(br "\n\n")) (br "\n\n"))
(message "Got %s with %s" type contents) (message "Got %s with %s" type contents)
(concat (concat
(case type (cl-case type
(ordered (ordered
(let* ((counter term-counter-id) (let* ((counter term-counter-id)
(extra (if counter (format " value=\"%s\"" counter) ""))) (extra (if counter (format " value=\"%s\"" counter) "")))

View file

@ -79,7 +79,20 @@ I get issues with Magic and Dimmer, so lets turn off this feature in certain
#+end_src #+end_src
As an interesting alternative, check out the [[https://www.emacs.dyerdwelling.family/emacs/20240208164549-emacs-selected-window-accent-mode-now-on-melpa/][selected-window-accent]] project. As an interesting alternative, check out the [[https://www.emacs.dyerdwelling.family/emacs/20240208164549-emacs-selected-window-accent-mode-now-on-melpa/][selected-window-accent]] project.
* Find the Bloody Cursor ** Ultra Scroll
The [[https://github.com/jdtsmith/ultra-scroll][ultra-scroll]] project allows smoother scrolling of text and images. While this splits text at the top/bottom of buffer windows, we no longer work within a 80x24 text matrix. Large images would
either be "there or not" which resulted large jumps and large distractions.
#+BEGIN_SRC emacs-lisp
(use-package ultra-scroll
:straight (:type git :host github :repo "jdtsmith/ultra-scroll")
:config
(setq scroll-conservatively 101 ; important!
scroll-margin 0)
(ultra-scroll-mode 1))
#+END_SRC
** Find the Bloody Cursor
Large screen, lots of windows, so where is the cursor? While I used to use =hl-line+=, I found that the prolific [[https://protesilaos.com/][Protesilaos Stavrou]] [[https://protesilaos.com/codelog/2022-03-14-emacs-pulsar-demo/][introduced his Pulsar project]] is just what I need. Specifically, I might /loose the cursor/ and need to have it highlighted (using ~F8~), but also, this automatically highlights the cursor line with specific /actions/ , like changing windows. Large screen, lots of windows, so where is the cursor? While I used to use =hl-line+=, I found that the prolific [[https://protesilaos.com/][Protesilaos Stavrou]] [[https://protesilaos.com/codelog/2022-03-14-emacs-pulsar-demo/][introduced his Pulsar project]] is just what I need. Specifically, I might /loose the cursor/ and need to have it highlighted (using ~F8~), but also, this automatically highlights the cursor line with specific /actions/ , like changing windows.
#+begin_src emacs-lisp #+begin_src emacs-lisp

View file

@ -43,6 +43,9 @@ I like =debug-on-error=, but not in Eshell, so I set this up when entering Eshel
(setq mode-line-format nil)) (setq mode-line-format nil))
#+end_src #+end_src
** Directory Notification ** Directory Notification
:PROPERTIES:
:ID: AD963BB5-6346-46C0-A364-4C8AEBA29882
:END:
While most people put the “current directory” in their shell prompt, Ive always found that pretty distracting, difficult when copy/pasting commands, and cuts out on the length of my commands (which might be a good thing, tbh). While most people put the “current directory” in their shell prompt, Ive always found that pretty distracting, difficult when copy/pasting commands, and cuts out on the length of my commands (which might be a good thing, tbh).
I use the =header-line= for this. I use the =header-line= for this.
@ -155,7 +158,7 @@ Keep in mind that the predicates are somewhat finicky. For instance, the followi
mv $f $f(:r).txt mv $f $f(:r).txt
#+end_src #+end_src
But you could call this: Instead, call this:
#+begin_src sh #+begin_src sh
mv $f $f(:s/org$/txt/) mv $f $f(:s/org$/txt/)
@ -1247,23 +1250,6 @@ I use =ex= to refer to both =en= / =ec=. Use cases:
The =-c= option can be combined with the /command/, but I dont want it to grab the last output, as I think I would just like to send text to the notebook as after thoughts. If the option to =-c= is blank, perhaps it just calls the capture template to allow me to enter voluminous content. The =-c= option can be combined with the /command/, but I dont want it to grab the last output, as I think I would just like to send text to the notebook as after thoughts. If the option to =-c= is blank, perhaps it just calls the capture template to allow me to enter voluminous content.
This requires capture templates that dont do any formatting. I will reused =c c= from [[file:ha-capturing-notes.org::*General Notes][capturing-notes]] code, and create other templates under =e= prefix:
#+begin_src emacs-lisp
;; (setq org-capture-templates nil)
(add-to-list 'org-capture-templates
'("e" "Engineering Notebook"))
(add-to-list 'org-capture-templates
'("ee" "Notes and Commentary" plain
(file+olp+datetree org-default-notes-file "General Notes")
"%i" :empty-lines 1 :tree-type month :unnarrowed t))
(add-to-list 'org-capture-templates
'("ef" "Piped-in Contents" plain
(file+olp+datetree org-default-notes-file "General Notes")
"%i" :immediate-finish t :empty-lines 1 :tree-type month))
#+end_src
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defun ha-eshell-engineering-notebook (capture-template args) (defun ha-eshell-engineering-notebook (capture-template args)
"Capture commands and output from Eshell into an Engineering Notebook. "Capture commands and output from Eshell into an Engineering Notebook.
@ -1328,7 +1314,33 @@ This requires capture templates that dont do any formatting. I will reused =c
;; Return output from the command, or nothing if there wasn't anything: ;; Return output from the command, or nothing if there wasn't anything:
(or output ""))) (or output "")))
#+end_src #+end_src
And now we have a =en= and a =ec= version:
This requires capture templates that dont do any formatting. I will reused =c c= from [[file:ha-capturing-notes.org::*General Notes][capturing-notes]] code, and create other templates under =e= prefix:
#+begin_src emacs-lisp
(add-to-list 'org-capture-templates '("e" "Engineering Notebook"))
(add-to-list 'org-capture-templates
'("ee" "Notes and Commentary" plain
(file+olp+datetree org-default-notes-file "General Notes")
"%i" :empty-lines 1 :tree-type month :unnarrowed t))
(add-to-list 'org-capture-templates
'("ef" "Piped-in Contents" plain
(file+olp+datetree org-default-notes-file "General Notes")
"%i" :immediate-finish t :empty-lines 1 :tree-type month))
#+end_src
The =cap= function simply calls [[help-org-capture][org-capture]] with [[info:org#Template elements][a template]]:
#+begin_src emacs-lisp
(defun eshell/cap (&rest args)
"Call `org-capture' with the `ee' template to enter text into the engineering notebook."
(org-capture nil "ee"))
#+end_src
The =en= and =ec= functions, since they do /pre-processing/ before calling =org-capture= calls some helper functions:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defun eshell/en (&rest args) (defun eshell/en (&rest args)
"Call `ha-eshell-engineering-notebook' to \"General Notes\"." "Call `ha-eshell-engineering-notebook' to \"General Notes\"."
@ -1341,12 +1353,7 @@ And now we have a =en= and a =ec= version:
(ha-eshell-engineering-notebook "cc" args)) (ha-eshell-engineering-notebook "cc" args))
#+end_src #+end_src
This function simply calls [[help-org-capture][org-capture]] with [[info:org#Template elements][a template]]: In order to have /devices/, for instance =some-command > e=, we define some functions:
#+begin_src emacs-lisp
(defun eshell/cap (&rest args)
"Call `org-capture' with the `ee' template to enter text into the engineering notebook."
(org-capture nil "ee"))
#+end_src
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defun ha-eshell-target-engineering-notebook (output) (defun ha-eshell-target-engineering-notebook (output)
@ -1357,7 +1364,9 @@ This function simply calls [[help-org-capture][org-capture]] with [[info:org#Tem
"Write OUTPUT into the current clocked in task via `org-capture'." "Write OUTPUT into the current clocked in task via `org-capture'."
(ha-eshell-engineering-capture "cc" nil nil output)) (ha-eshell-engineering-capture "cc" nil nil output))
#+end_src #+end_src
And finally, add our new functions to [[elisp(describe-variable 'eshell-virtual-targets)][eshell-virtual-targets]]:
And add these functions to [[elisp(describe-variable 'eshell-virtual-targets)][eshell-virtual-targets]], after =eshell= has been loaded:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(with-eval-after-load "eshell" (with-eval-after-load "eshell"
(add-to-list 'eshell-virtual-targets '("/dev/e" ha-eshell-target-engineering-notebook nil)) (add-to-list 'eshell-virtual-targets '("/dev/e" ha-eshell-target-engineering-notebook nil))
@ -1505,8 +1514,11 @@ Now tie it all together with a prompt function can color each of the prompts com
(setq-default eshell-prompt-function #'eshell/eshell-local-prompt-function) (setq-default eshell-prompt-function #'eshell/eshell-local-prompt-function)
#+end_src #+end_src
Here is the result: Here is the result:
[[http://imgur.com/nkpwII0.png]] [[file:screenshots/eshell-special-prompt.png]]
To be honest, this sort of prompt is garish and distracting. A better approach is to have that information in either the mode line, or a [[Directory Notification][header-line]].
** Simple Prompt with Mode Line ** Simple Prompt with Mode Line
To achieve more /screen estate/, leave your prompt simple: To achieve more /screen estate/, leave your prompt simple:
#+begin_src emacs-lisp #+begin_src emacs-lisp
@ -1615,6 +1627,17 @@ And lets bind it:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(bind-key "C-!" 'eshell-here) (bind-key "C-!" 'eshell-here)
#+end_src #+end_src
Obviously, I usually want to open a shell in the root of the current project.
#+BEGIN_SRC emacs-lisp
(defun eshell-project ()
"Call `eshell-there' with the current project root."
(interactive)
(eshell-there (or (project-root (project-current))
default-directory)))
#+END_SRC
** Shell Over There ** Shell Over There
Would be nice to be able to run an eshell session and use Tramp to connect to the remote host in one fell swoop: Would be nice to be able to run an eshell session and use Tramp to connect to the remote host in one fell swoop:
#+begin_src emacs-lisp #+begin_src emacs-lisp

View file

@ -892,7 +892,7 @@ Since the /definitions/ do not work, so let's use the [[https://github.com/abo-a
:bind ("s-d" . define-word-at-point) :bind ("s-d" . define-word-at-point)
:config :config
(ha-leader :keymaps 'text-mode-map (ha-leader :keymaps 'text-mode-map
"s d" '(:ignore t :which-key "thesaurus") "s d" '(:ignore t :which-key "dictionary")
"s d d" '("define this word" . define-word-at-point) "s d d" '("define this word" . define-word-at-point)
"s d a" '("define any word" . define-word))) "s d a" '("define any word" . define-word)))
#+end_src #+end_src

View file

@ -337,7 +337,7 @@ All the above loveliness can be easily accessible with a [[https://github.com/je
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package major-mode-hydra (use-package major-mode-hydra
:config :config
(major-mode-hydra-define emacs-lisp-mode (:quit-key "q" :color pink) (major-mode-hydra-define emacs-lisp-mode (:quit-key "q" :color blue)
("Evaluating" ("Evaluating"
(("e" ha-eval-current-expression "Current") (("e" ha-eval-current-expression "Current")
("d" lispy-debug/body "Debugging") ("d" lispy-debug/body "Debugging")

View file

@ -49,6 +49,53 @@ Note: Install the following checks:
pip install flake8 pylint pyright mypy pycompile pip install flake8 pylint pyright mypy pycompile
#+end_src #+end_src
Or better yet, add those to the =requirements-dev.txt= file. Or better yet, add those to the =requirements-dev.txt= file.
All the above loveliness can be easily accessible with a [[https://github.com/jerrypnz/major-mode-hydra.el][major-mode-hydra]] defined for =emacs-lisp-mode=:
#+begin_src emacs-lisp
(use-package major-mode-hydra
:config
(defvar ha-python-eval-title (font-icons 'mdicon "run" :title "Python Evaluation"))
(defvar ha-python-goto-title (font-icons 'faicon "python" :title "Python Symbol References"))
(pretty-hydra-define python-evaluate (:color blue :quit-key "q"
:title ha-python-eval-title)
("Section"
(("f" python-shell-send-defun "Function/Class")
("e" python-shell-send-statement "Line")
(";" python-shell-send-string "Expression"))
"Entirety"
(("F" python-shell-send-file "File")
("B" python-shell-send-buffer "Buffer")
("r" python-shell-send-region "Region"))))
(pretty-hydra-define python-goto (:color blue :quit-key "q"
:title ha-python-goto-title)
("Symbols"
(("s" xref-find-apropos "Find Symbol")
("e" python-shell-send-statement "Line")
(";" python-shell-send-string "Expression"))
"Entirety"
(("F" python-shell-send-file "File")
("B" python-shell-send-buffer "Buffer")
("r" python-shell-send-region "Region"))))
(major-mode-hydra-define python-mode (:quit-key "q" :color blue)
("Server"
(("S" run-python "Start Server")
("s" python-shell-switch-to-shell "Go to Server"))
"Edit"
(("r" iedit-mode "Rename")
(">" python-indent-shift-left "Shift Left")
("<" python-indent-shift-right "Shift Right"))
"Navigate/Eval"
(("e" python-evaluate/body "Evaluate...")
("g" python-goto/body "Go to..."))
"Docs"
(("d" python-eldoc-at-point "Docs on Symbol")
("D" python-describe-at-point "Describe Symbol")))))
#+end_src
** Virtual Environment ** Virtual Environment
For a local virtual machine, put the following in your =.envrc= file: For a local virtual machine, put the following in your =.envrc= file:
#+begin_src conf #+begin_src conf
@ -68,7 +115,7 @@ use python 3.7.1
Also, you need the following in your =~/.config/direnv/direnvrc= file (which I have): Also, you need the following in your =~/.config/direnv/direnvrc= file (which I have):
#+begin_src shell #+begin_src shell
use_python() { use_python() {
local python_root=$(pyenv root)/versions/$1 local python_root=$(pyenv root)/versions/$1
load_prefix "$python_root" load_prefix "$python_root"
if [[ -x "$python_root/bin/python" ]]; then if [[ -x "$python_root/bin/python" ]]; then
@ -77,7 +124,7 @@ use_python() {
echo "Error: $python_root/bin/python can't be executed." echo "Error: $python_root/bin/python can't be executed."
exit exit
fi fi
} }
#+end_src #+end_src
** Editing Python Code ** Editing Python Code
Lets integrate this [[https://github.com/wbolster/evil-text-object-python][Python support for evil-text-object]] project: Lets integrate this [[https://github.com/wbolster/evil-text-object-python][Python support for evil-text-object]] project:
@ -96,11 +143,11 @@ Enough of the rant (I go back and forth), after getting Docker installed and run
Your project's =.envrc= file would contain something like: Your project's =.envrc= file would contain something like:
#+begin_src shell #+begin_src shell
CONTAINER_NAME=my-docker-container CONTAINER_NAME=my-docker-container
CONTAINER_WRAPPERS=(python3 pip3 yamllint) CONTAINER_WRAPPERS=(python3 pip3 yamllint)
CONTAINER_EXTRA_ARGS="--env SOME_ENV_VAR=${SOME_ENV_VAR}" CONTAINER_EXTRA_ARGS="--env SOME_ENV_VAR=${SOME_ENV_VAR}"
container_layout container_layout
#+end_src #+end_src
** Unit Tests ** Unit Tests
#+begin_src emacs-lisp #+begin_src emacs-lisp
@ -108,21 +155,31 @@ container_layout
:after python :after python
:commands python-pytest-dispatch :commands python-pytest-dispatch
:init :init
(ha-local-leader :keymaps 'python-mode-map (use-package major-mode-hydra
"t" '(:ignore t :which-key "tests") :config
"t a" '("all" . python-pytest) (defvar ha-python-tests-title (font-icons 'devicon "pytest" :title "Python Test Framework"))
"t f" '("file dwim" . python-pytest-file-dwim) (pretty-hydra-define python-tests (:color blue :quit-key "q"
"t F" '("file" . python-pytest-file) :title ha-python-tests-title)
"t t" '("function-dwim" . python-pytest-function-dwim) ("Suite"
"t T" '("function" . python-pytest-function) (("a" python-pytest "All")
"t r" '("repeat" . python-pytest-repeat) ("f" python-pytest-file-dwim "File DWIM")
"t p" '("dispatch" . python-pytest-dispatch))) ("F" python-pytest-file "File"))
"Specific"
(("d" python-pytest-function-dwim "Function DWIM")
("D" python-pytest-function "Function"))
"Again"
(("r" python-pytest-repeat "Repeat tests")
("p" python-pytest-dispatch "Dispatch"))))
(major-mode-hydra-define+ python-mode (:quit-key "q" :color blue)
("Misc"
(("t" python-tests/body "Tests..."))))))
#+end_src #+end_src
** Python Dependencies ** Python Dependencies
Each Python project's =requirements-dev.txt= file would reference the [[https://pypi.org/project/python-lsp-server/][python-lsp-server]] (not the /unmaintained/ project, =python-language-server=): Each Python project's =requirements-dev.txt= file would reference the [[https://pypi.org/project/python-lsp-server/][python-lsp-server]] (not the /unmaintained/ project, =python-language-server=):
#+begin_src conf :tangle no #+begin_src conf :tangle no
python-lsp-server[all] python-lsp-server[all]
#+end_src #+end_src
*Note:* This does mean, you would have a =tox.ini= with this line: *Note:* This does mean, you would have a =tox.ini= with this line:
@ -144,114 +201,99 @@ python-lsp-server[all]
*** Pyright *** Pyright
Im using the Microsoft-supported [[https://github.com/Microsoft/pyright][pyright]] package instead. Adding this to my =requirements.txt= files: Im using the Microsoft-supported [[https://github.com/Microsoft/pyright][pyright]] package instead. Adding this to my =requirements.txt= files:
#+begin_src conf :tangle no #+begin_src conf :tangle no
pyright pyright
#+end_src #+end_src
The [[https://github.com/emacs-lsp/lsp-pyright][pyright package]] works with LSP. The [[https://github.com/emacs-lsp/lsp-pyright][pyright package]] works with LSP.
#+begin_src emacs-lisp :tangle no #+begin_src emacs-lisp :tangle no
(use-package lsp-pyright (use-package lsp-pyright
:hook (python-mode . (lambda () (require 'lsp-pyright))) :hook (python-mode . (lambda () (require 'lsp-pyright)))
:init (when (executable-find "python3") :init (when (executable-find "python3")
(setq lsp-pyright-python-executable-cmd "python3"))) (setq lsp-pyright-python-executable-cmd "python3")))
#+end_src #+end_src
* LSP Integration of Python * LSP Integration of Python
Now that the [[file:ha-programming.org::*Language Server Protocol (LSP) Integration][LSP Integration]] is complete, we can stitch the two projects together, by calling =lsp=. I oscillate between automatically turning on LSP mode with every Python file, but I sometimes run into issues when starting, so I turn it on with ~, w s~. Now that the [[file:ha-programming.org::*Language Server Protocol (LSP) Integration][LSP Integration]] is complete, we can stitch the two projects together, by calling =lsp=. I oscillate between automatically turning on LSP mode with every Python file, but I sometimes run into issues when starting, so I conditionally turn it on.
#+begin_src emacs-lisp
(defvar ha-python-lsp-title (font-icons 'faicon "python" :title "Python LSP"))
(defun ha-setup-python-lsp ()
"Configure the keybindings for LSP in Python."
(interactive)
(pretty-hydra-define python-lsp (:color blue :quit-key "q"
:title ha-python-lsp-title)
("Server"
(("D" lsp-disconnect "Disconnect")
("R" lsp-workspace-restart "Restart")
("S" lsp-workspace-shutdown "Shutdown")
("?" lsp-describe-session "Describe"))
"Refactoring"
(("a" lsp-execute-code-action "Code Actions")
("o" lsp-organize-imports "Organize Imports")
("l" lsp-avy-lens "Avy Lens"))
"Toggles"
(("b" lsp-headerline-breadcrumb-mode "Breadcrumbs")
("d" lsp-ui-doc-mode "Documentation Popups")
("m" lsp-modeline-diagnostics-mode "Modeline Diagnostics")
("s" lsp-ui-sideline-mode "Sideline Mode"))
""
(("t" lsp-toggle-on-type-formatting "Type Formatting")
("h" lsp-toggle-symbol-highlight "Symbol Highlighting")
("L" lsp-toggle-trace-io "Log I/O"))))
(pretty-hydra-define+ python-goto (:quit-key "q")
("LSP"
(("g" lsp-find-definition "Definition")
("d" lsp-find-declaration "Declaration")
("r" lsp-find-references "References")
("t" lsp-find-type-definition "Type Definition"))
"Peek"
(("D" lsp-ui-peek-find-definitions "Definitions")
("I" lsp-ui-peek-find-implementation "Implementations")
("R" lsp-ui-peek-find-references "References")
("S" lsp-ui-peek-find-workspace-symbol "Symbols"))
"LSP+"
(("u" lsp-ui-imenu "UI Menu")
("i" lsp-find-implementation "Implementations")
("h" lsp-treemacs-call-hierarchy "Hierarchy")
("E" lsp-treemacs-errors-list "Error List"))))
(major-mode-hydra-define+ python-mode nil
("Server"
(("l" python-lsp/body "LSP..."))
"Edit"
(("r" lsp-rename "Rename")
("=" lsp-format-region "Format"))
"Navigate"
(("A" lsp-workspace-folders-add "Add Folder")
("R" lsp-workspace-folders-remove "Remove Folder"))
"Docs"
(("D" lsp-describe-thing-at-point "Describe LSP Symbol")
("h" lsp-ui-doc-glance "Glance Help")
("H" lsp-document-highlight "Highlight"))))
(call-interactively 'lsp))
#+begin_src emacs-lisp :tangle no
(use-package lsp-mode (use-package lsp-mode
;; :hook ((python-mode . lsp)))
:config :config
(ha-local-leader :keymaps 'lsp-mode-map (major-mode-hydra-define+ python-mode (:quit-key "q")
"0" '("treemacs" . lsp-treemacs-symbols) ("Server"
(("L" ha-setup-python-lsp "Start LSP Server")))))
"/" '("complete" . completion-at-point) ;; ----------------------------------------------------------------------
"k" '("check code" . python-check) ;; Missing Symbols to be integrated?
"]" '("shift left" . python-indent-shift-left) ;; "0" '("treemacs" . lsp-treemacs-symbols)
"[" '("shift right" . python-indent-shift-right) ;; "/" '("complete" . completion-at-point)
;; "k" '("check code" . python-check)
;; actions ;; "Fb" '("un-blacklist folder" . lsp-workspace-blacklist-remove)
"a" '(:ignore t :which-key "code actions") ;; "hs" '("signature help" . lsp-signature-activate)
"aa" '("code actions" . lsp-execute-code-action) ;; "tT" '("toggle treemacs integration" . lsp-treemacs-sync-mode)
"ah" '("highlight symbol" . lsp-document-highlight) ;; "ta" '("toggle modeline code actions" . lsp-modeline-code-actions-mode)
"al" '("lens" . lsp-avy-lens) ;; "th" '("toggle highlighting" . lsp-toggle-symbol-highlight)
;; "tl" '("toggle lenses" . lsp-lens-mode)
;; formatting ;; "ts" '("toggle signature" . lsp-toggle-signature-auto-activate)
"=" '(:ignore t :which-key "formatting")
"==" '("format buffer" . lsp-format-buffer)
"=r" '("format region" . lsp-format-region)
"e" '(:ignore t :which-key "eval")
"e P" '("run python" . run-python)
"e e" '("send statement" . python-shell-send-statement)
"e b" '("send buffer" . python-shell-send-buffer)
"e f" '("send defun" . python-shell-send-defun)
"e F" '("send file" . python-shell-send-file)
"e r" '("send region" . python-shell-send-region)
"e ;" '("expression" . python-shell-send-string)
"e p" '("switch-to-shell" . python-shell-switch-to-shell)
;; folders
"F" '(:ignore t :which-key "folders")
"Fa" '("add folder" . lsp-workspace-folders-add)
"Fb" '("un-blacklist folder" . lsp-workspace-blacklist-remove)
"Fr" '("remove folder" . lsp-workspace-folders-remove)
;; goto
"g" '(:ignore t :which-key "goto")
"ga" '("find symbol in workspace" . xref-find-apropos)
"gd" '("find declarations" . lsp-find-declaration)
"ge" '("show errors" . lsp-treemacs-errors-list)
"gg" '("find definitions" . lsp-find-definition)
"gh" '("call hierarchy" . lsp-treemacs-call-hierarchy)
"gi" '("find implementations" . lsp-find-implementation)
"gm" '("imenu" . lsp-ui-imenu)
"gr" '("find references" . lsp-find-references)
"gt" '("find type definition" . lsp-find-type-definition)
;; peeks
"G" '(:ignore t :which-key "peek")
"Gg" '("peek definitions" . lsp-ui-peek-find-definitions)
"Gi" '("peek implementations" . lsp-ui-peek-find-implementation)
"Gr" '("peek references" . lsp-ui-peek-find-references)
"Gs" '("peek workspace symbol" . lsp-ui-peek-find-workspace-symbol)
;; help
"h" '(:ignore t :which-key "help")
"he" '("eldoc" . python-eldoc-at-point)
"hg" '("glance symbol" . lsp-ui-doc-glance)
"hh" '("describe symbol at point" . lsp-describe-thing-at-point)
"gH" '("describe python symbol" . python-describe-at-point)
"hs" '("signature help" . lsp-signature-activate)
"i" 'imenu
;; refactoring
"r" '(:ignore t :which-key "refactor")
"ro" '("organize imports" . lsp-organize-imports)
"rr" '("rename" . lsp-rename)
;; toggles
"t" '(:ignore t :which-key "toggle")
"tD" '("toggle modeline diagnostics" . lsp-modeline-diagnostics-mode)
"tL" '("toggle log io" . lsp-toggle-trace-io)
"tS" '("toggle sideline" . lsp-ui-sideline-mode)
"tT" '("toggle treemacs integration" . lsp-treemacs-sync-mode)
"ta" '("toggle modeline code actions" . lsp-modeline-code-actions-mode)
"tb" '("toggle breadcrumb" . lsp-headerline-breadcrumb-mode)
"td" '("toggle documentation popup" . lsp-ui-doc-mode)
"tf" '("toggle on type formatting" . lsp-toggle-on-type-formatting)
"th" '("toggle highlighting" . lsp-toggle-symbol-highlight)
"tl" '("toggle lenses" . lsp-lens-mode)
"ts" '("toggle signature" . lsp-toggle-signature-auto-activate)
;; workspaces
"w" '(:ignore t :which-key "workspaces")
"wD" '("disconnect" . lsp-disconnect)
"wd" '("describe session" . lsp-describe-session)
"wq" '("shutdown server" . lsp-workspace-shutdown)
"wr" '("restart server" . lsp-workspace-restart)
"ws" '("start server" . lsp)))
#+end_src #+end_src
* Project Configuration * Project Configuration
I work with a lot of projects with my team where I need to /configure/ the project such that LSP and my Emacs setup works. Let's suppose I could point a function at a project directory, and have it /set it up/: I work with a lot of projects with my team where I need to /configure/ the project such that LSP and my Emacs setup works. Let's suppose I could point a function at a project directory, and have it /set it up/:
@ -290,6 +332,7 @@ I work with a lot of projects with my team where I need to /configure/ the proje
(insert "pylsp-rope\n")) (insert "pylsp-rope\n"))
(shell-command "pip install -r requirements-dev.txt"))) (shell-command "pip install -r requirements-dev.txt")))
#+end_src #+end_src
* Major Mode Hydra
* Technical Artifacts :noexport: * Technical Artifacts :noexport:
Let's =provide= a name so we can =require= this file: Let's =provide= a name so we can =require= this file:

View file

@ -1157,7 +1157,8 @@ And then we can use it. For some reason, the =pymarkdown= (which I need to use f
(use-package markdown-mode (use-package markdown-mode
:after flycheck :after flycheck
:config :config
(setq flycheck-markdown-pymarkdown-config ".pymarkdown.yml") (setq flycheck-markdown-pymarkdown-config
(expand-file-name ".pymarkdown.yml" (getenv "HOME")))
(flycheck-may-enable-checker 'markdown-pymarkdown)) (flycheck-may-enable-checker 'markdown-pymarkdown))
#+end_src #+end_src

View file

@ -162,6 +162,7 @@ While not as fast as [[https://github.com/akermu/emacs-libvterm][vterm]], the [[
("terminfo/65" "terminfo/65/*") ("terminfo/65" "terminfo/65/*")
("integration" "integration/*") ("integration" "integration/*")
(:exclude ".dir-locals.el" "*-tests.el"))) (:exclude ".dir-locals.el" "*-tests.el")))
:commands (eat eat-make eat-project)
:bind (:map eat-semi-char-mode-map :bind (:map eat-semi-char-mode-map
("C-c C-t" . ha-eat-narrow-to-shell-prompt-dwim)) ("C-c C-t" . ha-eat-narrow-to-shell-prompt-dwim))
:config :config
@ -475,7 +476,7 @@ We'll give =openstack= CLI a =--format json= option to make it easier for parsin
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defun ha-ssh-overcloud-query-for-hosts () (defun ha-ssh-overcloud-query-for-hosts ()
"If the overcloud cache hasn't be populated, ask the user if we want to run the command." "If the overcloud cache hasn't be populated, ask the user if we want to run the command."
(when (not ha-ssh-favorite-hostnames) (unless ha-ssh-favorite-hostnames
(when (y-or-n-p "Cache of Overcloud hosts aren't populated. Retrieve hosts?") (when (y-or-n-p "Cache of Overcloud hosts aren't populated. Retrieve hosts?")
(call-interactively 'ha-ssh-overcloud-cache-populate)))) (call-interactively 'ha-ssh-overcloud-cache-populate))))
@ -488,7 +489,7 @@ We'll do the work of getting the /server list/ with this function:
(defun ha-ssh-overcloud-cache-populate (cluster) (defun ha-ssh-overcloud-cache-populate (cluster)
"Given an `os-cloud' entry, stores all available hostnames. "Given an `os-cloud' entry, stores all available hostnames.
Calls `ha-ssh-add-favorite-host' for each host found." Calls `ha-ssh-add-favorite-host' for each host found."
(interactive (list (completing-read "Cluster: " '(devprod501 devprod502)))) (interactive (list (completing-read "Cluster: " '(devprod501 devprod502 devprod502-yawxway))))
(message "Calling the `openstack' command...this will take a while. Grab a coffee, eh?") (message "Calling the `openstack' command...this will take a while. Grab a coffee, eh?")
(let* ((command (format "openstack --os-cloud %s server list --no-name-lookup -f json" cluster)) (let* ((command (format "openstack --os-cloud %s server list --no-name-lookup -f json" cluster))
(json-data (thread-last command (json-data (thread-last command
@ -496,10 +497,12 @@ We'll do the work of getting the /server list/ with this function:
(json-read-from-string)))) (json-read-from-string))))
(dolist (entry (seq--into-list json-data)) (dolist (entry (seq--into-list json-data))
(ha-ssh-add-favorite-host (alist-get 'Name entry) (ha-ssh-add-favorite-host (alist-get 'Name entry)
(or
(thread-last entry (thread-last entry
(alist-get 'Networks) (alist-get 'Networks)
(alist-get 'cedev13) (alist-get 'cedev13)
(seq-first)))) (seq-first))
(alist-get 'Name entry))))
(message "Call to `openstack' complete. Found %d hosts." (length json-data)))) (message "Call to `openstack' complete. Found %d hosts." (length json-data))))
#+end_src #+end_src
@ -554,3 +557,7 @@ Before you can build this on a new system, make sure that you put the cursor ove
#+options: num:nil toc:t todo:nil tasks:nil tags:nil date:nil #+options: num:nil toc:t todo:nil tasks:nil tags:nil date:nil
#+options: skip:nil author:nil email:nil creator:nil timestamp:nil #+options: skip:nil author:nil email:nil creator:nil timestamp:nil
#+infojs_opt: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js #+infojs_opt: view:nil toc:t ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
# Local Variables:
# eval: (org-next-visible-heading 1)
# End: