;;;_+ Make it easy to yank quotes into my quote file (defvar sacha/research/quote-default "" "Stores the BibTeX key for the paper I'm currently reading.") (defadvice bibtex-clean-entry (after sacha activate) "Set default key based on the current record." (save-excursion (setq sacha/research/quote-default (bibtex-key-in-head))) (set-register ?a (format "\n\\cite{%s}\n%%" sacha/research/quote-default)) (set-register ?b sacha/research/quote-default) (set-register ?c (format "\\cite{%s}" sacha/research/quote-default))) (global-set-key (kbd "") (lambda () (interactive) (insert-register ?c))) (defvar sacha/research/quote-file "/home/sacha/notebook/research/quotes" "File with my research notes.") (defun sacha/research/quote () "Paste the quote into `sacha/research/quote-file'." (interactive) (with-current-buffer (find-file-noselect sacha/research/quote-file) (goto-char (point-max)) (yank) (unless (bolp) (insert "\n")) (insert "\\cite{" sacha/research/quote-default "}\n%\n"))) (defvar sacha/research/quote-history nil) (defvar sacha/research/read-bibliography-file "/home/sacha/notebook/research/read.bib" "Filename for read papers.") (defvar sacha/research/current-bibliography-file "/home/sacha/notebook/research/research.bib" "Filename for toread papers.") (defalias 'done 'sacha/research/read) (defun sacha/research/read (filename) (interactive) (rename-file filename (concat "/home/sacha/notebook/research/papers/read/" sacha/research/quote-default "." (file-name-extension filename))) (sacha/research/mark-read sacha/research/quote-default)) (global-set-key (kbd "`") 'sacha/research/quote) (defun sacha/research/next-sentence () (interactive) (set-mark-command nil) (forward-sentence)) (defun sacha/research/save-paper () (interactive) (if current-prefix-arg (sacha/research/download-paper) (write-file (expand-file-name sacha/research/quote-default "/home/sacha/notebook/research/papers")))) (defun sacha/research/download-paper () (interactive) (let ((url (or (w3m-anchor) (w3m-image)))) (if url (let ((proc (start-process "wget" (format "*wget %s*" url) "wget" url "-x" "--passive-ftp" "-nv" "-O" (expand-file-name sacha/research/quote-default "/home/sacha/notebook/research/papers/" )))) (with-current-buffer (process-buffer proc) (erase-buffer)) (set-process-sentinel proc (lambda (proc str) (message "wget download done")))) (message "Nothing to get")))) (defun sacha/research/mark-read (key) "Mark a paper as read." (interactive (list (unless current-prefix-arg sacha/research/quote-default))) ; Remove this BiBTeX entry and put it in sacha/research/read-bibliography-file (with-current-buffer (find-file-noselect sacha/research/current-bibliography-file) (if (or (null key) (bibtex-find-entry key)) (progn (let ((text (buffer-substring-no-properties (bibtex-beginning-of-entry) (bibtex-end-of-entry)))) (with-current-buffer (find-file-noselect sacha/research/read-bibliography-file) (goto-char (point-max)) (unless (bolp) (insert "\n")) (insert "\n" text))) (delete-region (bibtex-beginning-of-entry) (bibtex-end-of-entry))) (error "No entry %s found." key)))) (defun sacha/research/bibtex-count-entries (&optional count-string-entries) "Count number of entries in current buffer or region. With prefix argument COUNT-STRING-ENTRIES count all entries, otherwise count all entries except @String entries. If mark is active count entries in region, if not in whole buffer." (interactive "P") (let ((number 0) (bibtex-sort-ignore-string-entries (not count-string-entries))) (save-restriction (if mark-active (narrow-to-region (region-beginning) (region-end))) (bibtex-map-entries (lambda (key beg end) (setq number (1+ number))))) (if (interactive-p) (message "%s contains %d entries." (if mark-active "Region" "Buffer") number) number))) (defun sacha/research/count () (interactive) (let (read toread mark-active) (with-current-buffer (find-file-noselect sacha/research/read-bibliography-file) (setq read (sacha/research/bibtex-count-entries))) (with-current-buffer (find-file-noselect sacha/research/current-bibliography-file) (setq toread (sacha/research/bibtex-count-entries))) (set-register ?c (format "%s papers read.
\n%s papers to go.
\n" read toread)) (message "%s papers read. %s papers to go" read toread))) (defun sacha/research/beginning-of-cookie () "Move point to beginning of cookie." (re-search-backward "^%" (point-min) 'move) (if (looking-at "^%") (forward-line 1)) (point)) (defun sacha/research/end-of-cookie () "Move point to end of cookie." (re-search-forward "^%" (point-max) 'move) (when (looking-back "^%") (backward-char 1)) (point)) (defun sacha/research/narrow-to-cookie () "Narrow buffer to cookie." (narrow-to-region (sacha/research/beginning-of-cookie) (sacha/research/end-of-cookie))) (defun sacha/research/next-cookie () "Moves to next cookie. Returns nil if not found." (sacha/research/end-of-cookie) (forward-line 1) (unless (eobp) (skip-chars-forward "[:space:]\n") (not (eobp)))) (defun sacha/research/previous-cookie () "Moves to previous cookie. Returns nil if not found." (interactive) (sacha/research/beginning-of-cookie) (unless (bobp) (forward-line -1))) (defvar sacha/research/default-tag "" "Default tags") (defun sacha/research/tag (tags) "Add tags to current quote." (interactive (list (split-string (read-string "Tags: ") " " t))) (save-restriction (sacha/research/narrow-to-cookie) (unless (listp tags) (setq tags (list tags))) (while tags (goto-char (point-min)) (unless (re-search-forward (format "\\tag{%s}" (car tags)) nil t) (if (re-search-forward "\\tag{" nil t) (progn (end-of-line) (insert " \\tag{" (car tags) "}")) (goto-char (point-max)) (unless (bolp) (insert "\n")) (insert "\n\\tag{" (car tags) "}\n"))) (setq tags (cdr tags))))) (defun sacha/research/show-next () (interactive) (widen) (when (sacha/research/next-cookie) (sacha/research/narrow-to-cookie))) (defun sacha/research/show-previous () (interactive) (widen) (when (sacha/research/previous-cookie) (sacha/research/narrow-to-cookie))) (defun sacha/research/reset () (interactive) (widen) (goto-char (point-min)) (sacha/research/narrow-to-cookie)) (defvar sacha/research/quote-mode-map (let ((map (make-sparse-keymap))) (define-key map " " 'sacha/research/show-next) (define-key map (kbd "") 'sacha/research/show-previous) (define-key map "1" (lambda () (interactive) (sacha/research/tag "1") (sacha/research/show-next))) (define-key map "2" (lambda () (interactive) (sacha/research/tag "2") (sacha/research/show-next))) (define-key map "3" (lambda () (interactive) (sacha/research/tag "3") (sacha/research/show-next))) (define-key map "4" (lambda () (interactive) (sacha/research/tag "4") (sacha/research/show-next))) (define-key map "5" (lambda () (interactive) (sacha/research/tag "5") (sacha/research/show-next))) (define-key map "6" (lambda () (interactive) (sacha/research/tag "6") (sacha/research/show-next))) (define-key map "7" (lambda () (interactive) (sacha/research/tag "7") (sacha/research/show-next))) (define-key map "8" (lambda () (interactive) (sacha/research/tag "8") (sacha/research/show-next))) (define-key map "9" (lambda () (interactive) (sacha/research/tag "9") (sacha/research/show-next))) (define-key map "0" 'sacha/research/reset) map) "Keymap for `sacha/research/quote-mode'.") (define-derived-mode sacha/research/quote-mode text-mode nil "Quote" "Quick tagging of quotes. \\{sacha/research/quote-mode-map}") (defun sacha/research/randomize-quotes () (sort-subr nil nil (lambda () (sacha/research/next-cookie)) 'random))