parent
f1130d19fe
commit
f1062c1a11
18 changed files with 1280 additions and 123 deletions
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 6f360b3901edce0b4dbdfd1fdc15a99f78cbfc8a |
||||||
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 9725bd8bbf9109903d54cb0c850ab81a27d261c5 |
||||||
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 0ef000bac76abae30601222e6f06c7d133ab4942 |
||||||
@ -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-<return>") |
|
||||||
(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") |
|
||||||
@ -0,0 +1,5 @@ |
|||||||
|
(add-hook 'c-mode-hook 'linum-mode) |
||||||
|
|
||||||
|
(add-hook 'c++-mode-hook (lambda () |
||||||
|
(linum-mode) |
||||||
|
(subword-mode))) |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
(add-hook 'c-mode-hook 'linum-mode) |
||||||
|
|
||||||
|
(add-hook 'c++-mode-hook (lambda () |
||||||
|
(linum-mode) |
||||||
|
(subword-mode)) |
||||||
@ -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-<return>") |
||||||
|
(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") |
||||||
@ -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 "</pre>" 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 "</title>" 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 "<dt><pre>@" nil t) |
||||||
|
(delete-region (point-min) (match-beginning 0))) |
||||||
|
(goto-char (point-max)) |
||||||
|
(when (re-search-backward "</pre>" nil t) |
||||||
|
(delete-region (point-max) (match-beginning 0))) |
||||||
|
(goto-char (point-min)) |
||||||
|
(while (re-search-forward |
||||||
|
(concat "^<dt><pre>\\|^</pre></td>\\|<a href" "=.*?>\\|</a>") ;; 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 "</title>" 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 "<!-- START RESULTS -->" nil t) |
||||||
|
(delete-region (point-min) (match-end 0)) |
||||||
|
(goto-char (point-max)) |
||||||
|
(re-search-backward "<!-- END RESULTS -->" nil t) |
||||||
|
(delete-region (point-max) (match-beginning 0)) |
||||||
|
(goto-char (point-min)) |
||||||
|
(while (search-forward-regexp "<[a-z]+>\\|</[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 |
||||||
@ -0,0 +1,196 @@ |
|||||||
|
;;; highlight-sexps.el --- highlight surrounding parentheses |
||||||
|
;; |
||||||
|
;; Copyright (C) 2011 David Rysdam |
||||||
|
;; |
||||||
|
;; Author: David Rysdam <david * rysdam org> |
||||||
|
;; 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 <bugs * nschum de> |
||||||
|
;; 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 <http://www.gnu.org/licenses/>. |
||||||
|
;; |
||||||
|
;;; 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 |
||||||
|
|
||||||
@ -0,0 +1 @@ |
|||||||
|
;; org-persist.el - fourspoons at <2014-12-11 Thu 09:27> |
||||||
@ -0,0 +1 @@ |
|||||||
|
;; org-persist.el - fourspoons at <2014-12-23 Tue 15:11> |
||||||
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 3ab61f959214b8ce76aad8a4ae52320652eca29b |
||||||
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 9ab439efba008834ccf37b6a80a953cf2da6e40d |
||||||
Loading…
Reference in new issue