diff --git a/.gitmodules b/.gitmodules index bf1c979..b2db846 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,18 @@ [submodule "smart-tab"] path = smart-tab url = https://github.com/genehack/smart-tab.git +[submodule "org-pomodoro"] + path = org-pomodoro + url = https://github.com/lolownia/org-pomodoro.git +[submodule "alert"] + path = alert + url = https://github.com/jwiegley/alert.git +[submodule "fringe-current-line"] + path = fringe-current-line + url = https://github.com/kyanagi/fringe-current-line.git +[submodule "Frame-Bufs"] + path = Frame-Bufs + url = https://github.com/alpaker/Frame-Bufs.git +[submodule "predictive"] + path = predictive + url = http://www.dr-qubit.org/git/predictive.git diff --git a/Frame-Bufs b/Frame-Bufs new file mode 160000 index 0000000..6f360b3 --- /dev/null +++ b/Frame-Bufs @@ -0,0 +1 @@ +Subproject commit 6f360b3901edce0b4dbdfd1fdc15a99f78cbfc8a diff --git a/alert b/alert new file mode 160000 index 0000000..9725bd8 --- /dev/null +++ b/alert @@ -0,0 +1 @@ +Subproject commit 9725bd8bbf9109903d54cb0c850ab81a27d261c5 diff --git a/fringe-current-line b/fringe-current-line new file mode 160000 index 0000000..0ef000b --- /dev/null +++ b/fringe-current-line @@ -0,0 +1 @@ +Subproject commit 0ef000bac76abae30601222e6f06c7d133ab4942 diff --git a/init-latex.el b/init-latex.el deleted file mode 100644 index 1f1f676..0000000 --- a/init-latex.el +++ /dev/null @@ -1,96 +0,0 @@ -(load "auctex.el" nil t t) -(setq TeX-auto-save t - TeX-parse-self t - TeX-insert-braces nil) -(setq-default TeX-master nil) -(setq font-latex-fontify-script nil) -(setq LaTeX-equation-label "e_") -(setq LaTeX-section-label "s_") -(setq LaTeX-figure-label "f_") -(require 'reftex) - -(defun add-delimiter (delim-begin delim-end r-begin r-end) - "Add the pair of delimiters given in delim at the ends of the region if it is activated" - (interactive "cBegin delimiter: \ncEnd delimiter: \nr") - (if (use-region-p) - (progn - (save-excursion - (goto-char r-end) (insert delim-end) - (goto-char r-begin) (insert delim-begin))) - (progn - (save-excursion - (insert delim-end)) - (insert delim-begin)))) - -(add-hook 'LaTeX-mode-hook (lambda () - (turn-on-auto-fill) - (subword-mode) - ;; Move around commands in the Right Way™ - (modify-syntax-entry ?\\ "w" LaTeX-mode-syntax-table) - (setq subword-forward-regexp "\\W*\\(\\([\\\\[:upper:]]*\\W?\\)[[:lower:][:digit:]]*\\)") - (setq subword-backward-regexp "\\(\\(\\W\\|[[:lower:][:digit:]]\\)\\([\\\\[:upper:]]+\\W*\\)\\|\\W\\w+\\)") - ;; FIXME: this breaks sourcepair for other modes. - (setq sourcepair-source-extensions '(".tex")) - (setq sourcepair-header-extensions '(".p.tex")) - - (define-key LaTeX-mode-map (kbd "C-c C-v") - (lambda (arg) - (interactive "P") - (insert "~") - (if arg (TeX-insert-macro "eqref") - (TeX-insert-macro "ref")))) - (define-key LaTeX-mode-map (kbd "M-S-") - (lambda (arg) - (interactive "P") - (if arg (LaTeX-insert-environment "align") - (LaTeX-insert-environment "align*")))) - - (define-key LaTeX-mode-map (kbd "S-SPC") (lambda() (interactive) (insert "\\"))) - (define-key LaTeX-mode-map (kbd "M-S-SPC") 'TeX-insert-braces) - (define-key LaTeX-mode-map (kbd "s-SPC") (lambda() (interactive) (insert "~"))) - (define-key LaTeX-mode-map (kbd "M-_") (lambda (r-begin r-end) (interactive "r") (add-delimiter "_{" "}" r-begin r-end))) - (define-key LaTeX-mode-map (kbd "M-^") (lambda (r-begin r-end) (interactive "r") (add-delimiter "^{" "}" r-begin r-end))) - (define-key LaTeX-mode-map (kbd "M-$") (lambda (r-begin r-end) (interactive "r") (add-delimiter "$" "$" r-begin r-end))) ;; This overlaps with the spell-checker; not that I ever remember that key - (define-key LaTeX-mode-map (kbd "C-c C-d") - (lambda (arg r-begin r-end) (interactive "P\nr") - (if arg - (add-delimiter "\\todo[inline]{" "}{}" r-begin r-end) - (add-delimiter "\\todo{" "}{}" r-begin r-end)))) - (define-key LaTeX-mode-map (kbd "C-c C-g") 'magit-status) - )) - -;; this reimplements TeX-insert-braces to work with negative argument -(defun TeX-insert-braces (arg) - "Make a pair of braces around next ARG sexps and leave point inside. -No argument is equivalent to zero: just insert braces and leave point -between. - -If there is an active region, ARG will be ignored, braces will be -inserted around the region, and point will be left after the -closing brace." - (interactive "P") - (if (TeX-active-mark) - (progn - (if (< (point) (mark)) - (exchange-point-and-mark)) - (insert TeX-grcl) - (save-excursion - (goto-char (mark)) - (insert TeX-grop))) - (if (and arg (< arg 0)) - (progn - (save-excursion - (backward-sexp (prefix-numeric-value (- 0 arg))) - (insert TeX-grop)) - (insert TeX-grcl)) - (insert TeX-grop) - (save-excursion - (if arg (forward-sexp (prefix-numeric-value arg))) - (insert TeX-grcl))))) - -(defun TeX-back-insert-braces (arg) - (interactive "P") - (if arg (TeX-insert-braces (- 0 arg)) - (insert TeX-grcl))) - -(load "latex-compile-filters.el") diff --git a/init.el b/init.el index 071f835..58fa6b5 100644 --- a/init.el +++ b/init.el @@ -3,9 +3,14 @@ ;; 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. + '(TeX-complete-word (quote dabbrev-expand-helper)) + '(TeX-fold-preserve-comments t) + '(TeX-fold-type-list (quote (env))) '(TeX-newline-function (quote reindent-then-newline-and-indent)) '(auto-save-file-name-transforms (quote ((".*" "~/.emacs.d/autosaves/\\1" t)))) '(backup-directory-alist (quote ((".*" . "~/.emacs.d/backup/")))) + '(blink-cursor-delay 3) + '(blink-cursor-mode t) '(bsn-backends (quote (msn))) '(case-fold-search t) '(compilation-auto-jump-to-first-error t) @@ -17,12 +22,50 @@ '(flyspell-mark-duplications-flag t) '(font-latex-fontify-sectioning (quote color)) '(global-font-lock-mode t nil (font-lock)) + '(hl-sexp-background-colors (quote ("#395959"))) + '(ibuffer-use-other-window t) '(inhibit-startup-screen t) + '(org-agenda-files (quote ("~/org/notes.org"))) + '(org-capture-templates + (quote + (("t" "Todo" entry + (file+headline "~/org/notes.org" "Tasks") + "* TODO %? + %u + %a") + ("i" "Idea" entry + (file+headline "~/org/notes.org" "Ideas") + "* IDEA %? + %u") + ("e" "MailTo" entry + (file+headline "~/org/notes.org" "E-mails") + "* TODO mailto:%?") + ("s" "Item to buy" item + (file+headline "~/org/spesa.org" "Food") + "- %? "))) t) '(org-catch-invisible-edits (quote smart)) + '(org-icalendar-include-todo t) + '(org-indent-mode-turns-on-hiding-stars nil) + '(org-pomodoro-play-sounds nil) '(parens-require-spaces nil) - '(safe-local-variable-values (quote ((eval add-hook (quote before-save-hook) (quote org-export-icalendar-this-file) nil t) (TeX-master . notes\.tex) (bookmark-default-file . "./emacs.bmk")))) + '(safe-local-variable-values + (quote + ((eval add-hook + (quote before-save-hook) + (quote org-icalendar-export-to-ics) + nil t) + (eval add-hook + (quote before-save-hook) + (quote org-export-icalendar-this-file) + nil t) + (TeX-master . notes\.tex) + (bookmark-default-file . "./emacs.bmk")))) '(show-paren-mode t) - '(smart-tab-completion-functions-alist (quote ((emacs-lisp-mode . lisp-complete-symbol) (text-mode . dabbrev-completion) (latex-mode . TeX-complete-symbol)))) + '(smart-tab-completion-functions-alist + (quote + ((emacs-lisp-mode . lisp-complete-symbol) + (text-mode . dabbrev-completion) + (latex-mode . TeX-complete-symbol)))) '(transient-mark-mode t) '(truncate-partial-width-windows nil) '(visible-mark-inhibit-trailing-overlay t)) @@ -33,20 +76,27 @@ ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(default ((t (:inherit nil :stipple nil :background "#182828" :foreground "cornsilk1" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 90 :width normal :foundry "xos4" :family "terminus")))) - '(bold ((t (:weight semi-bold)))) - '(cursor ((t (:background "orchid")))) + '(bold ((t (:weight normal)))) + '(cursor ((t (:background "orchid3" :foreground "#182828")))) '(fixed-pitch ((t (:family "Bitstream Vera Sans Mono")))) '(font-latex-italic-face ((t (:inherit italic :foreground "SpringGreen")))) '(font-lock-comment-delimiter-face ((t (:foreground "lightslategray")))) '(font-lock-comment-face ((t (:foreground "SlateGray")))) - '(highlight ((t (:background "#223939")))) + '(highlight ((t (:background "Darkslategray")))) + '(hl-sexp-face ((t (:underline t))) t) '(italic ((((supports :underline t)) nil))) + '(linum-highlight-face ((t (:inherit (highlight default))))) '(menu ((t (:inverse-video t)))) '(mouse ((t (:background "orchid")))) + '(org-pomodoro-mode-line ((t (:foreground "tomato3")))) + '(paren-face-match ((t (:background "turquoise" :foreground "black")))) '(region ((t (:background "DodgerBlue4")))) + '(shadow ((t (:foreground "grey60")))) '(tooltip ((t (:inherit default :background "lightyellow" :foreground "black" :foundry "xos4" :family "terminus")))) '(variable-pitch ((t (:family "default")))) - '(visible-mark-face ((t (:background "goldenrod" :foreground "darkslategrey"))))) + '(visible-mark-face ((t (:background "goldenrod" :foreground "#182828"))))) + +;; This kinda overrides the customize business, but it works (setq-default display-buffer-reuse-frames t) (add-hook 'before-save-hook 'delete-trailing-whitespace) @@ -74,7 +124,7 @@ scroll-preserve-screen-position 1) ;; add .emacs.d and subdirs to load path -(add-to-list 'load-path "~/.emacs.d") +;; (add-to-list 'load-path "~/.emacs.d") (let ((default-directory "~/.emacs.d/")) (normal-top-level-add-subdirs-to-load-path) (normal-top-level-add-to-load-path '("fringe-helper.el" "multiple-cursors.el" "dash.el"))) @@ -89,6 +139,8 @@ (load "init-latex.el") (load "init-org.el") +(load "init-c++.el") + ;; KDE stuff ;; @@ -101,7 +153,7 @@ (setq frame-title-format '((buffer-file-name "%f" - (dired-directory dired-directory "%b")) " · emacs %S")) + (dired-directory dired-directory "%b")) " · emacs " kde-current-activity-name "%S")) ;; Put autosave files (ie #foo#) and backup files (ie foo~) in ~/.emacs.d/. ;; create the autosave dir if necessary, since emacs won't. @@ -116,6 +168,8 @@ (require 'sourcepair) (global-set-key (kbd "") 'sourcepair-load) +(global-set-key (kbd "C-x C-b") 'ibuffer) + (setq default-fill-column 120) (add-to-list 'load-path "~/tmp") @@ -135,6 +189,10 @@ (substring (shell-command-to-string "qdbus org.kde.ActivityManager /ActivityManager/Activities org.kde.ActivityManager.Activities.CurrentActivity") 0 -1) ) +(defun kde-current-activity-name () + "Returns the name of the current KDE activity" + (substring (shell-command-to-string (concat "qdbus org.kde.ActivityManager /ActivityManager/Activities org.kde.ActivityManager.Activities.ActivityName " (kde-current-activity))) 0 -1)) + (defun X-window-id-belongs-to-activity (window-id activity) (= (shell-command (concat "xprop -id " window-id " | grep _KDE_NET_WM_ACTIVITIES | grep " activity ">/dev/null")) 0) ) @@ -169,8 +227,9 @@ ;; Rehab ↓ ;; mark the date 30/1/2014 -(require 'no-easy-keys) -(no-easy-keys 1) +;; (require 'no-easy-keys) +;; (no-easy-keys 1) +;; conflicts a bit with org-mode ;;Keyboard is faster than mouse (global-unset-key (kbd "")) @@ -182,15 +241,25 @@ ;;Remove insanely irritating key-binding (global-unset-key (kbd "C-z")) (global-unset-key (kbd "C-x f")) +(global-unset-key (kbd "")) ; rly? + +;; Change some global bindings: +(global-set-key (kbd "C-M-d") 'kill-sexp) +(global-set-key (kbd "C-M-i") 'down-list) ;; -i stands for /in/ +(global-set-key (kbd "C-M-o") 'up-list) ;; -o stands for /out/ +(global-unset-key (kbd "C-M-u")) + (require 'visible-mark) (visible-mark-mode t) (global-visible-mark-mode t) -(delete 'Git vc-handled-backends) +;(delete 'Git vc-handled-backends) (require 'magit) -(global-set-key (kbd "H-g") 'magit-status) +(global-set-key (kbd "C-x C-g") 'magit-status) ;; relates to C-x C-f and C-x C-s + +;; Comment out since it does not work reliably (require 'iy-go-to-char) (global-set-key (kbd "M-m") 'iy-go-up-to-char) (global-set-key (kbd "M-M") 'iy-go-up-to-char-backward) @@ -232,17 +301,17 @@ the current position of point, then move it to the beginning of the line." (beginning-of-line)))) (global-set-key (kbd "C-a") 'smart-line-beginning) -(defun smart-delete-backward-char () - "try to be smart to delete indentation" - (interactive) - (let ((pt (point))) - (beginning-of-line-text) - (if (eq pt (point)) - (delete-indentation) - (progn - (goto-char pt) - (call-interactively 'delete-backward-char))))) -(global-set-key "\d" 'smart-delete-backward-char) +;; (defun smart-delete-backward-char () +;; "try to be smart to delete indentation" +;; (interactive) +;; (let ((pt (point))) +;; (beginning-of-line-text) +;; (if (eq pt (point)) +;; (delete-indentation) +;; (progn +;; (goto-char pt) +;; (call-interactively 'delete-backward-char))))) +;; (global-set-key "\d" 'smart-delete-backward-char) (add-to-list 'load-path "~/tmp/expand-region.el") (require 'expand-region) @@ -267,7 +336,10 @@ a file in the home directory." (global-set-key (kbd "H-.") 'mc/mark-next-like-this) (global-set-key (kbd "H-,") 'mc/mark-previous-like-this) (global-set-key (kbd "H-") 'mc/add-cursor-on-click) -(global-set-key (kbd "H-`") 'mc/mark-pop) +(global-set-key (kbd "") 'mc/mark-pop) +(global-set-key (kbd "H-#") 'mc/insert-numbers) + +(global-set-key (kbd "") 'set-mark-command) ;; clever mark stuff (defun push-mark-no-activate () @@ -276,14 +348,20 @@ Equivalent to \\[set-mark-command] when \\[transient-mark-mode] is disabled" (interactive) (push-mark (point) t nil) (message "Pushed mark to ring")) -(global-set-key (kbd "C-`") 'push-mark-no-activate) +(global-set-key (kbd "") 'push-mark-no-activate) (defun jump-to-mark () "Jumps to the local mark, respecting the `mark-ring' order. This is the same as using \\[set-mark-command] with the prefix argument." (interactive) (set-mark-command 1)) -(global-set-key (kbd "M-`") 'jump-to-mark) +(global-set-key (kbd "") 'jump-to-mark) + +(defun just-activate-mark () + (interactive) + (exchange-point-and-mark) + (exchange-point-and-mark)) +(global-set-key (kbd "") 'just-activate-mark) ;; (defun exchange-point-and-mark-no-activate () ;; "Identical to \\[exchange-point-and-mark] but will not activate the region." @@ -313,6 +391,54 @@ This is the same as using \\[set-mark-command] with the prefix argument." (require 'epa-file) (epa-file-enable) +;; Time stamps +;; write +;; Time-stamp: <> +;; in your file and save it to see time stamps at work. +;; Other time stamp format: "%a %b %e, %Y %l:%M %p" +(add-hook 'write-file-hooks 'time-stamp) +(setq time-stamp-active t) +(setq time-stamp-format "%:a %02d %:b %:y, %02H:%02M:%02S, %u") +(setq european-calendar-style 't) +;; first day of the week is monday instead of sunday: +(setq calendar--week--start--day 1) + +(require 'highlight-sexps) + +(setq echo-keystrokes 0.10) +(set-default 'cursor-type 'box) +(require 'fringe-current-line) +(global-fringe-current-line-mode 1) +(require 'hlinum) +(hlinum-activate) + +(require 'completion-ui) + +(setq ibuffer-saved-filter-groups + (quote (("default" + ("LaTeχ" (mode . latex-mode)) + ("Magit" (name . "^\\*magit.*$")) + ("elisp" (mode . emacs-lisp-mode)) + ("org" (mode . org-mode)) + ("emacs" (or + (name . "^\\*scratch\\*$") + (name . "^\\*Messages\\*$") + (name . "^\\*compilation\\*$"))))))) + +(add-hook 'ibuffer-mode-hook + '(lambda () + (ibuffer-switch-to-saved-filter-groups "default"))) + +;; Try again with ido +(require 'ido) +(ido-mode t) + +(set-face-font 'default "-xos4-TerminusPlus-Medium-R-Normal--12-120-72-72-C-60-ISO10646-1") + (mapc + (lambda (face) + (set-face-attribute face nil :weight 'normal)) + (face-list)) + (setq server-name (kde-current-activity)) (server-start) (menu-bar-mode -99) diff --git a/init/init-c++.el b/init/init-c++.el new file mode 100644 index 0000000..504008f --- /dev/null +++ b/init/init-c++.el @@ -0,0 +1,5 @@ +(add-hook 'c-mode-hook 'linum-mode) + +(add-hook 'c++-mode-hook (lambda () + (linum-mode) + (subword-mode))) diff --git a/init/init-cc.el b/init/init-cc.el new file mode 100644 index 0000000..32e0dbc --- /dev/null +++ b/init/init-cc.el @@ -0,0 +1,5 @@ +(add-hook 'c-mode-hook 'linum-mode) + +(add-hook 'c++-mode-hook (lambda () + (linum-mode) + (subword-mode)) diff --git a/init/init-latex.el b/init/init-latex.el new file mode 100644 index 0000000..3fd4b5c --- /dev/null +++ b/init/init-latex.el @@ -0,0 +1,149 @@ +(load "auctex.el" nil t t) +(setq TeX-auto-save t + TeX-parse-self t + TeX-insert-braces nil) +(setq-default TeX-master nil) +(setq font-latex-fontify-script nil) +(setq LaTeX-equation-label "e_") +(setq LaTeX-section-label "s_") +(setq LaTeX-figure-label "f_") +(setq TeX-fold-ellipsis " …") +(require 'reftex) + +(defun dabbrev-expand-helper () + (interactive) + (call-interactively 'dabbrev-expand)) + + +(defun add-delimiter (delim-begin delim-end r-begin r-end) + "Add the pair of delimiters given in delim at the ends of the region if it is activated" + (interactive "cBegin delimiter: \ncEnd delimiter: \nr") + (if (use-region-p) + (progn + (save-excursion + (goto-char r-end) (insert delim-end) + (goto-char r-begin) (insert delim-begin))) + (progn + (save-excursion + (insert delim-end)) + (insert delim-begin)))) + +(add-hook 'LaTeX-mode-hook (lambda () + (turn-on-auto-fill) + (subword-mode) + (TeX-fold-mode 1) + ;; Move around commands in the Right Way™ + (modify-syntax-entry ?\\ "w" LaTeX-mode-syntax-table) + (setq subword-forward-regexp "\\W*\\(\\([\\\\[:upper:]]*\\W?\\)[[:lower:][:digit:]]*\\)") + (setq subword-backward-regexp "\\(\\(\\W\\|[[:lower:][:digit:]]\\)\\([\\\\[:upper:]]+\\W*\\)\\|\\W\\w+\\)") + ;; ;; FIXME: this breaks sourcepair for other modes. + ;; (setq sourcepair-source-extensions '(".tex")) + ;; (setq sourcepair-header-extensions '(".p.tex")) + + (define-key LaTeX-mode-map (kbd "C-c C-v") + (lambda (arg) + (interactive "P") + (insert "~") + (if arg (TeX-insert-macro "eqref") + (TeX-insert-macro "ref")))) + (define-key LaTeX-mode-map (kbd "C-M-") + (lambda (arg) + (interactive "P") + (if arg (LaTeX-insert-environment "align") + (LaTeX-insert-environment "align*")))) + + (define-key LaTeX-mode-map (kbd "S-SPC") (lambda() (interactive) (insert "\\"))) + (define-key LaTeX-mode-map (kbd "M-S-SPC") 'TeX-insert-braces) + (define-key LaTeX-mode-map (kbd "s-SPC") (lambda() (interactive) (insert "~"))) + (define-key LaTeX-mode-map (kbd "M-_") (lambda (r-begin r-end) (interactive "r") (add-delimiter "_{" "}" r-begin r-end))) + (define-key LaTeX-mode-map (kbd "M-^") (lambda (r-begin r-end) (interactive "r") (add-delimiter "^{" "}" r-begin r-end))) + (define-key LaTeX-mode-map (kbd "M-|") (lambda (r-begin r-end) (interactive "r") (add-delimiter "|" "|" r-begin r-end))) + (define-key LaTeX-mode-map (kbd "M-$") (lambda (r-begin r-end) (interactive "r") (message "deprecated") (add-delimiter "$" "$" r-begin r-end))) ;; This overlaps with the spell-checker; not that I ever remember that key + + ;; This is the rationale: C-M-SPC starts inline math C-M-RET starts display math + (define-key LaTeX-mode-map (kbd "C-M-SPC") (lambda (r-begin r-end) (interactive "r") (add-delimiter "$" "$" r-begin r-end))) + (define-key LaTeX-mode-map (kbd "C-c C-d") + (lambda (arg r-begin r-end) (interactive "P\nr") + (if arg + (add-delimiter "\\todo[inline]{" "}{}" r-begin r-end) + (add-delimiter "\\todo{" "}{}" r-begin r-end)))) + (define-key LaTeX-mode-map (kbd "C-M-d") 'kill-sexp) + (define-key LaTeX-mode-map (kbd "C-M-i") 'down-list) ;; -i stands for /in/ + (define-key LaTeX-mode-map (kbd "C-M-o") 'up-list) ;; -o stands for /out/ + + + (define-key LaTeX-mode-map (kbd "=") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "≠") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd ">") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "<") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "≥") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "≤") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "⇒") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "∩") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "∪") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "∨") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "∧") 'insert-char-with-padding) + (define-key LaTeX-mode-map (kbd "×") 'insert-char-with-padding) + + + ;; ;; Unicode shortcuts… + ;; (define-key LaTeX-mode-map (kbd "α") (lambda() (interactive) (insert "\\alpha"))) + ;; (define-key LaTeX-mode-map (kbd "β") (lambda() (interactive) (insert "\\beta"))) + ;; (define-key LaTeX-mode-map (kbd "δ") (lambda() (interactive) (insert "\\delta"))) + ;; (define-key LaTeX-mode-map (kbd "Δ") (lambda() (interactive) (insert "\\Delta"))) + ;; (define-key LaTeX-mode-map (kbd "θ") (lambda() (interactive) (insert "\\theta"))) + ;; (define-key LaTeX-mode-map (kbd "Θ") (lambda() (interactive) (insert "\\Theta"))) + ;; (define-key LaTeX-mode-map (kbd "λ") (lambda() (interactive) (insert "\\lambda"))) + ;; (define-key LaTeX-mode-map (kbd "Λ") (lambda() (interactive) (insert "\\Lambda"))) + ;; (define-key LaTeX-mode-map (kbd "ω") (lambda() (interactive) (insert "\\omega"))) + ;; (define-key LaTeX-mode-map (kbd "Ω") (lambda() (interactive) (insert "\\Omega"))) + + ;; (define-key LaTeX-mode-map (kbd "∈") (lambda() (interactive) (insert "\\in"))) + ;; (define-key LaTeX-mode-map (kbd "ℓ") (lambda() (interactive) (insert "\\ell"))) + + + )) + +;; this reimplements TeX-insert-braces to work with negative argument +(defun TeX-insert-braces (arg) + "Make a pair of braces around next ARG sexps and leave point inside. +No argument is equivalent to zero: just insert braces and leave point +between. + +If there is an active region, ARG will be ignored, braces will be +inserted around the region, and point will be left after the +closing brace." + (interactive "P") + (if (TeX-active-mark) + (progn + (if (< (point) (mark)) + (exchange-point-and-mark)) + (insert TeX-grcl) + (save-excursion + (goto-char (mark)) + (insert TeX-grop))) + (if (and arg (< arg 0)) + (progn + (save-excursion + (backward-sexp (prefix-numeric-value (- 0 arg))) + (insert TeX-grop)) + (insert TeX-grcl)) + (insert TeX-grop) + (save-excursion + (if arg (forward-sexp (prefix-numeric-value arg))) + (insert TeX-grcl))))) + +(defun TeX-back-insert-braces (arg) + (interactive "P") + (if arg (TeX-insert-braces (- 0 arg)) + (insert TeX-grcl))) + +(defun insert-char-with-padding (arg) + (interactive "*P") + (if (string= (string (preceding-char)) " ") () + (if (string= (string (preceding-char)) "\&") () (insert " "))) + (self-insert-command (prefix-numeric-value arg)) + (if (string= (string (following-char)) " ") () (insert " ")) ;; decide what to do with the point +) + +(load "latex-compile-filters.el") diff --git a/init-org.el b/init/init-org.el similarity index 80% rename from init-org.el rename to init/init-org.el index 479da4e..17a57fc 100644 --- a/init-org.el +++ b/init/init-org.el @@ -1,6 +1,9 @@ ;; Init for org-mode (require 'org-install) +(require 'org-pomodoro) +(add-hook 'org-mode-hook (lambda () + (turn-on-auto-fill))) (setq org-default-notes-file "~/org/notes.org") (global-set-key (kbd "C-c a") 'org-agenda) (global-set-key (kbd "C-c c") 'org-capture) @@ -13,5 +16,5 @@ ("e" "MailTo" entry (file+headline "~/org/notes.org" "E-mails") "* TODO mailto:%?"))) -(setq org-clock-persist ’history) +(setq org-clock-persist 'history) (org-clock-persistence-insinuate) diff --git a/misc/bibsnarf.el b/misc/bibsnarf.el new file mode 100644 index 0000000..51ce42b --- /dev/null +++ b/misc/bibsnarf.el @@ -0,0 +1,747 @@ +;;; bibsnarf --- get BibTeX format bibliography entries from the net + +;; Author: Hans Halvorson (hhalvors -at- princeton -dot- edu) +;; Version: 0.2 +;; Time-stamp: <2007-04-25 04:50:23 hhalvors> + +;;; Commentary: +;; +;; This program searches simultaneously through several bibliography +;; databases, and produces a summary of the results. You can then +;; view records (using "v"), append records to other buffers (usingz +;; "c"), or append records into local BibTeX files (using "f"). +;; +;; As of January 26, 2007, the supported search backends are: +;; +;; MathSciNet: www.ams.org/mathscinet (requires a subscription) +;; citebase: www.citebase.org +;; math arxive: front.math.ucdavis.edu +;; spires-hep: www.slac.stanford.edu/spires/ +;; +;; In theory, it is easy to add any backend for which a single URL +;; returns an html page with BibTeX formatted entries. +;; If you know of any such additional backends, please email the maintainer. +;; +;; To start a search: M-x bibsnarf RET +;; You will then be queried for Author and Title (you need only enter one of the two fields). +;; If everything goes well, in a few short seconds you will +;; find yourself in a buffer that summarizes your results, one line +;; per result. The following keybindings apply in the summary buffer: +;; +;; v - view the full BibTeX entry for the record at the point +;; SPC - ditto +;; RET - ditto +;; f - append the full BibTeX of the record at the point to some local file +;; (*CAUTION*: if you have made modifications to the file and have not saved, then you will +;; lose your changes! For that case, you should instead use "a" +;; c - append the full BibTeX of the record at the point to some buffer +;; +;; At present, all search results are dumped into a single buffer. But it would not be diffcult +;; to arrange things differently. +;; +;; +;; Technical discussion: Here is what actually happens after you ask bibsnarf to search: +;; 1. bibsnarf figures out which urls to get +;; 2. bibsnarf calls an external browser (e.g. links) to download the urls. +;; (Why not a native emacs browser, e.g. w3? For one, w3 is no longer maintained. +;; Second, using an external browser allows us to do asynchronous downloads. Maybe that is also +;; possible with w3; I don't know.) +;; 3. bibsnarf processes each downloaded html page in two stages: (a) It cleans out the html cruft, +;; hopefully (!) resulting in a valid BibTeX file. (b) It parses the BibTeX file by turning each +;; valid entry into a hash table whose keys are field names and whose values are field contents, and +;; then it makes a big hash table called *bib* whose keys are random, and whose values are the entry +;; hash tables. into a hash table called '*bib*'. Question: would it be better just to store the entries +;; in a list? Does hashing provide any advantage ;; in this case? +;; 4. bibsnarf writes out a summary string for each entry in *bib* in the buffer *bibsnarf results*. +;; + +;; requires an external web client: e.g., links, w3m, lynx + +;; TO DO: use async from url.el + +;; TO DO: add SciTation support, eprintweb.org support + +;; Acknowledgments: Much of the code is inspired by Eric Marsden's +;; watson.el, and some is borrowed from Nevin Kapur's bibfind.el. + +;;; Code: + +(require 'mm-url) +(require 'bibtex) +(require 'cl) + +(defvar bsn-summary-mode-map nil + "Keymap for the bsn-summary buffer.") + +(if bsn-summary-mode-map + () + (setq bsn-summary-mode-map (make-keymap)) + (suppress-keymap bsn-summary-mode-map) + ;; basic commands + (define-key bsn-summary-mode-map "v" 'bsn-summary-view) + (define-key bsn-summary-mode-map " " 'bsn-summary-view) + (define-key bsn-summary-mode-map [return] 'bsn-summary-view) + (define-key bsn-summary-mode-map "f" 'bsn-summary-file) + (define-key bsn-summary-mode-map "c" 'bsn-summary-copy) +) + +(defgroup bibsnarf nil + "BibSnarf: snarf a bibliography from the internet." + :group 'tools) + +(defconst bibsnarf-version "0.1" + "bibsnarf version.") + +(defvar bsn-frame-parameters '((menu-bar-lines . 0)) + "*Parameters to use when putting *bibsnarf results* buffer in a new frame.") + +(defvar bsn-frame) + +(defcustom bsn-backends '(msn arxive citebase spires) + "A list of backends to search. Currently supported: msn arxive citebase spires." + :group 'bibsnarf) + + +(defcustom bsn-notify-method 'bully + "*How to select the *bibsnarf results* buffer once it is ready. +Possible values are: + * 'newframe: create a dedicated new frame (see `bsn-frame-parameters') + * 'pushy: make *bibsnarf results* the current buffer in the current window + * 'bully: make *bibsnarf results* the current buffer and only window + * 'aggressive: make *bibsnarf results* the current buffer in the other window + * 'friendly: display *bibsnarf results* in the other window but don't make current + * 'polite: don't display *bibsnarf results*, but print message and beep when ready + * 'quiet: like `polite', but don't beep + * 'meek: make no indication that *bibsnarf results* is ready +You can also use a lisp expression that evaluates to your own notification method -- e.g. you can use \"man-notify-method\"." + :group 'bibsnarf) + + +(defun bsn-executable-exists-p (exe &rest args) + "Test whether the executable EXE exists. +Try to execute it with CALL-PROCESS with arguments ARGS, +returning its return status or nil if not found." + (condition-case nil + (apply #'call-process exe nil nil nil args) + (file-error nil))) + +(defvar bsn-get-command + ;; please send me any others which might be useful + (cond ((bsn-executable-exists-p "curl" "-h") "curl -x 127.0.01:8118") + ((bsn-executable-exists-p "links" "-version") "links -source -http-proxy 127.0.0.1:8118") + ((bsn-executable-exists-p "wget" "--version") "wget --output-document=~/out.txt") + ((bsn-executable-exists-p "lynx" "-help") "lynx -source") + ((bsn-executable-exists-p "w3m") "w3m -dump_source") + (t "")) + ) + +;; To Do: could we also invoke Firefox or Opera with -noraise flag? + +(defvar bsn-timeout 15 + "*Number of seconds to wait before assuming a request is late. +Bibsnarf will activate its buffer (according to the value of the +variable `bsn-notify-method') when all queries have completed +or after this number of seconds. If you have a slow Internet +connection it may be useful to set this to a higher value +than the default, particularly if you are using bl in +synchronous mode.") + +(defvar bsn-frame) +(defvar bsn-arguments "") +(defvar bsn-match-count "0") +(defvar bsn-timer nil) +(defvar bsn-tick 0) +(defvar bsn-jobs (make-hash-table)) +(defvar *bib* (make-hash-table :test #'equal)) + +(defvar bsn-extract-hook nil + "*Hook to run before a search-engine specific extraction function.") + +;; placate the byte-compiler +(defvar bsn-buffer-url nil) + +(defun bibsnarf () + (interactive) + (let* ((author (read-string "Author: ")) + (title (read-string "Title: "))) + (bsn-init) + (message "Looking for matches...") + (dolist (backend bsn-backends) + (bsn-fetch backend author title)))) + +(defun bsn-init () + (let ((buf (get-buffer "*bibsnarf results*"))) + (setq bsn-frame (selected-frame)) + (setq bsn-match-count "0") + (clrhash *bib*) ; remove previous matches + (clrhash bsn-jobs) ; remove any uncompleted async jobs + (setq bsn-tick 0) + (bsn-timer-start) + (when buf ; update the output buffer: ?? + (set-buffer buf) + (setq buffer-read-only nil) + (erase-buffer)))) + +;;; Main async fetch function +(defun bsn-fetch (backend author title) + (let* ((components (split-string bsn-get-command)) ; splits on whitespace + (bsn-get-program (car components)) ; e.g. "links" + (bsn-get-arguments (cdr components)) ; e.g. "-source" + (backend-str (symbol-name backend)) + (extractor (intern (concat "bsn-" backend-str "-extract"))) + (urler (intern (concat "bsn-" (symbol-name backend) "-url"))) + (url (funcall urler author title)) + ) + (apply #'bsn-add-job + `(lambda () + (run-hooks 'bsn-extract-hook) + (,extractor) + (bsn-display-matches)) + bsn-get-program + (append bsn-get-arguments (list url)) + ) + ) + ) + +(defun bsn-add-job (handler job &rest args) + (let* ((buf (generate-new-buffer " *bsn-async*")) + (proc (apply #'start-process "bsn-async" buf job args))) + (setf (gethash proc bsn-jobs) handler) + (set-process-sentinel proc #'bsn-sentinel))) + +(defun bsn-sentinel (process event) + (when (eq (process-status process) 'exit) + (let ((buf (process-buffer process)) + (handler (gethash process bsn-jobs))) + (when handler + (save-excursion + (unwind-protect + (progn + (set-buffer buf) + (funcall handler)) + (remhash process bsn-jobs) + (kill-buffer buf))))))) + + +;; (verbatim from watson.el) this is run regularly while a bsn search +;; is in progress. If all the requests have been treated, we switch to +;; the *bibsnarf results* buffer (using user-customizable method from +;; `bsn-notify-method'). If `bsn-timeout' seconds have passed without +;; all requests having finished, we display the buffer anyway. If no +;; matches have been found at timeout, display a "no matches" message. +(defun bsn-timer-function (&rest ignore) + (incf bsn-tick) + (cond ((zerop (hash-table-count bsn-jobs)) + (bsn-timer-stop) + (bsn-notify-when-ready)) + ((> bsn-tick bsn-timeout) + (bsn-timer-stop) + (if (zerop (hash-table-count *bib*)) + (message "bib search: no matches found after %s seconds" bsn-timeout) + (bsn-notify-when-ready))))) + +(defun bsn-timer-start () + (setq bsn-timer (run-with-timer 1 1 #'bsn-timer-function))) + +(defun bsn-timer-stop () + (cancel-timer bsn-timer) + (setq bsn-timer nil)) + +;; adapted from `Man-notify-method' in man.el. +(defun bsn-notify-when-ready () + "Notify the user when the *bibsnarf results* buffer is ready. +See the variable `bsn-notify-method' for the different notification behaviors." + (cond + ((eq bsn-notify-method 'newframe) + ;; Since we run asynchronously, perhaps while Emacs is waiting + ;; for input, we must not leave a different buffer current. We + ;; can't rely on the editor combibsnarfd loop to reselect the + ;; selected window's buffer. + (save-excursion + (let ((frame (make-frame bsn-frame-parameters))) + (set-window-buffer (frame-selected-window frame) "*bibsnarf results*") + (set-window-dedicated-p (frame-selected-window frame) t)))) + ((eq bsn-notify-method 'pushy) + (switch-to-buffer "*bibsnarf results*")) + ((eq bsn-notify-method 'bully) + (and window-system + (frame-live-p bsn-frame) + (select-frame bsn-frame)) + (pop-to-buffer "*bibsnarf results*") + (delete-other-windows)) + ((eq bsn-notify-method 'aggressive) + (and window-system + (frame-live-p bsn-frame) + (select-frame bsn-frame)) + (pop-to-buffer "*bibsnarf results*")) + ((eq bsn-notify-method 'friendly) + (and window-system + (frame-live-p bsn-frame) + (select-frame bsn-frame)) + (display-buffer "*bibsnarf results*" 'not-this-window)) + ((eq bsn-notify-method 'polite) + (beep) + (message "bibsnarf search results are not ready")) + ((eq bsn-notify-method 'quiet) + (message "bibsnarf search results are not ready")) + ((or (eq bsn-notify-method 'meek) + t) + (message "")))) + +;;;; SECTION: BACKENDS:: these are the databases we will search through + +;;; MathSciNet +;; N.B.: msn wants "Surname, First" +;; should we query for author firstname and author surname separately?? + +(defun bsn-msn-url (author title) + "What's the URL for MathSciNet." + (let* ((pairs `(("bdlback" . "r=1") + ("dr" . "all") + ("l" . "20") + ("pg3" . "TI") + ("s3" . ,title) + ("pg4" . "ICN") + ("s4" . ,author) + ("fn" . "130") + ("fmt" . "bibtex") + ("bdlall" . "Retrieve+All")))) + (concat "http://www.ams.org/mathscinet/search/publications.html?" (mm-url-encode-www-form-urlencoded pairs)))) + + +;;; Zentralblatt Mathematik +;;; As of Jan 2007, ZBM limits to only 3 results for non-subscribers + +(defun bsn-zbm-url (author title) + "What's the URL for ZBM?" + (let* ((pairs `(("ti" . ,title) + ("au" . ,author) + ("type" . "bibtex") + ("format" . "short") + ("maxdocs" . "20")))) + (concat "http://www.emis.de/cgi-bin/zmen/ZMATH/en/quick.html?" (mm-url-encode-www-form-urlencoded pairs)))) + +;;; MRL support +;;; As of Jan 2007, MRL seems to be defunct + +(defun bsn-mrl-url (author title) + "What's the URL for mrl?" + (let* ((pairs `(("s3" . ,author) + ("pg3" . "ICN") + ("s4" . ,title) + ("pg4" . "TI") + ("s5" . "") + ("pg5" . "JOUR") + ("format" . "bibtex") + ("Search" . "Search")))) + (concat "http://www.ams.org/mrlookup?" (mm-url-encode-www-form-urlencoded pairs)))) + +(defun bsn-msn-wash () + "Wash the output returned." + (goto-char (point-min)) + (let ((case-fold-search t)) + (when (re-search-forward "^@" nil t) + (delete-region (point-min) (match-beginning 0))) + (goto-char (point-max)) + (when (re-search-backward "" nil t) + (delete-region (point-max) (match-beginning 0))) + ;; Handle the case when nothing matches + (goto-char (point-min)) + (when (re-search-forward "No Records Selected" nil t) + (replace-match "@Comment No matches") + (delete-region (point-min) (match-beginning 0))) + (goto-char (point-max)) + (when (re-search-backward "" nil t) + (delete-region (point-max) (match-beginning 0))))) + +(defun bsn-msn-extract () + "Extract BibTeX entries from the html source delivered by MathSciNet." + ;; TO DO: informative error messages + (bsn-msn-wash) ; the result of this should be a valid BibTeX file + ; (bibtex-validate) + (bsn-read *bib* t) ; read these entries into the hashtable *bib* using "randomly" generated keys + (message "Successfully parsed MSN results buffer.") ; debugging + ) + +;; Note: arxive puts an extra pair of brackets around titles +;; (presumably to maintain capitalization); we want to strip these. + +(defun bsn-arxive-wash () + "Clean up the ArXive buffer." + (let ((case-fold-search t)) + (goto-char (point-min)) + (when (re-search-forward "
@" nil t)
+      (delete-region (point-min) (match-beginning 0)))
+    (goto-char (point-max))
+    (when (re-search-backward "
" nil t) + (delete-region (point-max) (match-beginning 0))) + (goto-char (point-min)) + (while (re-search-forward + (concat "^
\\|^
\\|\\|") ;; syntactic hack to allow posting on emacswiki + nil t) + (replace-match "")) + ;; Handle the case when no matches are found + (goto-char (point-min)) + (when (re-search-forward "Query not found" nil t) + (replace-match "@Comment No matches") + (delete-region (point-min) (match-beginning 0))) + (goto-char (point-max)) + (when (re-search-backward "" nil t) + (delete-region (point-max) (match-beginning 0))))) + +(defun bsn-arxive-extract () + (bsn-arxive-wash) + (bsn-read *bib* t) ; optional t to assign random external keys + (message "Successfully parsed ARXIVE results buffer.") + ) + +(defun bsn-citebase-extract () + (bsn-read *bib* t) + (message "Successfully parsed CITEBASE results buffer.") + ) + +(defun bsn-spires-extract () + (bsn-read *bib* t) + (message "Successfully parsed SPIRES results buffer.") + ) + +;;; math arXive support + +(defun bsn-arxive-url (author title) + (concat "http://front.math.ucdavis.edu/search?" + "a=" (mm-url-form-encode-xwfu author) + "&" + "t=" (mm-url-form-encode-xwfu title) + "&" + "s=BibTeX")) + +;;; CITEBASE support + +(defun bsn-citebase-wash () + t) + +(defun bsn-citebase-url (author title) + (let* ((pairs `(("submitted" . "Search") + ("author" . ,author) + ("format" . "BibTeX") + ("yearfrom" . "") + ("maxrows" . "100") + ("order" . "DESC") + ("yearuntil" . "") + ("publication" . "") + ("title" . ,title) + ("type" . "metadata") + ("rank" . "accession") ; in what order should we list? + ))) + (concat "http://www.citebase.org/search?" (mm-url-encode-www-form-urlencoded pairs)))) + +;; no html washing necessary for citebase + +;;; SPIRES-HEP support + +;; Note that the SPIRES server is quite slow .... maybe don't search +;; it if you're in a hurry + +(defun bsn-spires-rawcmd (author title) + (cond + ((zerop (length author)) (concat "T+" title)) + ((zerop (length title)) (concat "A+" author)) + (t (concat "A+" author "+and+" "T+" title)))) + +(defun bsn-simple-encode (pairs) + (cond + ((not pairs) nil) + ((= (length pairs) 1) (concat (caar pairs) "=" (cdar pairs))) + (t (concat (bsn-simple-encode (list (car pairs))) "&" (bsn-simple-encode (cdr pairs)))))) + +(defun bsn-spires-url (author title) + (let* ((rawcmd (bsn-spires-rawcmd author title)) + (pairs `(("rawcmd" . ,rawcmd) + ("FORMAT" . "wwwbriefbibtex") + ("SEQUENCE" . "")))) + (concat "http://www.slac.stanford.edu/spires/find/hep/www?" (bsn-simple-encode pairs)))) + +(defun bsn-spires-wash () + "Wash the output returned." + (goto-char (point-min)) + (let ((case-fold-search t)) + (re-search-forward "" nil t) + (delete-region (point-min) (match-end 0)) + (goto-char (point-max)) + (re-search-backward "" nil t) + (delete-region (point-max) (match-beginning 0)) + (goto-char (point-min)) + (while (search-forward-regexp "<[a-z]+>\\|") + (replace-match "")) + ;; TO DO: Handle the case when nothing matches + ) + ) + +(defun bsn-wash (backend) + (cond + ((string= backend "msn") (lambda () (bsn-msn-wash))) + ((string= backend "arxive") (lambda () (bsn-arxive-wash))) + ((string= backend "spires") (lambda () (bsn-spires-wash))) + (t (lambda () t)))) + +(defun bsn-gethash (key hash) + ; a gethash function that ignores the case of the key, and that + ; returns an empty string if there is nothing that matches (because + ; we cannot use 'truncate-string-to-width' on 'nil'. + (or (gethash key hash) (gethash (upcase key) hash) (gethash (downcase key) hash) "")) + +(defun bsn-record-summary-string (hash) + (let* ((author (truncate-string-to-width (bsn-gethash "author" hash) 20)) + (title (truncate-string-to-width (bsn-gethash "title" hash) 40)) + (title (remove ?\{ (remove ?\} title))) + (journal (truncate-string-to-width (bsn-gethash "journal" hash) 25)) + (volume (bsn-gethash "volume" hash)) + (year (bsn-gethash "year" hash)) + (pages (bsn-gethash "pages" hash))) + (format " %-25s %-45s %-28s : %-10s (%s)" (concat "[ " author " ]") (concat "\"" title "\"") journal pages year))) + +(defun bsn-display-match (hash) + (message "asdfasdf") + (let (first start local-start end) + (goto-char (point-max)) + (setq first (point)) + (setq start (point)) + ; (if (gethash key *bib*) ; debug + (insert (bsn-record-summary-string hash)) + (setq end (point)) + (add-text-properties start end '(face bsn-summary-default-face)) ;;; FIX + (insert "\n"))) + +(defvar helper nil) + +(defun bsn-really-display-matches () + (let ((buf (get-buffer-create "*bibsnarf results*"))) + (save-excursion + (set-buffer buf) + (setq buffer-read-only nil) + (erase-buffer) + (set (make-local-variable 'helper) (make-hash-table :test #'equal)) ; aux will keep track of where entries are inserted + (loop for k being the hash-keys in *bib* using (hash-value v) do + (puthash (line-number-at-pos) k helper) + (bsn-display-match v)) + (goto-char (point-min)) + (bsn-summary-mode) + (set-buffer-modified-p nil)))) + +(defun bsn-display-matches () + ;; display them, avoiding locking up emacs if possible. For some + ;; reason the XEmacs #'run-with-idle-timer doesn't work. + (if (and (fboundp 'run-with-idle-timer) + (not (featurep 'xemacs))) + (run-with-idle-timer 1 nil #'bsn-really-display-matches) + (bsn-really-display-matches))) + + +;;;; Reconstitute BibTeX format entries from hash ;;;;;;;;;;;;;;;;;; + +(defun bsn-print-bibtex-string (key bibhash) + (let ((record (gethash key bibhash))) + (concat (format "@%s{ %s,\n" (gethash "=type=" record) (gethash "=key=" record)) + (substring + (apply #'concat + (loop for k being the hash-keys in record using (hash-value v) + collect (unless (or (equal k "=key=") (equal k "=type=")) + (format "%15s = {%s},\n" k v)) + ) + ) 0 -2) + "\n}" + ) + ) + ) + +(defun bsn-print-bibtex (key bibhash) + (insert (concat "\n" (bsn-print-bibtex-string key bibhash) "\n\n"))) + + +;;;;;;; actions in the summary buffer + +(defun bsn-display-record (key bibhash) + (let ((origin (buffer-name))) + (pop-to-buffer "*bibsnarfed record*") + (setq buffer-read-only nil) + (erase-buffer) + (bibtex-mode) + (goto-char (point-min)) + (bsn-print-bibtex key bibhash) + (shrink-window-if-larger-than-buffer) ; FIXME: this needs to be recalibrated for each record + (goto-char (point-min)) + (setq buffer-read-only t) + (pop-to-buffer origin) + )) + +(defun bsn-display-rec (line-no bibhash) + ;; give line number in summary buffer and relevant bibhash, display the full BibTeX record + (if (gethash line-no helper) ; check first that we have a valid line number + (let ((key (gethash line-no helper))) + (bsn-display-record key bibhash) + (message "")) ; hack to erase previous error messages + (message "No record here to view."))) + +(defun bsn-file-record (key bibhash) + (interactive) + (let* ((record (gethash key bibhash)) + (file (read-file-name (format "Append record \"%s\" to file: " (gethash "=key=" record)))) + (bibstring (concat "\n\n" (bsn-print-bibtex-string key bibhash)))) + (write-region bibstring nil file t) + (message (format "Record \"%s\" appended to %s" key file)))) + +(defun bsn-file-rec (line-no bibhash) + (interactive) + (if (gethash line-no helper) + (let ((key (gethash line-no helper))) + (bsn-file-record key bibhash) + ) + (message "No record here to file."))) + +(defun bsn-summary-file () + (interactive) + (let ((line-no (line-number-at-pos))) + (bsn-file-rec line-no *bib*))) + +(defun bsn-summary-view () + (interactive) + (let ((line-no (line-number-at-pos))) + (bsn-display-rec line-no *bib*))) + + +;; the following is similar to 'append-to-buffer' in simple.el, but +;; that takes a region as input + +(defun bsn-copy-record (key bibhash) + (interactive) + (let* ((record (gethash key bibhash)) + (buffer (read-buffer (format "Append record \"%s\" to buffer: " (gethash "=key=" record)) (other-buffer (current-buffer) t))) + (oldbuf (current-buffer)) + (bibstring (concat "\n\n" (bsn-print-bibtex-string key bibhash)))) + (save-excursion + (let* ((append-to (get-buffer-create buffer)) + (windows (get-buffer-window-list append-to t t)) + point) + (set-buffer append-to) + (setq point (point)) + (barf-if-buffer-read-only) + (insert bibstring) + (dolist (window windows) + (when (= (window-point window) point) + (set-window-point window (point)))))))) + +(defun bsn-copy-rec (line-no bibhash) + (interactive) + (if (gethash line-no helper) + (let ((key (gethash line-no helper))) + (bsn-copy-record key bibhash) + ) + (message "No record here to copy."))) + +(defun bsn-summary-copy () + (interactive) + (let ((line-no (line-number-at-pos))) + (bsn-copy-rec line-no *bib*))) + +(defvar helper (make-hash-table :test #'equal)) ; buffer local variable to keep association of bibrecords and line numbers + +(defun bsn-summary-mode () +; TO DO: modeline + (setq major-mode 'bsn-summary-mode) + (setq mode-name "bibsnarf summary") + (use-local-map bsn-summary-mode-map) + ) + +(defun bsn-print-summary (bib-hash buffer-name) + (pop-to-buffer buffer-name) + (setq buffer-read-only nil) + (erase-buffer) + (loop for k being the hash-keys in bib-hash using (hash-value v) + do + (insert (format " [ %s ] %s\n" (cl-gethash "author" v) (cl-gethash "title" v)))) + (setq buffer-read-only t)) + + + +;; TO DO: underline the record at which the point is located + +(defgroup bsn-summary-faces nil + "BibSnarf, Faces of summary buffer." + :prefix "bsn-highlight-" + :group 'bibsnarf) + +(defface bsn-summary-default-face + '( + (((type tty) + (background dark)) + (:foreground "blue")) + (((class color) + (background dark)) + (:foreground "GreenYellow")) + (((class color) + (background light)) + (:foreground "green4"))) + "Face used for displaying bibliography record summaries." + :group 'bibsnarf) + +;;; BibTeX parsing + +;; compare the following with bibtex-parse-entry (in bibtex.el), which +;; converts the entry to an association list. This is just like that, +;; except that we store the entry in a hash table. + +(defvar bounds nil) + +(defun bsn-parse-entry (&optional content) + "Parse entry at point, return a hash table. +The hash table elements have the form (FIELD . TEXT), where FIELD +and TEXT are strings, and FIELD can also be the special strings +\"=type=\" and \"=key=\". For the FIELD \"=key=\" TEXT may be +nil. Remove \"OPT\" and \"ALT\" from FIELD. Move point to the +end of the last field. If optional arg CONTENT is non-nil +extract content of text fields." + (let (alist (entry (make-hash-table :test #'equal :size 14))) + (when (looking-at bibtex-entry-maybe-empty-head) + (puthash "=type=" (bibtex-type-in-head) entry) + (puthash "=key=" (bibtex-key-in-head) entry) + (goto-char (match-end 0)) + (while (setq bounds (bibtex-parse-field)) + (puthash (bibtex-name-in-field bounds t) + (bibtex-text-in-field-bounds bounds content) + entry) + (goto-char (bibtex-end-of-field bounds)))) + entry)) + + +(defun bsn-read (output &optional random) + "Read bibliography into an already existing hash table OUTPUT. +If optional argument is set to t, then we generate hash keys from +the current time (to avoid conflicts with previously added +entries)." + (goto-char (point-min)) + (while (bibtex-skip-to-valid-entry) + (let* ((internal-key (bibtex-key-in-head)) + (external-key (if random (current-time) + internal-key))) + (puthash external-key (bsn-parse-entry t) output))) + output) + +(provide 'bibsnarf) + + +;;;;; TO DO: journal shortname display replacement strings; e.g. "Communications in Mathematical Physics" ==> "CMP" + +;; (defun bsn-summary-dump () +;; "Dump the entire bibliography into a file." +;; (interactive) +;; ; query for filename +;; ) + +; (defun bsn-copy-record (line-no bibhash) +; (interactive ;; destination bibliography + +; (defun bsn-delete-record (line-no bibhash) +; (interactive) + + +;;; end of file bibsnarf.el diff --git a/misc/highlight-sexps.el b/misc/highlight-sexps.el new file mode 100644 index 0000000..02eac32 --- /dev/null +++ b/misc/highlight-sexps.el @@ -0,0 +1,196 @@ +;;; highlight-sexps.el --- highlight surrounding parentheses +;; +;; Copyright (C) 2011 David Rysdam +;; +;; Author: David Rysdam +;; Version: 0.9.1 +;; Keywords: faces, matching, s-expression, sexp +;; URL: http://david.rysdam.org/src/emacs/highlight-sexps.el +;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x +;; +;; Based on highlight-parentheses: +;; +;; Author: Nikolaj Schumacher +;; Version: 1.0.1 +;; Keywords: faces, matching +;; URL: http://nschum.de/src/emacs/highlight-parentheses/ +;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x +;; +;; This file is NOT part of GNU Emacs. +;; +;; 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 2 +;; 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: +;; +;; Add the following to your .emacs file: +;; (require 'highlight-sexps) +;; +;; Enable `highlight-sexps-mode'. +;; +;; Or also add one or both of the following your .emacs file: +;; (add-hook 'lisp-mode-hook 'highlight-sexps-mode) +;; (add-hook 'emacs-lisp-mode-hook 'highlight-sexps-mode) +;; +;; highlight-sexps-mode supports customization. You will likely find +;; it most useful to customize the hl-sexp-background-colors +;; variable. The number of nexted s-expressions highlighted is +;; determined by the number of colors defined. +;; +;;; Change Log: +;; +;; 2012-01-31 (0.9.1) +;; lisp-mode namespace collision fixed (but probably not The Right +;; Way) +;; +;; 2012-01-31 (0.9) +;; Initial Release. +;; +;;; Code: + +(eval-when-compile (require 'cl)) + +(provide 'highlight-sexps) + +(defgroup highlight-sexps nil + "Highlight the nested s-expressions around point" + :group 'faces + :group 'matching) + +(defun hl-sexp-set (variable value) + (set variable value) + (when (fboundp 'hl-sexp-color-update) + (hl-sexp-color-update))) + +(defcustom hl-sexp-colors + nil + "*List of colors for the highlighted parentheses. +The list starts with the the inside parentheses and moves +outwards." + :type '(repeat color) + :set 'hl-sexp-set + :group 'highlight-sexps) + +(defcustom hl-sexp-background-colors + '("cyan" "white") + "*List of colors for the background highlighted parentheses. +The list starts with the the inside parentheses and moves +outwards." + :type '(repeat color) + :set 'hl-sexp-set + :group 'highlight-sexps) + +(defface hl-sexp-face nil + "*Face used for highlighting parentheses. +Color attributes might be overriden by `hl-sexp-colors' and +`hl-sexp-background-colors'." + :group 'highlight-sexps) + +(defvar hl-sexp-overlays nil + "This buffers currently active overlays.") +(make-variable-buffer-local 'hl-sexp-overlays) + +(defvar hl-sexp-last-point 0 + "The last point for which parentheses were highlighted. +This is used to prevent analyzing the same context over and +over.") +(make-variable-buffer-local 'hl-sexp-last-point) + +(defun hl-sexp-highlight () + "Highlight the nested s-expressions around point" + (unless (= (point) hl-sexp-last-point) + (setq hl-sexp-last-point (point)) + (let ((overlays hl-sexp-overlays) + (sexp-list (hl-sexp-end-points (point) + (length hl-sexp-overlays))) + pos1 pos2) + (condition-case err + (while (and overlays sexp-list) + (let* ((overlay (pop overlays)) + (sexp (pop sexp-list)) + (pos1 (car sexp)) + (pos2 (cadr sexp))) + (move-overlay overlay pos1 pos2))) + (error nil)) + (dolist (ov overlays) + (move-overlay ov 1 1))))) + +;;;###autoload +(define-minor-mode highlight-sexps-mode + "Minor mode to highlight an expanding set of surrounding s-expressions." + nil " hl-s" nil + (if highlight-sexps-mode + (progn + (hl-sexp-create-overlays) + (add-hook 'post-command-hook 'hl-sexp-highlight nil t)) + (mapc 'delete-overlay hl-sexp-overlays) + (kill-local-variable 'hl-sexp-overlays) + (kill-local-variable 'hl-sexp-last-point) + (remove-hook 'post-command-hook 'hl-sexp-highlight t))) + +(defun hl-sexp-create-overlays () + "Create some 'overlays-in-waiting' with the right priorities and attributes." + (let* ((fg hl-sexp-colors) + (bg hl-sexp-background-colors) + (count (max (length fg) (length bg))) + (num count) + attributes) + (while (> num 0) + (setq attributes (face-attr-construct 'hl-sexp-face)) + (when (car fg) + (setq attributes (plist-put attributes :foreground (car fg)))) + (pop fg) + (when (car bg) + (setq attributes (plist-put attributes :background (car bg)))) + (pop bg) + (push (make-overlay 0 0) hl-sexp-overlays) + (overlay-put (car hl-sexp-overlays) 'face attributes) + (overlay-put (car hl-sexp-overlays) 'priority num) + (decf num)) + (setq hl-sexp-overlays (nreverse hl-sexp-overlays)))) + +(defun hl-sexp-color-update () + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when hl-sexp-overlays + (mapc 'delete-overlay hl-sexp-overlays) + (setq hl-sexp-overlays nil) + (hl-sexp-create-overlays) + (let ((hl-sexp-last-point -1)) ;; force update + (hl-sexp-highlight)))))) + +(defun hl-sexp-start-of-sexp (pt) + "Start of the s-expression surrounding PT." + (save-excursion (cadr (syntax-ppss pt)))) + +(defun hl-sexp-end-of-sexp (pt) + "End of s-expression that matches beginning point PT." + (condition-case nil + (scan-sexps pt 1) + (error nil))) + +(defun hl-sexp-end-points (pt n) + "Get beginning and ending points of N depths of s-expressions +surrounding PT." + (let (results prev next + (p pt)) + (dotimes (i n (nreverse results)) + (setq prev (hl-sexp-start-of-sexp p)) + (when prev + (setq next (hl-sexp-end-of-sexp prev)) + (when next + (push (list prev next) results) + (setq p (1- prev))))))) + +;;; highlight-sexps.el ends here + diff --git a/latex-compile-filters.el b/misc/latex-compile-filters.el similarity index 100% rename from latex-compile-filters.el rename to misc/latex-compile-filters.el diff --git a/misc/org-clock-save.el b/misc/org-clock-save.el new file mode 100644 index 0000000..63ff8b3 --- /dev/null +++ b/misc/org-clock-save.el @@ -0,0 +1 @@ +;; org-persist.el - fourspoons at <2014-12-11 Thu 09:27> diff --git a/wordnik-synonym.el b/misc/wordnik-synonym.el similarity index 100% rename from wordnik-synonym.el rename to misc/wordnik-synonym.el diff --git a/org-clock-save.el b/org-clock-save.el new file mode 100644 index 0000000..c39e936 --- /dev/null +++ b/org-clock-save.el @@ -0,0 +1 @@ +;; org-persist.el - fourspoons at <2014-12-23 Tue 15:11> diff --git a/org-pomodoro b/org-pomodoro new file mode 160000 index 0000000..3ab61f9 --- /dev/null +++ b/org-pomodoro @@ -0,0 +1 @@ +Subproject commit 3ab61f959214b8ce76aad8a4ae52320652eca29b diff --git a/predictive b/predictive new file mode 160000 index 0000000..9ab439e --- /dev/null +++ b/predictive @@ -0,0 +1 @@ +Subproject commit 9ab439efba008834ccf37b6a80a953cf2da6e40d