diff --git a/flake.lock b/flake.lock index 4580e78..02b0a8c 100644 --- a/flake.lock +++ b/flake.lock @@ -44,11 +44,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1709126324, - "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { diff --git a/lisp/fg42.el b/lisp/fg42.el index fba10d2..1373a93 100644 --- a/lisp/fg42.el +++ b/lisp/fg42.el @@ -65,6 +65,22 @@ (setq fg42/initialized t)))) +(defun fg42/initialize-v4 () + "Initialize FG42 after the Emacs window is rendered by loading the user init file." + ;; (fg42/-startup-optimization) + (require 'fg42/editor) + + (when (file-exists-p user-init-file) + (load user-init-file)) + + (add-hook 'emacs-startup-hook + (lambda () + (run-hooks 'fg42/after-init-hook) + (run-hooks 'fg42/after-initializing-theme-hook) + (run-hooks 'fg42/ui-hook) + (setq fg42/initialized t)))) + + (defun fg42/-startup-optimization () "Optimized FG42 startup." ;; by setting gc threshold to the largest number diff --git a/lisp/fg42/cubes/editor.el b/lisp/fg42/cubes/editor.el index 48f3460..d3e4c9d 100644 --- a/lisp/fg42/cubes/editor.el +++ b/lisp/fg42/cubes/editor.el @@ -88,6 +88,11 @@ contextual information." (global-set-key (kbd "C-h x") #'helpful-command) (global-set-key (kbd "C-c C-d") #'helpful-at-point)) +(->cube envrc + "Activate direnv whenever encounter a `.envrc' file" + :init + (require 'envrc) + (envrc-global-mode)) (defcube fg42/pinentry-cube "Pinentry cube with setup the =pinentry= program to be used within FG42." diff --git a/lisp/fg42/cubes/elisp.el b/lisp/fg42/cubes/elisp.el index 5c30e30..1f3d5d8 100644 --- a/lisp/fg42/cubes/elisp.el +++ b/lisp/fg42/cubes/elisp.el @@ -24,8 +24,6 @@ (require 'fpkg) (require 'fg42/cube) - - (defcube fg42/elisp-cube "Elisp cube" :title "fg42/cubes/fg42/elisp-cube.org" diff --git a/lisp/fg42/deps.el b/lisp/fg42/deps.el index b6e006c..5999161 100644 --- a/lisp/fg42/deps.el +++ b/lisp/fg42/deps.el @@ -94,8 +94,6 @@ org-super-agenda org-ql ctrlf - selectrum-prescient - selectrum badwolf-theme ace-window avy @@ -119,7 +117,10 @@ exwm verilog-ext verilog-mode - pkg-info) + pkg-info + envrc + vertico + orderless) (provide 'fg42/deps) ;;; deps.el ends here diff --git a/lisp/fg42/direnv.el b/lisp/fg42/direnv.el new file mode 100644 index 0000000..23dd93a --- /dev/null +++ b/lisp/fg42/direnv.el @@ -0,0 +1,33 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2010-2024 Sameer Rahmani +;; +;; Author: Sameer Rahmani +;; Keywords: lisp fg42 IDE package manager +;; Version: 1.0.0 +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;; This file contains all the dependencies of FG42 v4 in no particular order. +;; Whether we use a package during runtime or not we will build everything +;; and decide what to load at runtime. +;; +;; We fetch these dependencies using Nix via the emacs-overlay. +;; +;;; Code: + + +(provide 'fg42/direnv) +;;; direnv.el ends here diff --git a/lisp/fg42/editor.el b/lisp/fg42/editor.el new file mode 100644 index 0000000..d8259ca --- /dev/null +++ b/lisp/fg42/editor.el @@ -0,0 +1,248 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; URL: https://devheroes.codes/FG42/FG42 +;; Version: 3.0.0 +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;;; Code: +(require 'server) + +(eval-when-compile + (require 'fpkg)) + +;; (require 'fg42/utils) +;; (require 'fg42/modeline) +;; (require 'fg42/cubes/modeline) +;; (require 'fg42/themes) +;; (require 'fg42/project) + + +(defvar fg42/font '("Fira Mono" 12)) + + +(defun fg42/setup-font () + "Set the default font of `FG42' to FONT-NAME and FONT-SIZE." + (let ((name (car fg42/font)) + (size (cadr fg42/font))) + (add-to-list 'default-frame-alist + (cons 'font (format "%s-%d" name size))) + + (set-face-attribute 'default t :font name))) + + +(defun fg42/setup-editor () + "Setup the overall functionality of FG42." + (use! origami + "A text folding minor mode for Emacs." + :bind + (("C-c TAB" . origami-toggle-node)) + :config + (global-origami-mode t)) + + (use! which-key + "which-key is a minor mode for Emacs that displays the key bindings following +your currently entered incomplete command (a prefix) in a popup. For example, +after enabling the minor mode if you enter ~C-x~ and wait for the default of +1 second the minibuffer will expand with all of the available key bindings +that follow ~C-x~ (or as many as space allows given your settings). +This includes prefixes like ~C-x 8~ which are shown in a different face." + :init + (require 'which-key) + :config + (which-key-setup-side-window-bottom) + (which-key-mode)) + + (use! helpful + "Helpful is an alternative to the built-in Emacs help that provides much more +contextual information." + :init + (require 'helpful) + :config + (global-set-key (kbd "C-h f") #'helpful-callable) + (global-set-key (kbd "C-h v") #'helpful-variable) + (global-set-key (kbd "C-h k") #'helpful-key) + (global-set-key (kbd "C-h x") #'helpful-command) + (global-set-key (kbd "C-c C-d") #'helpful-at-point)) + + (use! envrc + "Activate direnv whenever encounter a `.envrc' file" + :init + (require 'envrc) + (envrc-global-mode)) + + (use! pinentry + "Pinentry cube with setup the =pinentry= program to be used within FG42." + :init + (progn + (require 'pinentry) + (setq epa-pinentry-mode 'loopback) + (pinentry-start))) + + (use! imenu-list + "his Emacs minor-mode creates an automatically updated buffer + called `Ilist' that is populated with the current buffer's imenu entries. + The `Ilist' buffer is typically shown as a sidebar (Emacs vertically splits the window)." + :init + (global-set-key (kbd "C-'") #'imenu-list-smart-toggle)) + + (use! emojify + "Adds support for emojis to `FG42'" + :hook (after-init . global-emojify-mode)) + + (use! discover + "Adds support for the discover.el `https://github.com/mickeynp/discover.el'.") + + (use! exec-path-from-shell + "This package fixes the =exec-path-from-shell= issue on MacOS." + :init + (require 'exec-path-from-shell) + (when (memq window-system '(mac ns x)) + (exec-path-from-shell-initialize))) + + (use! hl-line + "Highlights the current line." + :init + (require 'hl-line) + (global-hl-line-mode)) + + (use! rainbow-delimiters + "rainbow-delimiters is a =rainbow parentheses= like mode which highlights delimiters +such as parentheses, brackets or braces according to their depth. Each successive level +is highlighted in a different color. This makes it easy to spot matching delimiters, +orient yourself in the code, and tell which statements are at a given depth." + ;; It doesn't work due to a problem/conflict in rainbow-delimiters + ;; But we use it any way they might fix it + :hook (prog-mode . rainbow-delimiters-mode)) + + (use! paredit + "`paredit' is a minor mode for performing structured editing of S-expression +data. The typical example of this would be Lisp or Scheme source code." + :hook ((emacs-lisp-mode . paredit-mode) + (clojure-mode . paredit-mode) + (scheme-mode . paredit-mode))) + + (add-hook 'fg42/after-initializing-theme-hook + (lambda () + (set-default 'cursor-type 'box) + (set-cursor-color "#eeeeec"))) + + (use! avy + "This cube controls the different aspect of buffer navigation" + :bind ("M-1" . avy-goto-word-1)) + + (use! ace-window + "This cube controls the different aspect of buffer navigation" + :bind ("C-" . ace-window)) + + (fg42/setup-font) + + (use! vertico + "Vertico provides a performant and minimalistic vertical completion UI + based on the default completion system. The focus of Vertico is to provide + a UI which behaves correctly under all circumstances." + :config + (vertico-mode) + (setq vertico-count 10) + (setq vertico-cycle t)) + + + (use! orderless + "This package provides an orderless completion style that divides the +pattern into space-separated components, and matches candidates that +match all of the components in any order." + :init + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles partial-completion))))) + + (use! savehist + "Persist history over Emacs restarts. Vertico sorts by history position." + :init + (savehist-mode)) + + + (when-not-wm + (use! ctrlf + "Single buffer text search." + :config + (ctrlf-mode +1))) + + (use! all-the-icons + "A utility package to collect various Icon Fonts and propertize them within +Emacs.") + + ;; In the following section we're setting some default behavior of FG42. + ;; Most of these configuration are opiniated and I think most of people + ;; shared the same opinion or don't care at all. + + ;; Remove splash screen + (setq inhibit-splash-screen t) + ;; scratch should be scratch + (setq initial-scratch-message nil) + ;; Don't allow tab as indent + (setq-default indent-tabs-mode nil) + ;; Default indent width + (setq tab-width 2) + ;; Share the clipboard with X applications + (setq x-select-enable-clipboard t) + ;; Automatically removed excess backups of the file + (setq delete-old-versions t) + ;; Emacs 28 and newer: Hide commands in M-x which do not work in the current + ;; mode. Vertico commands are hidden in normal buffers. This setting is + ;; useful beyond Vertico. + (setq read-extended-command-predicate #'command-completion-default-include-p) + + ;; Support opening new minibuffers from inside existing minibuffers. + (setq enable-recursive-minibuffers t) + ;; Global configurations + (tool-bar-mode -1) + + (menu-bar-mode -1) + (when (display-graphic-p) + (scroll-bar-mode -1)) + + (column-number-mode t) + (show-paren-mode t) + (electric-pair-mode 1) + + ;; Rectangular select + (cua-selection-mode t) + + ;; Yank the region on type + (delete-selection-mode 1) + + (defalias 'yes-or-no-p 'y-or-n-p) + + ;; Hooks --- + ;; Deletel extra trailing white spaces on save + (add-hook 'before-save-hook 'delete-trailing-whitespace) + + ;; Enable rainbow-delimiters for programming + (add-hook 'prog-mode-hook #'rainbow-delimiters-mode) + + ;; With this section we will have two emacs server running + ;; this way we can interact with the wm via emacsclient as well + (when (not (server-running-p)) + (when-wm + (setq server-name "fg42-wm")) + (server-start))) + + +(provide 'fg42/editor) +;;; editor.el ends here diff --git a/lisp/fg42/elisp.el b/lisp/fg42/elisp.el new file mode 100644 index 0000000..b7bbd13 --- /dev/null +++ b/lisp/fg42/elisp.el @@ -0,0 +1,38 @@ +;;; ElispCube --- The elisp cube for FG42 -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; URL: https://devheroes.codes/FG42/FG42 +;; Version: 3.0.0 +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;;; Code: +(require 'fpkg) + + +(defun fg42/setup-elisp () + "Setup the Emacs Lisp development environment." + (use! eros + :init + (require 'eros) + (eros-mode)) + + (add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode)) + + +(provide 'fg42/cubes/elisp) +;;; elisp.el ends here diff --git a/lisp/fg42/flags.el b/lisp/fg42/flags.el index ffa585c..cef7f35 100644 --- a/lisp/fg42/flags.el +++ b/lisp/fg42/flags.el @@ -40,7 +40,7 @@ Flags are defined using the \\[defflag] through out the source code. To see a list of available flags use \\[fg42/show-all-flags] and to see the documentation of each flag simply use \\[describe-flag]." :group 'fg42 - :package-version '(FG42 . "3.x") + :package-version '(FG42 . "4.x") :type '(symbol) :tag "FG42 Flags") diff --git a/lisp/fg42/init.el b/lisp/fg42/init.el index d1f7cdd..c8b9e8e 100644 --- a/lisp/fg42/init.el +++ b/lisp/fg42/init.el @@ -25,23 +25,41 @@ (when (string= (getenv "FG42_DEBUG") "1") (setq debug-on-error t)) + (eval-when-compile (defvar package-archives) (defvar use-package-ensure-function)) -(defvar fg42-use-nix (or (getenv "FG42_USE_NIX") nil)) + +(defgroup fg42 nil + "Customize your FG42 instance via this group of configurations.") + +(defvar fg42/disabled-features nil + "List of features to disable.") + +(defvar fg42/after-init-hook nil + "The hook tha runs when FG42 finished running the user configuration.") + +(defvar fg42/debug-p nil + "The hook tha runs when FG42 finished running the user configuration.") + +(defvar fg42-home (or (getenv "FG42_HOME") "~/.fg42") + "The pass to fg42-home.") + +(defvar fg42-tmp (make-temp-file "fg42-" t)) + + + +(add-to-list 'load-path (concat (getenv "FG42_HOME") "/lisp")) ;; (when fg42-use-nix ;; (require 'site-start)) -(add-to-list 'load-path (concat (getenv "FG42_HOME") "/lisp")) ;; Prevent package.el to install anything at startup (setq package-enable-at-startup nil) (setq package-archives nil) -(when fg42-use-nix - (setq use-package-ensure-function 'ignore)) - +(setq use-package-ensure-function 'ignore) (setq tab-width 2) (let ((emacsd (or (getenv "FG42_EMACSD") (format "%s/emacs.d" (getenv "FG42_HOME"))))) @@ -49,16 +67,18 @@ (setq user-emacs-directory emacsd) (setq user-init-file (or (getenv "FG42_CONFIG_FILE") - (format "%s/.fg42.el" + (format "%s/.fg42.v4.el" (getenv "HOME"))))) + ;; Load the customization file. In FG42 it is different than ;; the default `user-init-file' (if (file-exists-p custom-file) (load custom-file)) + (require 'fg42) -(fg42/initialize) +(fg42/initialize-v4) (provide 'fg42/init) ;;; init.el ends here diff --git a/lisp/fg42/langs/#cpp.el# b/lisp/fg42/langs/#cpp.el# new file mode 100644 index 0000000..35a6c25 --- /dev/null +++ b/lisp/fg42/langs/#cpp.el# @@ -0,0 +1,63 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; URL: https://devheroes.codes/FG42/FG42 +;; Version: 3.0.0 +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;;; Code: +(require 'fpkg) +(require 'fg42/utils) +(require 'fg42/language-servers) + +;; (use! cmake-ts-mode) +(use! eldoc-cmake + :hook (cmake-ts-mode . eldoc-cmake-enable)) + + +(use! ninja-mode + "This cube enables Ninja integration with FG42. For more info checkout: +https://github.com/ninja-build/ninja/blob/master/misc/ninja-mode.el") + + +(use! c++-ts-mode + "C++ setup. We're using treesitter version of c++ mode." + :mode ("\\.h\\'" . c++-ts-mode) + :mode ("\\.hpp\\'" . c++-ts-mode) + :mode ("\\.cpp\\'" . c++-ts-mode) + + :hook ((c++-ts-mode-hook . fg42/ls-run) + (c++-ts-mode-hook . fg42/cpp-autocomplete)) + ) + + +(add-hook 'c++-ts-mode-hook (setq-local company-backends + '((company-dabbrev company-ispell :separate) + company-files)) + (lambda () + + (require 'company-capf) + (require 'company-box) + + + (setq company-backends + '((company-capf + company-keywords))))) + +(provide 'fg42/langs/cpp) +;;; cpp.el ends here diff --git a/lisp/fg42/langs/.#cpp.el b/lisp/fg42/langs/.#cpp.el new file mode 120000 index 0000000..a7fda75 --- /dev/null +++ b/lisp/fg42/langs/.#cpp.el @@ -0,0 +1 @@ +lxsameer@majin.3221106:1710087423 \ No newline at end of file diff --git a/lisp/fg42/langs/cpp.el b/lisp/fg42/langs/cpp.el new file mode 100644 index 0000000..3f8aafd --- /dev/null +++ b/lisp/fg42/langs/cpp.el @@ -0,0 +1,63 @@ +;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*- +;; +;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors +;; +;; Author: Sameer Rahmani +;; URL: https://devheroes.codes/FG42/FG42 +;; Version: 3.0.0 +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;;; Code: +(require 'fpkg) +(require 'fg42/utils) +(require 'fg42/language-servers) + +;; (use! cmake-ts-mode) +(use! eldoc-cmake + :hook (cmake-ts-mode . eldoc-cmake-enable)) + + +(use! ninja-mode + "This cube enables Ninja integration with FG42. For more info checkout: +https://github.com/ninja-build/ninja/blob/master/misc/ninja-mode.el") + + +(use! c++-ts-mode + "C++ setup. We're using treesitter version of c++ mode." + :mode ("\\.h\\'" . c++-ts-mode) + :mode ("\\.hpp\\'" . c++-ts-mode) + :mode ("\\.cpp\\'" . c++-ts-mode) + + :hook ((c++-ts-mode-hook . fg42/ls-run) + (c++-ts-mode-hook . fg42/cpp-autocomplete)) + ) + + +(add-hook 'c++-ts-mode-hook (setq-local company-backends + '((company-dabbrev company-ispell :separate) + company-files)) + (lambda () + + (require 'company-capf) + (require 'company-box) + + + (setq company-backends + '((company-capf + company-keywords))))) + +(provide 'fg42/langs/cpp) +;;; cpp.el ends here diff --git a/lisp/fg42/shell.el b/lisp/fg42/shell.el index 4461ef1..d4cf154 100644 --- a/lisp/fg42/shell.el +++ b/lisp/fg42/shell.el @@ -111,6 +111,5 @@ OPTS: ;;(kill-process process) )))))) - (provide 'fg42/shell) -;;; ssh.el ends here +;;; shell.el ends here diff --git a/lisp/fpkg.el b/lisp/fpkg.el index c14ccbf..0bc5bf6 100644 --- a/lisp/fpkg.el +++ b/lisp/fpkg.el @@ -24,54 +24,46 @@ ;; Simple package manager for FG42 ;; ;;; Code: - (require 'map) (defvar package-names ()) (eval-when-compile - (defvar fg42-use-nix)) ;; defined in fg42-config.el - -(defun inject-straight (args) - "Inject `:straight t' to ARGS it the key was missing." - (if fg42-use-nix - ;; We don't use straight with nix - (map-delete args :straight) - (if (member :straight args) - args - (append args '(:straight t))))) + (defvar fg42/disabled-features '()) + (require 'use-package)) (defun inject-params (args) "Inject required `use-package' params to ARGS if the key is missing." - (if fg42-use-nix - (append '(:ensure nil) args) - ;; (if (member :defer args) - ;; args - ;; (append args '(:defer t))) - args)) + ;; (if (member :defer args) + ;; (append '(:ensure nil) args) + (append args '(:ensure nil))) (defmacro fpkg/use (pkg &rest details) "Install the given package DETAILS PKG via `use-package' and straight." (declare (indent defun)) (if (and (listp details) (< 0 (length details))) - (let ((p (inject-straight (inject-params details)))) - `(progn - (use-package ,pkg ,@p))) + (let ((p (inject-params details))) + `(progn + (use-package ,pkg ,@p))) `(progn (use-package ,pkg :defer t :ensure nil)))) -(defmacro fpkg/require (pkg) - "Work like require but make sure that PKG is installed first." +(defmacro use! (pkg docs &rest details) + "Loading the given package DETAILS PKG via `use-package'. + +DOCS is the documentation of the package." + (declare (indent defun) (doc-string 2)) + + (when (not (stringp docs)) + (error "Missing docstring for '%s' package" pkg)) + + (let ((disabled (or (member pkg fg42/disabled-features) nil))) + (when (not disabled) + `(use-package ,pkg ,@details)))) - (let ((pkg-name (intern (symbol-name `,(cadr pkg))))) - (if fg42-use-nix - `(require ,pkg) - `(fpkg/use ,pkg-name - :init - (require ,pkg))))) (provide 'fpkg) ;;; fpkg.el ends here diff --git a/nix/fg42.nix b/nix/fg42.nix index 5659ae1..b13ae86 100644 --- a/nix/fg42.nix +++ b/nix/fg42.nix @@ -23,6 +23,9 @@ ourPackages, writeText, symlinkJoin, + direnv, + nix, + nil, # nix lsp server # python deps python311, @@ -43,8 +46,8 @@ tree-sitter, supportWM ? true, - xorg, - + xorg, + supportPython ? true, supportVerilog ? true, @@ -71,6 +74,9 @@ let git ltex-ls tree-sitter + direnv + nix + nil ] ++ (lib.optional supportPython [ python311 # Python deps