(require (quote TeX-mode)) (defconst tex-cite-tmp "--- TeX Bibliography Scratch Buffer ---") (defconst tex-cite-window "--- TeX Bibliography Lookup Help ---") (defvar tex-master-buffer nil "\ Buffer for document master.") (defconst tex-cite-query-buffer-name "TeX-Cite-Query") (defvar tex-cite-wildcard nil "\ List of files matching *.bib in tex-bib-path") (defconst tex-cite-ext ".bib") (defvar tex-cite-document-directory nil "\ Directory containing document file") (defvar tex-cite-note-on nil "\ A flag t if note field required.") (defvar tex-cite-cite-on nil "\ A flag t if cite, nil if nocite.") (defconst tex-cite-cite-str "\\cite") (defconst tex-cite-nocite-str "\\nocite") (defvar tex-cite-mfs-last-regexp nil "\ Last regular expression used by multifile search") (defvar tex-cite-mfs-last-file-list nil "\ Last file list used by multifile search") (defvar tex-cite-mfs-front nil "\ Front of file list") (defvar tex-cite-mfs-tail nil "\ Back of file list. Car of this list is the current file") (defvar tex-cite-mfs-last-back nil "\ Last value of BACK used by mfs") (defvar tex-cite-search-last-query nil "\ Last query passed to tex-cite-search") (defvar tex-cite-last-query nil) (defvar tex-cite-query-field-labels nil "\ A list of the strings which act as labels for the fields of the query template") (defvar tex-cite-query-fields-alist nil "\ An association list which maintains the relationship between the labels of the template fields and the normal BibTeX fields the label stands for.") (defconst tex-cite-bibmsg (concat ".bib filename (default *.bib in " tex-bib-env "): ")) (defvar tex-cite-query-lookup-response (quote (((13 121) "RET" yes) ((27) "ESC" yes-more) ((32 110) "SPC" next) ((127 112) "DEL" previous) ((115) "s" show) ((70) "F" new-file) ((75) "K" new-key-from-top) ((107) "k" new-key) ((117) "u" note-switch) ((109) "m" cite-switch) ((18) "C-r" redit) ((3) "C-c=exit" quit) ((63) "?=help" help))) "\ Data for lookup prompt") (defvar tex-cite-query-failure-response (quote (((70) "F" new-file) ((75) "K" new-key-from-top) ((101) "e" new-entry) ((18) "C-r" redit) ((3) "C-c=exit" quit) ((63) "?=help" help))) "\ Data for prompt upon failure of search") (defvar tex-cite-lookup-window-config nil "\ Last window configuration used in tex-cite-lookup") (defvar tex-cite-lookup-show nil "\ Flag is non-nil if user wants show-window") (defun tex-cite-cite (&optional note) "\ Make a citation entry. If C-u is given as a prefix, prompt for the optional note field." (interactive "P") (byte-code "ˆ!\"!" [note t nil message "Looking up .bib files for a citation..." tex-cite-entry-merge "Looking up .bib files for a citation...done"] 4)) (defun tex-cite-nocite nil "\ Make a pseudo-citation entry." (interactive) (byte-code "!\"!" [nil message "Looking up .bib files for a pseudo citation..." tex-cite-entry-merge "Looking up .bib files for a pseudo citation...done"] 4)) (defun tex-cite-forms-toggle nil (interactive) (byte-code "!‰!" [tex-cite-use-full-query nil t message "Disabling Full Query Lookup ... (enabling regular expression)" "Enabling Full Query Lookup ... (disabling regular expression)"] 3)) (defun tex-cite-clear-file-list nil (interactive) (byte-code "!" [tex-cite-wildcard nil message "Clearing List of .bib files ... done"] 2)) (defun tex-cite-case-toggle nil (interactive) (byte-code "!‰!" [tex-cite-case-fold-search nil t message "Setting citation search to be Case Sensitive ... done" "Setting citation search to be Case Insensitive ... done"] 3)) (defun tex-cite-entry-merge (note-on cite-on) (byte-code "   V  \"  @ 8?\"E\" R!." [tex-cite-note-on note-on tex-cite-cite-on cite-on result continue t cite-string entry-id tex-cite-cite-str tex-cite-nocite-str tex-cite-lookup nil 1 tex-cite-with-note tex-cite-without-note tex-cite-biblist] 8)) (defun tex-cite-with-note (cite-string entry-id) (byte-code "!\"ǂQ &*" [str note cite-string entry-id read-string "Citation note field: " string-equal "" "[" "]" insert 126 123 125] 9)) (defun tex-cite-without-note (cite-string entry-id) (byte-code " Q#!)c!!!`!V0!#)> %_ \"U\" !_ b\")*k %)" [regexp cite-string nil t entries insert-point entry-id "\\" "\\s *{\\([^}]*\\)}" search-backward looking-at vortex-parse-comma-list vortex-match-string 1 match-end 0 re-search-backward "\\w\\| [ ]* " insert "~" "{" "}" vortex-memq message "Entry {%s} already cited in this list." beep sit-for 2 ","] 20)) (defun tex-cite-biblist nil "\ Add the .bib file FN to the \\bibliography list. Create one if necessary." (byte-code " @O!!  O \" !qdb#R !#FȂOSb \"]# #)-" [fn-pre tex-cite-mfs-tail fn-nd-pre fd pre tex-bib-path eoe tex-master-buffer nil t 0 -4 file-name-nondirectory file-name-directory vortex-memq -1 re-search-backward "\\\\bibliography *{.*}" search-forward match-end insert 44 "\\\\end *$\\|\\\\bye *$\\|\\\\end{document}\\|\\\\input.*-.*$" " \\bibliography{" "} "] 12)) (defun tex-cite-master nil (byte-code " ! ‚!p))" [master-file tex-master-buffer nil tex-check-master-file get-file-buffer find-file] 5)) (defun tex-cite-fn-ext (fn suffix) "\ Attach SUFFIX to the base of FN, if FN has no extension or has extension `.bib'. Otherwise (i.e FN has other extension) FN itself is returned." (byte-code " \"Ă \"ĉ ' O P( *" [base fn ext t nil suffix string-match "\\.bib" "\\." 0] 5)) (defun tex-cite-list-wildcard (ext path) "\ Return a list of files with extension EXT in PATH (list of directories)." (byte-code " !q ' @% A\"d &\"b!NĂ|m?x!]Ăm`! `\" B! N !)+" [tmp tex-cite-tmp args lst nil path ext tex-bib-env shell-file-name t get-buffer-create "/bin/ls" erase-buffer concat " " "/*" message "Looking for *.bib in path %s..." call-process-region 1 "-c" "Looking for *.bib in path %s...done" looking-at "No match." "^ *$" set-mark end-of-line buffer-substring mark next-line beginning-of-line reverse] 16)) (defun tex-cite-multifile-search (&optional back nowrap top new-regexp new-file-list) "\ Search through a list of files for a regular expression. If TOP is non-nil, search from beginning of file-list. If NOWRAP is non-nil, do not wrap around end of file list when searching. If BACK is non-nil, search backwards. NEW-REGEXP is a single regular expression to be searched for. NEW-FILE-LIST is the list of files to be searched. If NEW-REGEXP and NEW-FILE-LIST are nil, use the last values provided. It is assumed that TOP and BACK will never both be non-nil" (byte-code "   !lj  @!q @\"Ѝ*" [regexp new-regexp tex-cite-mfs-last-regexp first-time nil top new-file-list t default-directory tex-cite-document-directory tex-cite-mfs-tail tex-cite-mfs-initialize-data find-file-noselect message "Searching %s ..." found (byte-code "J  #)p\"F !!%!B @!q @\"F\"" [t case-fold-search tex-cite-case-fold-search regexp back first-time nowrap default-directory tex-cite-document-directory tex-cite-mfs-tail nil tex-cite-mfs-search-buffer throw found tex-cite-mfs-roll-backward tex-cite-mfs-roll-forward find-file-noselect message "Searching %s ..."] 10)] 5)) (defun tex-cite-mfs-initialize-data (file-list) (byte-code "  " [file-list tex-cite-mfs-last-file-list tex-cite-mfs-last-back nil tex-cite-mfs-front tex-cite-mfs-tail] 2)) (defun tex-cite-mfs-search-buffer (regexp back first-time) (byte-code " dbeb( =?( $!b(!b  9 #> #" [first-time back tex-cite-mfs-last-back regexp nil t match-beginning 0 match-end re-search-backward re-search-forward] 7)) (defun tex-cite-mfs-roll-forward (nowrap) (byte-code "A? ‚4A#@ BAĂ4‰ !!ć" [tex-cite-mfs-tail nowrap nil tex-cite-mfs-front t tex-cite-mfs-last-file-list message "Wrapping around..." sit-for 1] 3)) (defun tex-cite-mfs-roll-backward (nowrap) (byte-code "? ‚;!@ BAĂ; !@CA!!ć" [tex-cite-mfs-front nowrap nil tex-cite-mfs-tail t tex-cite-mfs-last-file-list reverse message "Wrapping around..." sit-for 1] 4)) (defun tex-cite-search (&optional back top new-query file-list) (byte-code "   @@   %  Tq! ?J \"Tq8 ." [query new-query tex-cite-search-last-query first-regexp tex-cite-use-full-query nowrap top buffer back file-list continue t return-value nil tex-cite-multifile-search tex-cite-query-check-entry] 6)) (defun tex-cite-query-check-entry (query) (byte-code " ) ?` 8VĂE % %8 @ \" A E 88p E+)" [case-fold-search t entry-data result nil query tex-cite-use-full-query bibtex-search-entry 1 tex-cite-query-check-regexp 2 3] 5)) (defun tex-cite-query-check-regexp (regexp-data entry-data) (byte-code " @ 8 @ A \" 88\"%b΍," [entry-start entry-data entry-end regexp regexp-data label-regexp t 1 string-equal "ID" string-match 2 3 done (byte-code " #9  \" 88\"=, 88\")3\"))" [regexp entry-end t field-data label-regexp case-fold-search tex-cite-case-fold-search re-search-forward bibtex-current-field-data string-equal "ANYFIELD" 0 string-match 2 3 throw done] 10)] 6)) (defun tex-cite-query-init nil (byte-code " \" \"" [tex-cite-query-field-labels tex-cite-query-fields tex-cite-query-fields-alist mapcar tex-cite-make-query-label tex-cite-make-query-field-alist] 4)) (defun tex-cite-make-query-label (field-list) "\ FIELD-LIST is a list of strings. This function returns the same strings concatenated together with slashes between them. That is, (`AUTHOR' `EDITOR') => `AUTHOR/EDITOR'" (byte-code "#" [field-list mapconcat eval "/"] 4)) (defun tex-cite-make-query-field-alist (labels field-lists) "\ Recursively generates an association list between the elements of of the two lists that are its arguments. It assumes that the lists are of the same length, though if the first one is short, it's not a problem. Has been modified to tranform the elements of the second list into regular expressions matching each string in the list." (byte-code "? @ @#BA A\"B" [labels nil field-lists mapconcat eval "\\|" tex-cite-make-query-field-alist] 5)) (tex-cite-query-init) (defun tex-cite-get-query (file-list) "\ Returns a list of (word-list field-list) pairs. A field-list is a list of BibTeX field labels. The words in the word list will contain no white space. The list of pairs is constructed by having the user fill in a query template. All of the field labels used are standard except ID, which stands for the unique identifier, and ANYFIELD, which is supposed to stand for all fields." (byte-code " !" [tex-cite-use-full-query file-list tex-cite-get-full-query tex-cite-get-regexp-query] 3)) (defun tex-cite-get-full-query nil "\ Returns a list of (word-list field-list) pairs. A field-list is a list of BibTeX field labels. The words in the word list will contain no white space. The list of pairs is constructed by having the user fill in a query template. All of the field labels used are standard except ID, which stands for the unique identifier, and ANYFIELD, which is supposed to stand for all fields." (byte-code "‹" [query-buffer tex-cite-last-query ((byte-code " !!!! )" [query-buffer tex-cite-last-query tex-cite-get-query-buffer tex-cite-insert-template tex-cite-edit-query-buffer tex-cite-parse-query-buffer bury-buffer] 6))] 1)) (defun tex-cite-get-regexp-query (file-list) (byte-code "A Â@!Q!" [file-list read-string "Lookup regexp in " "*.bib" file-name-nondirectory " (default browsing mode): "] 5)) (defun tex-cite-get-query-buffer nil "\ Either gets the buffer named by tex-cite-query-buffer-name or creates it. Returns the buffer and leaves the cursor in the buffer." (byte-code "!!q p" [tex-cite-query-buffer-name t get-buffer get-buffer-create bibtex-mode] 4)) (defun tex-cite-insert-template (buffer) "\ Inserts a blank template in BUFFER. Note that what fields are produced depends on the elements of tex-cite-query-field-labels." (byte-code "!eb ?!Z c ̂!cc  ADc j @$ A(c j @$ jc)" [buffer tex-cite-last-query default-case-fold-search field-list tex-cite-query-field-labels bibtex-field-indent bibtex-field-pair switch-to-buffer-other-window y-or-n-p "Clear query form? " erase-buffer "%% Type ESC C-c when query is complete. " "Using Case-Insensitive search. " "Using Case-Sensitive search. " "@QUERY{," " " insert " = " "," "}"] 9)) (defun tex-cite-edit-query-buffer (buffer) "\ Lets the user recursively edit the query buffer, politely placing the cursor at the identifier field." (byte-code "b!! " [1 bibtex-next-field 2 message "Edit template to complete query ... ESC C-c to accept" recursive-edit] 4)) (defun tex-cite-parse-query-buffer (buffer) "\ Parses a completed query template in BUFFER. Will only parse the first template found there. Returns a list of (word-list field-list) pairs, which are described in more detail under tex-cite-get-query." (byte-code "  qeb#!!\"(!!\"\" ` @@P#!!\"W!!\"\"\") A)*" [result nil field-alist tex-cite-query-fields-alist buffer t new-items re-search-forward "@QUERY{\\(.*\\)," /= match-beginning 1 match-end mapcar (lambda (re) (cons re "ID")) tex-cite-field-parse "\\s *=\\s {\\(.*\\)}" (lambda (re) (cons re (cdr (car field-alist)))) nconc] 20)) (defun tex-cite-field-parse (start end) "\ START and END are the boundaries of a substring in the current buffer. This function returns a list of the separate words found in this substring. The notion of `word' used here differs from that used by Emacs. The local definition of `word' means contiguous non-whitespace characters." (byte-code "b #a!f=8` #2 `S\"C\"5!]`S #S `S\"C\"] \"C\" *" [start regexp-start nil result end t re-search-forward "\\S " match-beginning 0 34 "[^\\\\]\"" append buffer-substring error "Mismatched quotes, please reenter your query" "\\s " 1] 15)) (defun tex-cite-lookup (&optional round2 abort) (byte-code " p     ۋ . " [file-list round2 tex-cite-mfs-last-file-list home-buffer query nil result response return-value entry-id help-window pre-help-config show-window continue t tex-cite-document-directory default-directory tex-cite-lookup-window-config tex-cite-lookup-show tex-cite-query-lookup-response tex-cite-query-failure-response tex-cite-note-on tex-cite-cite-on abort sysmsg tex-cite-master tex-cite-get-file-list ((byte-code " ! 3ĉ! ?# \")! $ @ q U ! 8!e q 8!p! #!)  Q \" \" !ĉ = Dĉ = 8q 88b Dĉ = 88b! = 8@b! = lj =# $ =9!# =O!# =]  =?v!y!! =?!!! =!@) A=B C\"!D\"ĉĉ E=ljF  G H 4" [round2 tex-cite-lookup-window-config result tex-cite-lookup-show nil query file-list t continue entry-id show-window home-buffer response tex-cite-query-lookup-response tex-cite-query-failure-response help-window pre-help-config return-value tex-cite-note-on tex-cite-cite-on abort sysmsg set-window-configuration tex-cite-search tex-cite-get-query equal "" error "You supplied an empty query." select-window switch-to-buffer 1 pop-to-buffer get-buffer-window search-backward "@" recenter 0 vortex-user-response "Confirm {" "}? " "Your query not found " yes yes-more 2 next previous show new-file tex-cite-get-file-list new-key-from-top new-key new-entry tex-cite-new-entry note-switch message "Citation note field prompting enabled." "Citation note field prompting disabled." sit-for cite-switch "Citation mode enabled." "Pseudo citation mode enabled." redit "Entering recursive edit...(return to bibliography lookup by ESC C-c)" ((byte-code " " [recursive-edit] 2)) quit ding "%squit (returning to previous level)" throw help current-window-configuration tex-cite-lookup-help tex-cite-option-help] 40)) current-window-configuration] 13)) (defun tex-cite-get-file-list nil (byte-code " !\"  \"* \" \")C*)" [fn tex-cite-bibmsg tex-cite-wildcard tex-cite-ext tex-bib-path t nil read-string string-equal "" tex-cite-list-wildcard vortex-file-exists-p tex-cite-fn-ext] 7)) (defun tex-cite-new-entry (&optional abort) (byte-code "!! ! \" \"  ҋ \"! ?< !EK    \"-" [func key fn tex-cite-bibmsg tex-cite-ext tmp tex-bib-path entry nil abort =entry= =key= read-command "Creating new entry of type: " read-string "Entry name: " tex-cite-fn-ext vortex-file-exists-p ((byte-code "!db ! c!! db b" [fn func key entry find-file-other-window funcall bibtex-next-field 1 message "Fill in rest of empty fields, type ESC C-c to return." recursive-edit bibtex-search-entry] 8)) message "New entry {%s} created." sit-for 1 get-buffer throw] 11)) (defun tex-cite-option-help nil (byte-code "! !b!" [tex-cite-window pop-to-buffer erase-buffer insert-string " F -- Give up current .bib file, prompt for an alternate filename. K -- Give up current search key, prompt for an alternate query and start searching from beginning of buffer. e -- Create a new .bib entry. C-r -- Enter recursive edit. Use ESC C-c to return. C-c -- Quit, go back to previous level, if there is one. ? -- This help message." 1 other-window] 5)) (defun tex-cite-lookup-help nil (byte-code "! !b!" [tex-cite-window pop-to-buffer erase-buffer insert-string " RET/y -- Confirm and exit. ESC -- Confirm and continue searching for another matching reference. SPC/n -- Go to next entry containing this key, if any. DEL/p -- Go to previous entry containing this key, if any. s -- Show the entry in other window. F -- Give up current .bib file, prompt for an alternate filename. K -- Give up current search key, prompt for an alternate query and start searching from beginning of buffer. k -- Give up current search key, prompt for an alternate query and start searching from current position. u -- Toggle citation note field prompting. m -- Toggle cite/nocite mode. C-r -- Enter recursive edit. Use ESC C-c to return. C-c -- Quit, go back to previous level, if there is one. ? -- This help message." 1 other-window] 5))