Update emacs config
[emacs.git] / .emacs.d / init.el
index 2cf5973..968b93d 100644 (file)
+;; Added by Package.el.  This must come before configurations of
+;; installed packages.  Don't delete this line.  If you don't want it,
+;; just comment it out by adding a semicolon to the start of the line.
+;; You may delete these explanatory comments.
+;(package-initialize)
+
+;; Ganneff's emacs config
+
+;; Emacs can not read its config directly from org-mode files.
+;; But as my config nearly completly is inside an org-mode file,
+;; emacs need to be told to deal with it.
+;; Meet org-tangle/org-babel-load-file, which extracts the emacs-lisp
+;; source parts of my config files, writes them into .el files
+;; and then lets emacs load those.
+
+;; That way I have a nice environment to edit and comment - and easily export
+;; to web or elsewhere - while emacs has its elisp. The initial run after
+;; a config change takes longer, but as that only happens when I change
+;; something in the .org files - I don't care.
+
+(eval-and-compile
+  (defvar jj--file-name-handler-alist file-name-handler-alist)
+  (setq gc-cons-threshold most-positive-fixnum
+        gc-cons-percentage 0.6
+        file-name-handler-alist nil))
+  
+;; Go go go
+(unless noninteractive
+(message "Emacs is powering up... Be patient, Master %s!" (getenv "USER")))
+
 ;; I like to see how long it takes to "boot" emacs (usually one or two
 ;; seconds), so save the start time
-(setq emacs-load-start-time (current-time))
-
-;; Set path to (my, recent) Org-Mode version
-(add-to-list 'load-path "~/elisp/org/")
-;; Have use-package/bindkey in here wich are needed for startup
-(add-to-list 'load-path "~/elisp/local/")
-
-;; Set up dotfiles-dir variable, for easier reference later
-(setq dotfiles-dir (expand-file-name "config" 
-                                     (file-name-directory 
-                                      (or load-file-name (buffer-file-name)))))
-
-;; I might have special configuration based on various states
-;; First we set an own variable, as system-type from emacs directly is
-;; useless. gnu/linux and gnu/kfreebsd have extra /, which is plenty annoying
-;; when you want to use them in a path entry.
-(defun jj-system-type ()
-  "Return a string depending on the OS we use"
-  (interactive)
-  (cond
-   ((eq system-type 'darwin) "macosx")
-   ((eq system-type 'gnu/linux) "linux")
-   ((eq system-type 'gnu/kfreebsd) "kfreebsd")
-   ((eq system-type 'cygwin) "cygwin")
-   ((eq system-type 'windows-nt) "windows")))
-
-;; Setup some variables for files I might want to load later.
-;; Those are config files that are specific to
-;; - the system my emacs runs on
-;; - the os emacs is on
-;; - the user name I have
-(setq jj-sys-config (concat dotfiles-dir "/" system-name ".org"))
-(setq jj-os-config (concat dotfiles-dir "/" (jj-system-type) ".org"))
-(setq jj-user-config (concat dotfiles-dir "/" user-login-name ".org"))
-
-;; As we use org-mode/org-babel/org-tangle to extract the real emacs
-;; config out of the org-mode files, we have to load that first.
+(defvar emacs-load-start-time (current-time))
+
+;; If we are starting a daemon, load each and every package. If not,
+;; default use-package is to delay package loading, which is good when
+;; interactively starting emacs.
+(if (daemonp)
+      (setq use-package-always-demand t))
+
+; Much larger threshold for garbage collection prevents it to run too often.
+;(setq gc-cons-threshold 480000000)
+
+;; Set a high number of lines for the message buffer so stuff doesn't "scroll out"
+(setq message-log-max 16384)
+
+;; Don't load old .elc files when the .el file is newer
+(setq load-prefer-newer t)
+
+;; ;; Set path to (my, recent) Org-Mode version
+;; (add-to-list 'load-path (concat (file-name-directory (or load-file-name (buffer-file-name))) "elisp/org/"))
+;; org-mode can load modules when it loads itself, lets tell it which ones we want.
+;  org-checklist
 (setq org-modules (quote
                    (org-bbdb org-bibtex org-crypt org-docview org-gnus
-                    org-id org-info org-jsinfo org-habit org-inlinetask
-                    org-irc org-protocol org-w3m org-mouse org-checklist
-                    org-notmuch icalendar)))
-(require 'org-install)
+                    org-id org-info org-habit org-inlinetask
+                    org-irc org-protocol org-w3m org-mouse
+                    icalendar))) ; org-notmuch
+
+;; And load org-mode
+(require 'org)
+;; Without this the whole config can't load
 (require 'ob-tangle)
+;; And finally, let org-babel do its work. All the rest of the emacs
+;; initialization comes from initjj.org
+;(org-babel-load-file (expand-file-name "initjj.org" (file-name-directory (or load-file-name (buffer-file-name))))))
+
+(defun my-tangle-section-canceled ()
+  "Checks if the previous section header was CANC"
+  (save-excursion
+    (if (re-search-backward "^\\*+\\s-+\\(.*?\\)?\\s-*$" nil t)
+        (progn
+          ;; (message "FOUND '%s'" (match-string 1))
+          (string-prefix-p "CANC" (match-string 1)))
+      nil)))
+
+(defun my-tangle-config-org (orgfile elfile)
+  "This function will write all source blocks from =config.org= into
+=config.el= that are ...
+
+- not marked as :tangle no
+- have a source-code of =emacs-lisp=
+- doesn't have the todo-marker CANC"
+  (let* ((body-list ())
+                (gc-cons-threshold most-positive-fixnum)
+         (org-babel-src-block-regexp   (concat
+                                        ;; (1) indentation                 (2) lang
+                                        "^\\([ \t]*\\)#\\+begin_src[ \t]+\\([^ \f\t\n\r\v]+\\)[ \t]*"
+                                        ;; (3) switches
+                                        "\\([^\":\n]*\"[^\"\n*]*\"[^\":\n]*\\|[^\":\n]*\\)"
+                                        ;; (4) header arguments
+                                        "\\([^\n]*\\)\n"
+                                        ;; (5) body
+                                        "\\([^\000]*?\n\\)??[ \t]*#\\+end_src")))
+    (with-temp-buffer
+      (insert-file-contents orgfile)
+      (goto-char (point-min))
+      (while (re-search-forward org-babel-src-block-regexp nil t)
+        (let ((lang (match-string 2))
+              (args (match-string 4))
+              (body (match-string 5))
+              (canc (my-tangle-section-canceled)))
+          (when (and (string= lang "emacs-lisp")
+                     (not (string-match-p ":tangle\\s-+no" args))
+                     (not canc))
+              (add-to-list 'body-list body)))))
+    (with-temp-file elfile
+      (insert ";; *- lexical-binding: t; -*-\n")
+      (insert (format ";; Don't edit this file, edit %s instead ...\n\n" orgfile))
+      ;; (insert (apply 'concat (reverse body-list)))
+      (apply 'insert (reverse body-list)))
+    (message "Wrote %s ..." elfile)
+    (byte-compile-file elfile)))
+
+
+(let ((orgfile (expand-file-name "initjj.org" (file-name-directory (or load-file-name (buffer-file-name)))))
+      (elfile (expand-file-name "initjj.el" (file-name-directory (or load-file-name (buffer-file-name))))))
+  (when (or (not (file-exists-p elfile))
+            (file-newer-than-file-p orgfile elfile))
+    (my-tangle-config-org orgfile elfile))
+  (load-file elfile))
+
+; And back done a bit with it, startup is over
+;(setq gc-cons-threshold (* 100 1024 1024))
 
-;; Now read my config
-;; Note that those files *can* include further files.
-
-;; The basic config is always loaded, no matter where we start emacs.
-(org-babel-load-file (expand-file-name "emacs.org" dotfiles-dir))
-
-;; All the others are optional. We try the order of os, system, user
-;; specific files and load them, should they be there
-(if (file-exists-p jj-os-config)
-    (org-babel-load-file (expand-file-name jj-os-config dotfiles-dir)))
-(if (file-exists-p jj-sys-config)
-    (org-babel-load-file (expand-file-name jj-sys-config dotfiles-dir)))
-(if (file-exists-p jj-user-config)
-    (org-babel-load-file (expand-file-name jj-user-config dotfiles-dir)))
-
-;; Lets get a message about startup time out
-(when (require 'time-date nil t)
-  (message "Emacs startup time: %d seconds."
-           (time-to-seconds (time-since emacs-load-start-time)))
-  )
+;; Don't keep gc-cons-threshold too high. It helps to stave off the GC while
+;; Emacs starts up, but afterwards it causes stuttering and random freezes. So
+;; reset it to a reasonable default.
+(setq gc-cons-threshold 16777216
+      gc-cons-percentage 0.1
+      file-name-handler-alist jj--file-name-handler-alist)
+(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(package-selected-packages (quote (notmuch validate use-package paradox keyfreq))))
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )