Skip to content

Instantly share code, notes, and snippets.

@matthew-ball
Created May 25, 2012 07:09
Show Gist options
  • Save matthew-ball/2786321 to your computer and use it in GitHub Desktop.
Save matthew-ball/2786321 to your computer and use it in GitHub Desktop.
;; FILE: /home/chu/Programming/lisp/elisp/ref-man/org-ref-man.el
;; AUTHOR: Matthew Ball (copyleft 2012)
;; TIME: Fri 25 May 2012 02:46:58 EST
;;; COMMENT:
;; Welcome to `org-ref-man', a reference manager for GNU Emacs utilising the functionality of `org-mode'.
;; The project's goals state:
;; 1. Creates and manages a database of source material.
;; 2. Interact with this database with emacs-lisp.
;; 3. Creates an `org-mode' buffer with the database information.
;; TODO:
;; 1. Populate database.
;; 2. Write parser to read from `org-table' entries.
(require 'ref-man-db)
(eval-when-compile (require 'cl))
;; COMMENT: custom variables
(defcustom ref-man-directory (expand-file-name "~/Documents/Papers/PDFs/")
"`ref-man' main directory; for storing/locating reference material."
:type 'directory :safe 'stringp :group 'ref-man)
(defcustom ref-man-extension "pdf" ;; TODO: should make this a list
"`ref-man' file extension."
:type 'string :safe 'stringp :group 'ref-man)
;; COMMENT: constants
(defconst ref-man-version "0.3" "Version of the system's `ref-man' install.")
(defconst ref-man-mode-name "org-ref-man" "The `ref-man' mode name.")
(defconst ref-man-buffer-name (concat "*" ref-man-mode-name "*") "The `ref-man' buffer name.")
(defconst ref-man-column-length 20 "Column length for `ref-man'.")
;; COMMENT: variables
(defvar ref-man-mode-hook nil "Run hook when entering `ref-man' mode.")
(defvar ref-man-files nil "List of files.")
(defvar ref-man-filter-regexp nil "Current filter regexp used by `ref-man' mode.") ;; NOTE: should be able to filter `tags'
;; COMMENT: functions
(defun ref-man-reset-files ()
"Reset the `ref-man-files' list."
(setq ref-man-files nil))
(defun ref-man-find-files ()
"Return a list of all files in the `ref-man-directory' directory which matches the `ref-man-extension' extension."
(if (file-exists-p ref-man-directory)
(let (files result)
(setq files (directory-files ref-man-directory t (concat "\." ref-man-extension "$") t))
(dolist (file-name files)
(when (and (file-readable-p file-name) (not (file-directory-p file-name)))
(setq result (cons file-name result))))
result)))
(defun ref-man-buffer-setup ()
"Render the file browser in the `*ref-man*' buffer."
;; TODO: check if database entry is found, ask questions, etc
;; (setq ref-man-files (ref-man-find-files)) ;; NOTE: find files
(setq ref-man-files (ref-man-load-database)) ;; NOTE: load database
(if (not (file-exists-p ref-man-directory))
(insert (concat "ERROR: Directory " ref-man-directory " does not exist."))
(if ref-man-files
(progn
(ref-man-populate-database)
(ref-man-read-from-database)
(insert "* Reference Manager\n")
(insert "|----------------------------------------+----------+--------|\n")
(insert "| *Title* | *Author* | *Year* |\n")
(insert "|----------------------------------------+----------+--------|\n")
(dolist (entry ref-man-files)
(insert
(concat "| [[" (plist-get entry :file) "][" (plist-get entry :title) "]] | "
(plist-get entry :author) " | "
(plist-get entry :year) " |"))
(insert "\n"))
(insert "|----------------------------------------+----------+--------|\n\n")
(insert "* Bibliography Information\n"))
(insert (concat "ERROR: No files were loaded."))
)))
(defun ref-man-populate-database ()
"Populate the `ref-man' database with the contents of the `ref-man-files' variable."
(dolist (entry ref-man-files)
(ref-man-create-record
(plist-get entry :file)
(plist-get entry :title)
(plist-get entry :author)
(plist-get entry :type)
(plist-get entry :year)
(plist-get entry :tags))))
(defun ref-man-read-from-database () ;; ERROR: this does not work
"..."
(dolist (record ref-man-record-database) ;; NOTE: loop through the records of the (external) `ref-man-db' database
(add-to-list 'ref-man-files record) ;; NOTE: ... add the record to the (internal) `ref-man' database
))
;; COMMENT: commands
(defun ref-man-add-file (file &optional title author type notes) ;; TODO: ...
"Add a file to the `ref-man-files' database."
(interactive "f\nSelect file:"))
(defun ref-man-quit (&rest junk)
"Bury the `*ref-man*' buffer."
(interactive)
(setq ref-man-files nil) ;; NOTE: clear database
(when (string= (buffer-name) ref-man-buffer-name)
(kill-buffer)))
(defun ref-man-goto-file (&rest junk) ;; NOTE: this is a bit limiting, requires *all* files to be in the same main directory
"Follow filename in `*ref-man*' buffer."
(interactive)
(find-file (concat ref-man-directory (thing-at-point 'filename))))
;; COMMENT: mode configuration
(defvar ref-man-mode-map
(let ((map (make-keymap)))
;; sorting
;; (define-key map (kbd "s") 'ref-man-sort-files) ;; sort by FILE or {AUTHOR, JOURNAL, YEAR, TAGS} ;; ERROR: this won't work
;; open file
(define-key map (kbd "RET") 'ref-man-goto-file)
;; file management
(define-key map (kbd "a") 'ref-man-add-file)
(define-key map (kbd "r") 'ref-man-remove-file) ;; TODO: rename to `ref-man-delete-file'
;; misc
(define-key map (kbd "g") 'ref-man-refresh)
(define-key map (kbd "q") 'ref-man-quit)
(define-key map (kbd "v") 'ref-man-show-version)
;; widgets
(define-key map [down-mouse-1] 'widget-button-click)
(define-key map [down-mouse-2] 'widget-button-click)
(define-key map (kbd "<tab>") 'widget-forward)
(define-key map (kbd "<backtab>") 'widget-backward)
(define-key map (kbd "<S-tab>") 'widget-backward)
map)
"Keymap for `ref-man' major mode")
(defun ref-man-mode (&rest junk)
"Major mode for managing reference files in GNU Emacs."
(kill-all-local-variables)
(setq truncate-lines t)
(ref-man-buffer-setup) ;; NOTE: render `*ref-man*' buffer
(org-mode)
;; NOTE: the following ...
(beginning-of-buffer)
(org-cycle)
(next-line)
(next-line)
(org-cycle)
(beginning-of-buffer)
;; NOTE: ... is there just to set up the display (there is a better way)
(toggle-read-only))
(put 'ref-man-mode 'mode-class 'special)
;;;###autoload
(defun ref-man ()
"Switch to `*ref-man*' buffer and start mode."
(interactive)
(save-excursion
(split-window-below)
(switch-to-buffer ref-man-buffer-name)
(when (not (eq major-mode 'ref-man-mode))
(ref-man-mode))))
(provide 'org-ref-man)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment