Compare commits

..

No commits in common. "b23f15a670d4805b0b52453f84bc659eb4616c76" and "a1118e0c2e20ce60d80cdcf138f22a0adee871fb" have entirely different histories.

5 changed files with 78 additions and 166 deletions

View file

@ -485,9 +485,6 @@ These interactive functions scroll the “notes” in the other window in anothe
#+END_SRC
* New Demonstration
:LOGBOOK:
CLOCK: [2025-03-26 Wed 09:04]--[2025-03-26 Wed 09:29] => 0:25
:END:
Instead of executing a sequence of demonstration steps, demonstrations key on “state”, that is, the active buffer or major-mode, or the heading of an Org file, etc. I described the [[https://howardism.org/Technical/Emacs/demonstrations-part-two.html][guts of writing this code]], but we bind a key to calling =ha-demo-step= with a list of /state matchers/ to functions to call when matched. For instance:
#+BEGIN_SRC emacs-lisp :tangle no :eval no
@ -847,8 +844,8 @@ All options? Should I use Common Lisps =cl-defun= for the keyword parameters?
(switch-to-buffer filename))
(if image-minor-mode
(image-transform-fit-to-window)
(goto-char (point-min)))
(goto-char (point-min))
(image-transform-fit-to-window))
(ha-demo-set-side-window :size size :modeline modeline
:cursor cursor)
@ -987,18 +984,18 @@ And we can open the shell in a window:
(when command
(sit-for 1)
(ha-shell-send command))
(ha-shell-send command ha-demo-shell-dir))
(when (and focus (eq focus 'presentation))
(pop-to-buffer orig-buf))))
(defun ha-demo-shell-send (command)
"Send COMMAND to the currently opened shell, `ha-demo-shell'."
(ha-shell-send command))
(ha-shell-send command ha-demo-shell-dir))
(defun ha-demo-shell-quit ()
"Close the window associated with a shell."
(ha-shell-send "exit")
(ha-shell-send "exit" ha-demo-shell-dir)
(delete-other-windows))
#+END_SRC

View file

@ -66,7 +66,7 @@ The Escape key act like ~C-g~ and always go back to normal mode?
;; (global-set-key (kbd "<escape>") 'keyboard-escape-quit)
;; Let's connect my major-mode-hydra to a global keybinding:
(evil-define-key '(normal visual) 'global "," 'major-mode-hydra)
(evil-define-key 'normal 'global "," 'major-mode-hydra)
(evil-mode))
#+end_src

View file

@ -3,8 +3,6 @@
#+date: 2021-11-16
#+tags: emacs python programming
import re
A literate programming file for configuring Python.
#+begin_src emacs-lisp :exports none
@ -39,111 +37,80 @@ While Emacs supplies a Python editing environment, well still use =use-packag
(setq python-indent-guess-indent-offset-verbose nil
flycheck-flake8-maximum-line-length 120)
:config
(setq python-shell-interpreter (or (executable-find "ipython") "python"))
(when (and (executable-find "ipython")
(string= python-shell-interpreter "ipython"))
(setq python-shell-interpreter "ipython"))
(flycheck-add-next-checker 'python-pylint 'python-pycompile 'append))
#+end_src
** Keybindings
Instead of memorizing all the Emacs-specific keybindings, we use [[https://github.com/jerrypnz/major-mode-hydra.el][major-mode-hydra]] defined for =python-mode=:
#+BEGIN_SRC emacs-lisp
(use-package major-mode-hydra
:after python
: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"))
(defvar ha-python-refactor-title (font-icons 'faicon "recycle" :title "Python Refactoring"))
(pretty-hydra-define python-evaluate (:color blue :quit-key "C-g"
: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" elpy-shell-send-region-or-buffer "Region"))))
(pretty-hydra-define python-refactor (:color blue :quit-key "C-g"
:title ha-python-refactor-title)
("Simple"
(("r" iedit-mode "Rename"))
"Imports"
(("A" python-add-import "Add Import")
("a" python-import-symbol-at-point "Import Symbol")
("F" python-fix-imports "Fix Imports")
("S" python-sort-imports "Sort Imports"))))
(pretty-hydra-define python-goto (:color pink :quit-key "C-g"
:title ha-python-goto-title)
("Statements"
(("s" xref-find-apropos "Find Symbol" :color blue)
("j" python-nav-forward-statement "Next")
("k" python-nav-backward-statement "Previous"))
"Functions"
(("F" imenu "Jump Function" :color blue)
("f" python-nav-forward-defun "Forward")
("d" python-nav-backward-defun "Backward")
("e" python-nav-end-of-defun "End of" :color blue))
"Blocks"
(("u" python-nav-up-list "Up" :color blue)
(">" python-nav-forward-block "Forward")
("<" python-nav-backward-block "Backward"))))
(major-mode-hydra-define python-mode (:quit-key "C-g" :color blue)
("Server"
(("S" run-python "Start Server")
("s" python-shell-switch-to-shell "Go to Server"))
"Edit"
(("r" python-refactor/body "Refactor...")
(">" 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
Sections below can add to this with =major-mode-hydra-define+=.
Note: Install the following packages /globally/ for Emacs:
Note: Install the following checks:
#+begin_src sh
pip install flake8 flake8-bugbear pylint pyright mypy pycompile black ruff ipython
pip install flake8 pylint pyright mypy pycompile
#+end_src
Or better yet, add those to the =requirements-dev.txt= file.
But certainly add those to each projects =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=:
iPython has a feature of [[https://ipython.readthedocs.io/en/stable/config/intro.html#python-configuration-files][loading code on startup]] /per profile/. First, create it with:
#+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"))
#+BEGIN_SRC sh
ipython profile create
#+END_SRC
(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"))))
Next, after reading David Vujics [[https://davidvujic.blogspot.com/2025/03/are-we-there-yet.html][Are We There Yet]] essay, I took a look at [[https://github.com/DavidVujic/my-emacs-config?tab=readme-ov-file#python-shell][his Python configuration]], and added the /auto reloading/ feature to the iPython /profile configuration/:
(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"))))
#+BEGIN_SRC python :tangle ~/.ipython/profile_default/ipython_config.py
c = get_config() #noqa
%load_ext autoreload
%autoreload 2
# c.InteractiveShellApp.extensions = ['autoreload']
# c.InteractiveShellApp.exec_lines = ['%autoreload 2']
#+END_SRC
(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
When you need a particular version of Python, use [[https://github.com/pyenv/pyenv][pyenv]] globally:
For a local virtual machine, put the following in your =.envrc= file:
#+begin_src conf
layout_python3
#+end_src
That is pretty slick and simple.
The old way, that we still use if you need a particular version of Python, is to install [[https://github.com/pyenv/pyenv][pyenv]] globally:
#+begin_src sh
pip install pyenv
pip install pyenv
#+end_src
And have this in your =.envrc= file for use with [[file:ha-programming.org::*Virtual Environments with direnv][direnv]]:
And have this in your =.envrc= file:
#+begin_src conf
use python 3.7.1
use python 3.7.1
#+end_src
Also, you need the following in your =~/.config/direnv/direnvrc= file (which I have):
@ -208,57 +175,7 @@ Your project's =.envrc= file would contain something like:
("Misc"
(("t" python-tests/body "Tests..."))))))
#+end_src
* Elpy
The [[https://elpy.readthedocs.io/en/latest/introduction.html][Elpy Project]] expands on the =python-mode=.
#+BEGIN_SRC emacs-lisp
(use-package elpy
:ensure t
:init
(elpy-enable))
#+END_SRC
Lets expand our =major-mode-hydra= with some extras:
#+begin_src emacs-lisp
(use-package major-mode-hydra
:after elpy
:config
(pretty-hydra-define python-evaluate (:color blue :quit-key "q"
:title ha-python-eval-title)
("Section"
(("F" elpy-shell-send-defun "Function")
("E" elpy-shell-send-statement "Statement")
(";" python-shell-send-string "Expression"))
"Entirety"
(("B" elpy-shell-send-buffer "Buffer")
("r" elpy-shell-send-region-or-buffer "region"))
"And Step..."
(("f" elpy-shell-send-defun-and-step "Function" :color pink)
("e" elpy-shell-send-statement-and-step "Statement" :color pink))))
(pretty-hydra-define+ python-refactor nil
("Elpy"
(("r" elpy-refactor-rename "Rename")
("i" elpy-refactor-inline "Inline var")
("v" elpy-refactor-extract-variable "To variable")
("f" elpy-refactor-extract-function "To function")
("a" elpy-refactor-mode "All..."))))
(major-mode-hydra-define+ python-mode (:quit-key "q" :color blue)
("Server"
(("s" elpy-shell-switch-to-shell "Go to Server")
("C" elpy-config "Config Elpy"))
"Edit"
(("f" elpy-black-fix-code "Fix/format code"))
"Docs"
(("d" elpy-eldoc-documentation "Describe Symbol")
("D" elpy-doc "Docs Symbol")))))
#+end_src
* LSP Integration of 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=):
#+begin_src conf :tangle no
@ -281,7 +198,7 @@ Each Python project's =requirements-dev.txt= file would reference the [[https://
stestr slowest
# ...
#+end_src
** Pyright
*** Pyright
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
pyright
@ -295,7 +212,7 @@ The [[https://github.com/emacs-lsp/lsp-pyright][pyright package]] works with LSP
:init (when (executable-find "python3")
(setq lsp-pyright-python-executable-cmd "python3")))
#+end_src
*** Keybindings
* 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 conditionally turn it on.
#+begin_src emacs-lisp

View file

@ -305,8 +305,8 @@ Now that Emacs can /host/ a Terminal shell, I would like to /programmatically/ s
#+begin_src emacs-lisp
(defun ha-shell-send (command &optional name)
"Send COMMAND to existing shell terminal based on DIRECTORY.
If you want to refer to another session, specify the correct NAME.
This is really useful for scripts and demonstrations."
If you want to refer to another session, specify the correct NAME.
This is really useful for scripts and demonstrations."
(unless name
(setq name ha-latest-ssh-window-name))
@ -314,16 +314,14 @@ Now that Emacs can /host/ a Terminal shell, I would like to /programmatically/ s
(pop-to-buffer name)
(goto-char (point-max))
(cond
((eq major-mode 'vterm-mode) (progn
(vterm-send-string command)
(vterm-send-return)))
((eq major-mode 'eat-mode) (eat-term-send-string
ha-eat-terminal (concat command "\n")))
(t (progn
(insert command)
(term-send-input))))))
(ha-shell-send "exit")
((eq major-mode 'vterm-mode) (progn
(vterm-send-string command)
(vterm-send-return)))
((eq major-mode 'eat-mode) (eat-term-send-string
ha-eat-terminal (concat command "\n")))
(t (progn
(insert command)
(term-send-input))))))
#+end_src
Let's have a quick way to bugger out of the terminal:

View file

@ -2,7 +2,7 @@
#+author: Howard X. Abrams
#+date: 2025-01-18
#+filetags: emacs hamacs
#+lastmod: [2025-03-21 Fri]
#+lastmod: [2025-03-03 Mon]
A literate programming file for a Comint-based MUD client.
@ -263,7 +263,7 @@ Command string to use, given a =world= with a connection type:
(cl-case (aref world 1)
(telnet (append (cons pud-telnet-path pud-cli-arguments)
(list host port)))
(ssh (append (cons pud-ssh-path pud-cli-arguments)
(ssh (append (cons pud-cli-filepath-ssh pud-cli-arguments)
(list "-p" port host)))
(t (error "Unsupported connection type")))))
#+END_SRC