Change the cube loading interface to postpone the operations to after emacs startup

This commit is contained in:
Sameer Rahmani 2023-06-10 20:47:55 +01:00
parent 76602edf1b
commit d65037f57f
Signed by: lxsameer
GPG Key ID: B0A4AF28AB9FD90B
9 changed files with 169 additions and 82 deletions

View File

@ -42,8 +42,8 @@
For more info checkout [[https://github.com/gregsexton/origami.el]]" For more info checkout [[https://github.com/gregsexton/origami.el]]"
(:title "Folding cube" (:title "Folding cube"
:flag folding :flag folding
:flag-default t) :flag-default t)
(fpkg/use origami (fpkg/use origami
:bind :bind
(("C-c TAB" . origami-toggle-node)) (("C-c TAB" . origami-toggle-node))
@ -90,8 +90,8 @@ contextual information."
(defcube fg42/pinentry-cube (defcube fg42/pinentry-cube
"Pinentry cube with setup the =pinentry= program to be used within FG42." "Pinentry cube with setup the =pinentry= program to be used within FG42."
(:title "Pinentry cube" (:title "Pinentry cube"
:flag pinentry :flag pinentry
:flag-default t) :flag-default t)
(fpkg/use pinentry (fpkg/use pinentry
:init :init
(progn (progn
@ -102,8 +102,8 @@ contextual information."
(defcube fg42/imenu-cube (defcube fg42/imenu-cube
"Imenu support" "Imenu support"
(:title "Imenu cube" (:title "Imenu cube"
:flag imenu :flag imenu
:flag-default t) :flag-default t)
(fpkg/use imenu-list (fpkg/use imenu-list
:init :init
(global-set-key (kbd "C-'") #'imenu-list-smart-toggle))) (global-set-key (kbd "C-'") #'imenu-list-smart-toggle)))
@ -112,16 +112,16 @@ contextual information."
(defcube fg42/alert-cube (defcube fg42/alert-cube
"alert support" "alert support"
(:title "Alert cube" (:title "Alert cube"
:flag alert :flag alert
:flag-default t) :flag-default t)
(fpkg/use alert)) (fpkg/use alert))
(defcube fg42/emojify-cube (defcube fg42/emojify-cube
"Adds support for emojis to *FG42*" "Adds support for emojis to *FG42*"
(:title "Emojify cube" (:title "Emojify cube"
:flag emoji :flag emoji
:flag-default t) :flag-default t)
(fpkg/use emojify (fpkg/use emojify
:hook (after-init . global-emojify-mode))) :hook (after-init . global-emojify-mode)))
@ -129,16 +129,16 @@ contextual information."
(defcube fg42/discover-cube (defcube fg42/discover-cube
"Adds support for the [[https://github.com/mickeynp/discover.el][discover]]" "Adds support for the [[https://github.com/mickeynp/discover.el][discover]]"
(:title "Discover cube" (:title "Discover cube"
:flag discover :flag discover
:flag-default t) :flag-default t)
(fpkg/use discover)) (fpkg/use discover))
(defcube fg42/exec-path-cube (defcube fg42/exec-path-cube
"This cube fixes the =exec-path-from-shell= issue on MacOS." "This cube fixes the =exec-path-from-shell= issue on MacOS."
(:title "Exec path cube" (:title "Exec path cube"
:flag exec-path-from-shell :flag exec-path-from-shell
:flag-default t) :flag-default t)
(fpkg/use exec-path-from-shell (fpkg/use exec-path-from-shell
:init :init
(when (memq window-system '(mac ns x)) (when (memq window-system '(mac ns x))
@ -148,8 +148,8 @@ contextual information."
(defcube fg42/hl-cube (defcube fg42/hl-cube
"This cube highlight the curret line." "This cube highlight the curret line."
(:title "Current line highlight cube" (:title "Current line highlight cube"
:flag hl-line :flag hl-line
:flag-default t) :flag-default t)
(require 'hl-line) (require 'hl-line)
(global-hl-line-mode)) (global-hl-line-mode))
@ -161,8 +161,8 @@ is highlighted in a different color. This makes it easy to spot matching delimit
orient yourself in the code, and tell which statements are at a given depth." orient yourself in the code, and tell which statements are at a given depth."
(:title "Rainbow Delimiters Cube" (:title "Rainbow Delimiters Cube"
:flag rainbow-delimiters :flag rainbow-delimiters
:flag-default t) :flag-default t)
(fpkg/use rainbow-delimiters (fpkg/use rainbow-delimiters
;; It doesn't work due to a problem/conflict in rainbow-delimiters ;; It doesn't work due to a problem/conflict in rainbow-delimiters
@ -175,8 +175,8 @@ orient yourself in the code, and tell which statements are at a given depth."
data. The typical example of this would be Lisp or Scheme source code." data. The typical example of this would be Lisp or Scheme source code."
(:title "Paredit Cube" (:title "Paredit Cube"
:flag paredit :flag paredit
:flag-default t) :flag-default t)
(fpkg/use paredit (fpkg/use paredit
:hook ((emacs-lisp-mode . paredit-mode) :hook ((emacs-lisp-mode . paredit-mode)
(clojure-mode . paredit-mode) (clojure-mode . paredit-mode)
@ -186,8 +186,8 @@ data. The typical example of this would be Lisp or Scheme source code."
(defcube fg42/cursor-cube (defcube fg42/cursor-cube
"This cube controls the shape of the cursor." "This cube controls the shape of the cursor."
(:title "Cursor cube" (:title "Cursor cube"
:flag cursor-type :flag cursor-type
:flag-default t) :flag-default t)
(let ((ctype (or (plist-get fg42/cursor-cube-params :type) 'box)) (let ((ctype (or (plist-get fg42/cursor-cube-params :type) 'box))
(ccolor (or (plist-get fg42/cursor-cube-params :color) "#aa0000"))) (ccolor (or (plist-get fg42/cursor-cube-params :color) "#aa0000")))
@ -199,8 +199,8 @@ data. The typical example of this would be Lisp or Scheme source code."
(defcube fg42/buffer-navigation-cube (defcube fg42/buffer-navigation-cube
"This cube controls the different aspect of buffer navigation" "This cube controls the different aspect of buffer navigation"
(:title "Buffer navigation cube" (:title "Buffer navigation cube"
:flag buffer-navigation :flag buffer-navigation
:flag-default t) :flag-default t)
(fpkg/use avy (fpkg/use avy
:bind ("M-1" . avy-goto-word-1))) :bind ("M-1" . avy-goto-word-1)))
@ -209,8 +209,8 @@ data. The typical example of this would be Lisp or Scheme source code."
(defcube fg42/window-navigation-cube (defcube fg42/window-navigation-cube
"This cube controls the different aspect of buffer navigation" "This cube controls the different aspect of buffer navigation"
(:title "Window navigation cube" (:title "Window navigation cube"
:flag window-navigation :flag window-navigation
:flag-default t) :flag-default t)
(fpkg/use ace-window (fpkg/use ace-window
:bind ("C-<tab>" . ace-window))) :bind ("C-<tab>" . ace-window)))
@ -219,8 +219,8 @@ data. The typical example of this would be Lisp or Scheme source code."
(defcube fg42/font-cube (defcube fg42/font-cube
"This cube controls the font configuration of *FG42*" "This cube controls the font configuration of *FG42*"
(:title "Font Cube" (:title "Font Cube"
:no-flag t :no-flag t
:flag-default t) :flag-default t)
(let ((font (or (plist-get fg42/font-cube-params :font-name) (let ((font (or (plist-get fg42/font-cube-params :font-name)
"Fira Mono")) "Fira Mono"))
(size (or (plist-get fg42/font-cube-params :font-size) (size (or (plist-get fg42/font-cube-params :font-size)
@ -233,25 +233,25 @@ data. The typical example of this would be Lisp or Scheme source code."
(set-face-attribute 'default t :font font)))) (set-face-attribute 'default t :font font))))
;TODO: Replace this cube with a `theme-cube' ;TODO: Replace this cube with a `theme-cube'
(defcube fg42/dracula-theme-cube (defcube fg42/dracula-theme-cube
"Replace this with a theme cube" "Replace this with a theme cube"
(:title "Dracula theme" (:title "Dracula theme"
:no-flag t) :no-flag t
:ui-hook (lambda ()
(fpkg/use dracula-theme (fpkg/use dracula-theme
:init :init
(fg42/setup-theme (fg42/setup-theme
(load-theme 'dracula t) (load-theme 'dracula t)
(custom-theme-set-faces (custom-theme-set-faces
'dracula 'dracula
'(match ((t (:background "#44475a")))) '(match ((t (:background "#44475a"))))
'(all-the-icons-lgreen ((t (:background "#bd93f9")))) '(all-the-icons-lgreen ((t (:background "#bd93f9"))))
'(all-the-icons-faicon ((t (:background "#bd93f9")))) '(all-the-icons-faicon ((t (:background "#bd93f9"))))
'(font-lock-comment-face ((t (:foreground "#8B9298")))) '(font-lock-comment-face ((t (:foreground "#8B9298"))))
'(font-lock-comment-delimiter-face ((t (:foreground "#5B6268"))))) '(font-lock-comment-delimiter-face ((t (:foreground "#5B6268")))))
(enable-theme 'dracula) (enable-theme 'dracula)
(set-face-attribute 'region nil :background "#888")))) (set-face-attribute 'region nil :background "#888"))))))
(defcube fg42/badwolf-theme-cube (defcube fg42/badwolf-theme-cube
"Badwolf theme cube. An Emacs port of Bad Wolf theme for Vim. "Badwolf theme cube. An Emacs port of Bad Wolf theme for Vim.
@ -272,8 +272,8 @@ https://emacsthemes.com/themes/badwolf-theme.html"
(defcube fg42/selectrum-cube (defcube fg42/selectrum-cube
"This cube adds support for `selectrum' to FG42" "This cube adds support for `selectrum' to FG42"
(:title "Selectrum cube" (:title "Selectrum cube"
:flag selectrum :flag selectrum
:flag-default t) :flag-default t)
(fpkg/use selectrum (fpkg/use selectrum
:defer nil :defer nil
:init :init
@ -297,7 +297,7 @@ https://emacsthemes.com/themes/badwolf-theme.html"
(defcube fg42/editor-cube (defcube fg42/editor-cube
"This is a meta cube that sets up the basic functionalities of an Editor" "This is a meta cube that sets up the basic functionalities of an Editor"
(:title "Editor cube" (:title "Editor cube"
:no-flag t) :no-flag t)
(fpkg/use rainbow-delimiters (fpkg/use rainbow-delimiters
;; It doesn't work due to a problem/conflict in rainbow-delimiters ;; It doesn't work due to a problem/conflict in rainbow-delimiters
@ -350,9 +350,9 @@ https://emacsthemes.com/themes/badwolf-theme.html"
(when-flag server (when-flag server
(when (not (server-running-p)) (when (not (server-running-p))
(when-wm (when-wm
(setq server-name "fg42-wm")) (setq server-name "fg42-wm"))
(server-start))) (server-start)))
;; Call the editor related cubes. They will be run only if ;; Call the editor related cubes. They will be run only if
;; their flag is active otherwise they will be skipped ;; their flag is active otherwise they will be skipped

View File

@ -61,14 +61,17 @@ This cube is enough to load everything and control what cube to execute
via flags." via flags."
(:title "Editor cube" (:title "Editor cube"
:flag-default t :flag-default t
:flag fg42-editor-cube) :flag fg42-editor-cube
:init-hook (lambda (params)
(mapc (mapc
(lambda (cube) (lambda (cube)
(let ((params (plist-get fg42/editor-params (when (not (string= (symbol-name cube)
(intern (concat ":" (symbol-name cube)))))) "fg42/editor"))
(eval `(funcall #',cube ,@params)))) (let ((cube-params (plist-get
fg42/available-cubes)) params
(intern (concat ":" (symbol-name cube))))))
(eval `(funcall #',cube ,@cube-params)))))
fg42/available-cubes))))

View File

@ -79,7 +79,7 @@
(setq fg42/modeline-setter #'fg42/mini-modeline-setter)) (setq fg42/modeline-setter #'fg42/mini-modeline-setter))
:defer nil :defer nil
:config :config
(add-hook 'fg42-after-init-hook #'mini-modeline-mode) (add-hook 'fg42/after-init-hook #'mini-modeline-mode)
(add-hook 'fg42/after-initializing-theme-hook (add-hook 'fg42/after-initializing-theme-hook
(lambda () (lambda ()
(custom-set-faces (custom-set-faces
@ -111,7 +111,7 @@ valuable information."
(setq fg42/modeline-setter #'fg42/statusbar-setter) (setq fg42/modeline-setter #'fg42/statusbar-setter)
(add-hook 'fg42-after-init-hook (add-hook 'fg42/after-init-hook
(lambda () (lambda ()
(require 'fg42/statusbar) (require 'fg42/statusbar)
(fg42/statusbar-mode t)))) (fg42/statusbar-mode t))))

View File

@ -25,16 +25,70 @@
(require 'fg42/utils) (require 'fg42/utils)
(defun fg42/before-initialize () (defvar fg42/-gc-cons-threshold 16777216
"Initialize the package manager before rendering the window instance." "Value of GC threshold of FG42.")
(require 'fpkg/core)
(fpkg/initialize)) (defun defer-garbage-collection ()
"Disable garbage collection."
(setq gc-cons-threshold fg42/-gc-cons-threshold))
(defun restore-garbage-collection ()
"Restore garbage collection to it's default value."
(run-at-time
1 nil (lambda () (setq gc-cons-threshold most-positive-fixnum))))
(defun fg42/initialize () (defun fg42/initialize ()
"Initialize FG42 after the Emacs window is rendered by loading the user init file." "Initialize FG42 after the Emacs window is rendered by loading the user init file."
(fg42/-startup-optimization)
(require 'fpkg/core)
(fpkg/initialize)
(when (file-exists-p user-init-file) (when (file-exists-p user-init-file)
(load user-init-file))) (require 'fg42/cube)
(load user-init-file))
(add-hook 'emacs-startup-hook
(lambda ()
(run-hooks 'fg42/-cubes-body-hook)
(run-hooks 'fg42/after-cubes-setup-hook)
(run-hooks 'fg42/after-init-hook)
(run-hooks 'fg42/after-initializing-theme-hook)
(run-hooks 'fg42/ui-hook))))
(defun fg42/-startup-optimization ()
"Optimized FG42 startup."
;; by setting gc threshold to the largest number
;; Emacs can understand we are basically disabling it :).
(setq gc-cons-threshold most-positive-fixnum
gc-cons-percentage 0.6)
;; after initilization phase restore cons threshold to normal
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold fg42/-gc-cons-threshold ; 16mb
gc-cons-percentage 0.1)))
;; disable auto initilization of package.el
(setq package-enable-at-startup nil)
;; disable gc when we are in minibuffer using the same method we
;; use for initilization time
(add-hook 'minibuffer-setup-hook #'defer-garbage-collection)
;; just enable gc when exiting minibuffer
(add-hook 'minibuffer-exit-hook #'restore-garbage-collection)
;; we dont need Emacs to check every file type and look for file
;; handlers when we are initializing so we backup the original
;; value and set it to nil
(setq --file-name-handler-alist file-name-handler-alist)
(setq file-name-handler-alist nil)
;; after initialization we can restore that file-name-handler-alist
;; to original value.
(add-hook 'emacs-startup-hook
(lambda ()
(setq file-name-handler-alist
--file-name-handler-alist)))
;; initial mode for emacs can be fundamental mode we have nothing to lose
(setq initial-major-mode 'fundamental-mode))
(provide 'fg42) (provide 'fg42)

View File

@ -25,11 +25,11 @@
(defgroup fg42 nil (defgroup fg42 nil
"Customize your FG42 instance via this group of configurations.") "Customize your FG42 instance via this group of configurations.")
(defvar fg42-after-init-hook nil (defvar fg42/after-init-hook nil
"The hook tha runs when FG42 finished running the user configuration") "The hook tha runs when FG42 finished running the user configuration.")
(defvar fg42/debug-p nil (defvar fg42/debug-p nil
"The hook tha runs when FG42 finished running the user configuration") "The hook tha runs when FG42 finished running the user configuration.")
(defvar fg42-home (getenv "FG42_HOME") (defvar fg42-home (getenv "FG42_HOME")
"The pass to fg42-home.") "The pass to fg42-home.")

View File

@ -27,6 +27,7 @@
;;; Code: ;;; Code:
(require 'seq) (require 'seq)
(require 'fg42/utils) (require 'fg42/utils)
(require 'fg42/themes)
(defvar fg42/after-cubes-setup-hook nil (defvar fg42/after-cubes-setup-hook nil
"A hook that will be run after all the active cubes got setup. "A hook that will be run after all the active cubes got setup.
@ -40,6 +41,10 @@ it is to use `fg42/after-cubes' macro.")
(defvar fg42/available-cubes '() (defvar fg42/available-cubes '()
"A list of all the registered cubes.") "A list of all the registered cubes.")
(defvar fg42/-cubes-body-hook nil
"A Hook that is internal to FG42 and will be used to run the cub bodies.
The execution happens after Emacs is initialized.")
(defmacro defcube (cube-name docs props &rest body) (defmacro defcube (cube-name docs props &rest body)
"Define a cube with the given CUBE-NAME, a list of PROPS, DOCS and a BODY." "Define a cube with the given CUBE-NAME, a list of PROPS, DOCS and a BODY."
@ -55,6 +60,11 @@ it is to use `fg42/after-cubes' macro.")
(let ((complete-props (plist-put props :docs docs)) (let ((complete-props (plist-put props :docs docs))
(cube-name-internal (intern (format "%s-internal" cube-name))) (cube-name-internal (intern (format "%s-internal" cube-name)))
;; prop hooks
(init-hook (plist-get props :init-hook))
(ui-hook (plist-get props :ui-hook))
(params-var (intern (format "%s-params" cube-name))) (params-var (intern (format "%s-params" cube-name)))
(active-var (intern (format "%s-active-p" cube-name))) (active-var (intern (format "%s-active-p" cube-name)))
(pre-lang-server-up-hook (intern (format "%s-pre-lang-server-up-hook" cube-name))) (pre-lang-server-up-hook (intern (format "%s-pre-lang-server-up-hook" cube-name)))
@ -145,13 +155,27 @@ it is to use `fg42/after-cubes' macro.")
(defun ,cube-name (&rest params) (defun ,cube-name (&rest params)
(interactive) (interactive)
(if ,no-flag? (let ((ui-hook ,ui-hook)
;; If no flag is need to control this cube (init-hook ,init-hook))
(,cube-name-internal params) (if ,no-flag?
;; Otherwise check for the flag to be active (progn
(if-flag ,flag-var (when (not (null ui-hook))
(,cube-name-internal params) (add-hook 'fg42/ui-hook ui-hook))
(fg42/info "The flag for '%s' cube is disabled. Skiping." ,(symbol-name cube-name))))) ;; If no flag is need to control this cube
(when (not (null init-hook))
(funcall init-hook params))
(add-hook 'fg42/-cubes-body-hook (lambda ()
(,cube-name-internal params))))
;; Otherwise check for the flag to be active
(if-flag ,flag-var
(progn
(when (not (null ui-hook))
(add-hook 'fg42/ui-hook ,ui-hook))
(when (not (null init-hook))
(funcall init-hook params))
(add-hook 'fg42/-cubes-body-hook (lambda ()
(,cube-name-internal params))))
(fg42/info "The flag for '%s' cube is disabled. Skiping." ,(symbol-name cube-name))))))
;; Set the symbol-plist of the cube-name to its props ;; Set the symbol-plist of the cube-name to its props
(setplist ',cube-name ',complete-props)))) (setplist ',cube-name ',complete-props))))

View File

@ -27,6 +27,10 @@
;;; Code: ;;; Code:
(require 'fg42/utils) (require 'fg42/utils)
(defvar fg42/ui-hook ()
"A hook that cubes can use via :ui-hook property.
It executes way before the rest of the cubes.")
(defvar fg42/before-initializing-theme-hook () (defvar fg42/before-initializing-theme-hook ()
"The hook to plug any configuration to before initialize event of themes.") "The hook to plug any configuration to before initialize event of themes.")

View File

@ -778,7 +778,8 @@ We can clone a library somewhere on the disk and add the path to it to the =load
and load the library files. and load the library files.
But that would be tedious to do so for all the libraries. That's why we use a package manager But that would be tedious to do so for all the libraries. That's why we use a package manager
* Episode 13 - Editing Modes, Part 1 * DONE Episode 13 - Editing Modes, Part 1
CLOSED: [2023-06-10 Sat 15:44]
Emacs provides a concept called ~editing mode~ that allows Emacs provides a concept called ~editing mode~ that allows
us to control different aspect of the editor. us to control different aspect of the editor.
@ -881,3 +882,10 @@ and to enable it we can pass a positive integer.
- ~global-minor-modes~: This variable lists the currently enabled global minor modes, - ~global-minor-modes~: This variable lists the currently enabled global minor modes,
and is a list of symbols. and is a list of symbols.
- ~minor-mode-list~: The value of this variable is a list of all minor mode commands. - ~minor-mode-list~: The value of this variable is a list of all minor mode commands.
* Episode 14 - Editing Modes, Part 2
** Quick overview:
*** Hooks
*** Keymaps
*** Interactive functions
** A quick and useless minor mode
** Resources:

View File

@ -44,13 +44,7 @@
(load custom-file)) (load custom-file))
(require 'fg42) (require 'fg42)
(fg42/before-initialize)
(fg42/initialize) (fg42/initialize)
(run-hooks 'fg42/after-cubes-setup-hook)
(run-hooks 'fg42-after-init-hook)
(run-hooks 'fg42/after-initializing-theme-hook)
(provide 'fg42-config) (provide 'fg42-config)
;;; fg42-config.el ends here ;;; fg42-config.el ends here