1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177 |
- ;;;; -*- mode: EMACS-LISP; lexical-binding: t -*-
- ;;
- ;; bible-mode.el --- A browsing interface for the SWORD Project's Diatheke CLI
- ;; Time-stamp: <2024-05-22 09:00:30 fred>
- ;; Author: Zacalot
- ;; Fixes and modifications by Fred Gilham
- ;; Url: https://gitbot.homedns.org/fred/bible-mode
- ;; Forked from
- ;; Url: https://github.com/Zacalot/bible-mode
- ;; Version: 1.0.0
- ;; Package-Requires: ((emacs "24.1"))
- ;; Keywords: diatheke, sword, research, bible
- ;;; Commentary:
- ;; This package uses the `diatheke' program to browse and search
- ;; Biblical texts provided by the Sword project.
- ;; Word study is also supported.
- ;;; Usage:
- ;; First install `diatheke'. On Debian/Ubuntu it's in the `diatheke'
- ;; package. In other distributions it might be in the sword package.
- ;; For Windows I found that you can simply install the Xiphos package.
- ;; It includes the Sword library and its utilities including diatheke,
- ;; installmgr and mkfastmod. Add the "Program Files\Xiphos\bin" path
- ;; to your execution path.
- ;; Use M-x `bible-open' to open a Bible buffer.
- ;; Use C-h f `bible-mode' to see available keybindings.
- ;; You may customize `bible-mode-module' to set a default browsing
- ;; module, as well as `bible-mode-word-study-enabled' to enable word
- ;; study by default.
- ;;; Design:
- ;; The idea here is to use the diatheke program to insert code from
- ;; modules into buffers. The main bible display uses an "internal" XML
- ;; format. The whole buffer gets parsed by libxml-parse-html-region to
- ;; create a dom tree. This gets parsed by
- ;; bible-mode--insert-domnode-recursive to render the text into
- ;; reading format.
- ;; The text is then decorated using information from the dom format as
- ;; necessary along with regular expressions to identify the verse
- ;; references. This is for red letters, purple highlighting of the
- ;; verse numbers, bold face of the divine name in the OT and so on.
- ;; If strongs tags and/or morphological tags are present, they are
- ;; looked up in appropriate lexical and morphological modules and used
- ;; to add tooltips to the text so that mousing over words will bring
- ;; up a tooltip with information about the word. Clicking on a word
- ;; with lexical information will display that informatio in a "term"
- ;; buffer.
- ;;;
- ;;; bm- is used as shorthand (see Local Variables) for bible-mode-
- ;;; Code:
- ;;;; Requirements
- (require 'cl-lib) ; XXX FMG there are just a few constructs that use this; use elisp versions instead.
- ;; (require 'bidi)
- (require 'dom)
- (require 'shr)
- ;; Turn off tool bar mode because we want the pixels....
- (tool-bar-mode -1)
- ;;;; Variables
- (defgroup bible-mode nil
- "Settings for `bible-mode'."
- :group 'tools
- :link '(url-link "https://gitbot.homedns.org/fred/bible-mode"))
- (defcustom bm-module
- "KJV"
- "Book module for Diatheke to query."
- :type '(choice (const :tag "None" nil)
- (string :tag "Module abbreviation (e.g. \"KJV\")"))
- :local t
- :group 'bible-mode)
- ;;;
- ;;; XXX Not implememted yet
- (defcustom bm-font
- "Ezra SIL"
- "Default font for bible-mode."
- :type '(string :tag "Font family name (e.g. \"Ezra SIL\")")
- :local t
- :group 'bible-mode)
- (defcustom bm-greek-lexicon
- "MLStrong"
- "Lexicon used for displaying definitions of Greek words using Strong's codes."
- :type '(string :tag "Lexicon module (e.g. \"StrongsRealGreek\").")
- :local nil
- :group 'bible-mode)
- ;; This determines whether or not to use the Abbott Smith lexicon.
- ;; There is special-case code for this.
- (defcustom bm-use-abbott
- t
- "Use the Abbott Smith `Manual Greek Lexicon' for Greek definitions."
- :type 'boolean
- :local nil
- :group 'bible-mode)
- (defcustom bm-short-greek-lexicon
- "StrongsRealGreek"
- "Lexicon used for displaying definitions of Greek words in tooltips."
- :type '(string :tag "Lexicon module (e.g. \"StrongsRealGreek\").")
- :local nil
- :group 'bible-mode)
- (defcustom bm-hebrew-lexicon
- "StrongsRealHebrew"
- "Lexicon used for displaying definitions of Hebrew words using Strong's codes."
- :type '(string :tag "Lexicon module (e.g. \"StrongsRealHebrew\")")
- :local nil
- :group 'bible-mode)
- (defcustom bm-short-hebrew-lexicon
- "BDBGlosses_Strongs" ; This seems to work
- "Lexicon used for displaying definitions of Hebrew words in tooltips."
- :type '(string :tag "Lexicon module (e.g. \"StrongsRealHebrew\")")
- :local nil
- :group 'bible-mode)
- (defcustom bm-word-study-enabled
- nil
- "Display Strong's Hebrew, Strong's Greek, and Lemma words for study."
- :type 'boolean
- :local t
- :group 'bible-mode)
- (defcustom bm-red-letter-enabled
- t
- "Display words of Jesus in red when module has that information."
- :type 'boolean
- :local t
- :group 'bible-mode)
- ;;; defvars
- ;;(defvar bm-verse-regexp "([\d ]*[a-zA-Z]+( \d*:\d*)?)(( - )| )?(((\d* )?[a-zA-Z]+ )?\d*([:-]+\d*)?)")
- ;; (defvar bm-verse-regexp "/(\d*)\s*([a-z]+)\s*(\d+)(?::(\d+))?(\s*-\s*(\d+)(?:\s*([a-z]+)\s*(\d+))?(?::(\d+))?)?/i")
- (defvar bm-verse-regexp "\\(I?I \\)*[a-zA-Z]* [0-9]*:[0-9]*")
- (setq bm-verse-regexp "\\(I?I \\)*[a-zA-Z]* [0-9]*:[0-9]*")
- (defvar bm-modules (lazy-completion-table bm-modules bm--list-biblical-modules))
- ;; XXX I believe these chapter counts aren't the same for all modules, e.g. JPS.
- (defvar bm-books
- '(;; Old Testament
- ("Genesis" . 50) ("Exodus" . 40) ("Leviticus" . 27) ("Numbers" . 36)
- ("Deuteronomy" . 34) ("Joshua" . 24) ("Judges" . 21) ("Ruth" . 4)
- ("I Samuel" . 31) ("II Samuel" . 24) ("I Kings" . 22) ("II Kings" . 25)
- ("I Chronicles" . 29) ("II Chronicles" . 36) ("Ezra" . 10) ("Nehemiah" . 13)
- ("Esther" . 10) ("Job" . 42) ("Psalms" . 150) ("Proverbs" . 31)
- ("Ecclesiastes" . 12) ("Song of Solomon" . 8) ("Isaiah" . 66) ("Jeremiah" . 52)
- ("Lamentations" . 5) ("Ezekiel" . 48) ("Daniel" . 12) ("Hosea" . 14)
- ("Joel" . 3) ("Amos" . 9) ("Obadiah" . 1) ("Jonah" . 4)
- ("Micah" . 7) ("Nahum" . 3) ("Habakkuk" . 3) ("Zephaniah" . 3)
- ("Haggai" . 2) ("Zechariah" . 14) ("Malachi" . 4)
- ;; New Testament
- ("Matthew" . 28) ("Mark" . 16) ("Luke" . 24) ("John" . 21)
- ("Acts" . 28) ("Romans" . 16) ("I Corinthians" . 16) ("II Corinthians" . 13)
- ("Galatians" . 6) ("Ephesians" . 6) ("Philippians" . 4) ("Colossians" . 4)
- ("I Thessalonians" . 5) ("II Thessalonians" . 3) ("I Timothy" . 6) ("II Timothy" . 4)
- ("Titus" . 3) ("Philemon" . 1) ("Hebrews" . 13) ("James" . 5)
- ("I Peter" . 5) ("II Peter" . 3) ("I John" . 5) ("II John" . 1)
- ("III John" . 1) ("Jude" . 1) ("Revelation of John" . 22))
- "A-list of name / chapter count for Bible books.")
- (defvar bm-book-name-abbreviations-alist
- '(;; Old Testament
- ("Ge" . "Genesis") ("Ex" . "Exodus") ("Le" . "Leviticus") ("Nu" . "Numbers")
- ("De" . "Deuteronomy") ("Js" . "Joshua") ("Jg" . "Judges") ("Ru" . "Ruth")
- ("I Sa" . "I Samuel") ("II Sa" . "II Samuel") ("I Ki" . "I Kings") ("II Ki" . "II Kings")
- ("I Ch" . "I Chronicles") ("II Ch" . "II Chronicles") ("Ezr" . "Ezra") ("Ne" . "Nehemiah")
- ("Es" . "Esther") ("Jb" . "Job") ("Ps" . "Psalms") ("Pr" . "Proverbs")
- ("Ec" . "Ecclesiastes") ("So" . "Song of Solomon") ("Is" . "Isaiah") ("Je" . "Jeremiah")
- ("La" . "Lamentations") ("Ez" . "Ezekiel") ("Da" . "Daniel") ("Ho" . "Hosea")
- ("Joe" . "Joel") ("Am" . "Amos") ("Ob" . "Obadiah") ("Jon" . "Jonah")
- ("Mi" . "Micah") ("Na" . "Nahum") ("Ha" . "Habakkuk") ("Zep" . "Zephaniah")
- ("Hag" . "Haggai") ("Ze" . "Zechariah") ("Mal" . "Malachi")
- ;; New Testament
- ("Mt" . "Matthew") ("Mk" . "Mark") ("Lk" . "Luke") ("Jo" . "John")
- ("Ac" . "Acts") ("Ro" . "Romans") ("I Co" . "I Corinthians") ("II Co" . "II Corinthians")
- ("Ga" . "Galatians") ("Eph" . "Ephesians") ("Phl" . "Philippians") ("Col" . "Colossians")
- ("I Th" . "I Thessalonians") ("II Th" . "II Thessalonians") ("I Ti" . "I Timothy") ("II Ti" . "II Timothy")
- ("Tit" . "Titus") ("Phm" . "Philemon") ("He" . "Hebrews") ("Ja" . "James")
- ("I Pe" . "I Peter") ("II Pe" . "II Peter") ("I Jo" . "I John") ("II Jo" . "II John")
- ("III Jo" . "III John") ("Ju" . "Jude") ("Re" . "Revelation of John"))
- "A-list of abbreviations for Bible books.")
- ;;;; Book / chapter
- (defvar-local bm-current-book (assoc "Genesis" bm-books)
- "Current book data (name . chapter).")
- (defvar-local bm-current-book-name "Genesis"
- "Current book name.")
- (defvar-local bm-current-chapter 1
- "Current book chapter number.")
- (defvar-local bm-search-query nil
- "Search query associated with the buffer.")
- (defvar-local bm-search-mode "phrase"
- "Search mode: either `lucene' or `phrase'.")
- (defvar-local bm-has-strongs nil
- "Set if the module being displayed has strongs numbers availabile.")
- (defvar-local bm-has-morphology nil
- "Set if the module being displayed has morphology availabile.")
- ;; (defvar bm-current-module nil)
- ;;;; Keymaps
- (defconst bm-map (make-keymap))
- ;;;;; Navigation
- (define-key bm-map "n" 'bm-next-chapter)
- (define-key bm-map "p" 'bm-previous-chapter)
- (define-key bm-map (kbd "TAB") 'bm-forward-word) ; TODO: bm-forward-word
- ;;;;; Direct jump
- (define-key bm-map "b" 'bm-select-book)
- (define-key bm-map "c" 'bm-select-chapter)
- ;;;;; Search
- (define-key bm-map "s" 'bible-search)
- (define-key bm-map "/" 'bible-search)
- ;;;; Not yet
- ;;(define-key bm-map "" 'bm-set-search-range)
- ;;;;; Misc
- (define-key bm-map "m" 'bm-select-module)
- (define-key bm-map "w" 'bm-toggle-word-study)
- (define-key bm-map "x" 'bm-split-display)
- ;;;;; Deal with visual-line-mode
- (define-key bm-map "\C-n" 'next-logical-line)
- (define-key bm-map "\C-p" 'previous-logical-line)
- (defconst bible-search-mode-map (make-keymap))
- (define-key bible-search-mode-map "s" 'bible-search)
- (define-key bible-search-mode-map "w" 'bm-toggle-word-study)
- (define-key bible-search-mode-map (kbd "RET") 'bible-search-mode-follow-verse)
- (define-key bible-search-mode-map [mouse-1] 'bible-search-mode-follow-xref)
- (defconst bible-term-hebrew-mode-map (make-keymap))
- (defconst bible-term-greek-mode-map (make-keymap))
- ;; (defconst bible-term-morph-mode-map (make-keymap))
- ;;;
- ;;; Menu bar items
- ;;;
- (define-key global-map [menu-bar bible-mode]
- (cons "Bible Mode" (make-sparse-keymap "Bible Mode")))
- (defun bible-set-left-to-right ()
- (interactive)
- (setq-local bidi-paragraph-direction 'left-to-right))
- (defun bible-set-right-to-left ()
- (interactive)
- (setq-local bidi-paragraph-direction 'right-to-left))
- (define-key global-map
- [menu-bar bible-mode left-to-right]
- '("Left-to-right" . bible-set-left-to-right))
- (define-key global-map
- [menu-bar bible-mode right-to-left]
- '("Right-to-left" . bible-set-right-to-left))
- (defvar-local bm-debugme nil
- "Make text show up as XML when set.")
- (defun bible-set-display-xml ()
- "Turn on XML display."
- (interactive)
- (setq-local bm-debugme t)
- (bm--display))
- (defun bm-set-display-text ()
- "Turn off XML display."
- (interactive)
- (setq-local bm-debugme nil)
- (bm--display))
- (define-key global-map
- [menu-bar bible-mode display-xml]
- '("Display XML" . bm-set-display-xml))
- (define-key global-map
- [menu-bar bible-mode display-text]
- '("Display Text" . bm-set-display-text))
- (define-key global-map
- [menu-bar bible-mode select-biblical-text]
- '("Select Module" . bm--display-available-modules))
- (define-key global-map
- [menu-bar bible-mode select-biblical-text]
- '("Toggle debug-on-error" . toggle-debug-on-error))
- (defun bm-display-greek ()
- "This command is run by clicking on text, not directly by the user."
- (interactive)
- (let ((item (car (split-string (get-text-property (point) 'strong)))))
- ;; Remove "strong:G" prefix
- (bible-term-greek (replace-regexp-in-string "strong:G" "" item))))
-
- (defconst bm-greek-keymap (make-sparse-keymap))
- (define-key bm-greek-keymap (kbd "RET") 'bm-display-greek)
- (define-key bm-greek-keymap [mouse-1] 'bm-display-greek)
- (defun bm-display-hebrew ()
- "This command is run by clicking on text, not directly by the user."
- (interactive)
- (let ((item (car (split-string (get-text-property (point) 'strong)))))
- ;; Remove "strong:H" prefix and any alphabetic suffixes.
- (bible-term-hebrew (replace-regexp-in-string "strong:H" "" item))))
- (defconst bm-hebrew-keymap (make-sparse-keymap))
- (define-key bm-hebrew-keymap (kbd "RET") 'bm-display-hebrew)
- (define-key bm-hebrew-keymap [mouse-1] 'bm-display-hebrew)
- (defconst bm-lemma-keymap (make-sparse-keymap))
- (define-key bm-lemma-keymap (kbd "RET")
- (lambda ()
- (interactive)
- ))
- (defconst bm-morph-keymap (make-sparse-keymap))
- (define-key bm-morph-keymap (kbd "RET")
- (lambda ()
- (interactive)
- ;;; (let ((thing (thing-at-point 'word)))
- ;;; (message "thing at point: %s" thing)
- ;;; (message "morph property %s" (get-text-property 0 'field thing))
- ))
- ;;;; Modes
- (define-derived-mode bible-mode special-mode "Bible"
- "Mode for reading the Bible.
- \\{bm-map}"
- (buffer-disable-undo)
- (font-lock-mode t)
- (use-local-map bm-map)
- (setq buffer-read-only t)
- (visual-line-mode t))
- (define-derived-mode bible-search-mode special-mode "Bible Search"
- "Mode for performing Bible searches.
- \\{bible-search-mode-map}"
- (buffer-disable-undo)
- (font-lock-mode t)
- (use-local-map bible-search-mode-map)
- (setq buffer-read-only t)
- (visual-line-mode t)
- )
- (define-derived-mode bible-term-hebrew-mode special-mode "Bible Term (Hebrew)"
- "Mode for researching Hebrew terms in the Bible.
- \\{bible-term-hebrew-mode-map}"
- (buffer-disable-undo)
- (font-lock-mode t)
- (use-local-map bible-term-hebrew-mode-map)
- (setq buffer-read-only t)
- (visual-line-mode t))
- (define-derived-mode bible-term-greek-mode special-mode "Bible Term (Greek)"
- "Mode for researching Greek terms in the Bible.
- \\{bible-term-greek-mode-map}"
- (buffer-disable-undo)
- (font-lock-mode t)
- ;; (use-local-map bible-term-greek-mode-map)
- (setq buffer-read-only t)
- (visual-line-mode t))
- (define-derived-mode module-select-mode special-mode "Select Text Module"
- (buffer-disable-undo)
- (font-lock-mode t)
- (setq buffer-read-only t))
- ;;;; Functions
- ;;;;; Commands
- ;;;###autoload
- (defun bible-open (&optional book-name chapter verse)
- "Creates and opens a `bible-mode' buffer"
- (interactive)
- (let ((buf (get-buffer-create (generate-new-buffer-name (concat "*bible*")))))
- (set-buffer buf)
- (bible-mode)
- (bm--set-location (assoc (or book-name "Genesis") bm-books) (or chapter 1) verse)
- (set-window-buffer (get-buffer-window (current-buffer)) buf)))
- ;;;###autoload
- (defun bm-next-chapter ()
- "Pages to the next chapter for the active `bible-mode' buffer."
- (interactive)
- (let* ((book-chapters (cdr bm-current-book))
- (chapter (min book-chapters (+ bm-current-chapter 1))))
- (bm--set-location bm-current-book chapter)))
- ;;;###autoload
- (defun bm-previous-chapter ()
- "Pages to the previous chapter for the active `bible-mode' buffer."
- (interactive)
- (bm--set-location bm-current-book (max 1 (- bm-current-chapter 1))))
- (defun bm-forward-word ()
- "Moves forward a word, taking into account the relevant text properties.
- XXX Doesn't work yet."
- (interactive)
- (field-end))
- ;;;###autoload
- (defun bm-select-book ()
- "Queries user to select a new book and chapter for the current
- `bible-mode' buffer."
- (interactive)
- (let* ((completion-ignore-case t)
- (book-data (assoc (completing-read "Book: " bm-books nil t) bm-books))
- (chapter (string-to-number (completing-read "Chapter: " (bm--list-number-range 1 (cdr book-data)) nil t))))
- (setq-local bm-current-book book-data)
- (setq-local bm-current-book-name (car book-data))
- (setq-local bm-current-chapter chapter)
- (bm--display)))
- ;;;###autoload
- (defun bm-select-chapter ()
- "Queries user to select a new chapter for the current `bible-mode' buffer."
- (interactive)
- (let* ((book-chapters (cdr bm-current-book))
- (chapter (string-to-number (completing-read "Chapter: " (bm--list-number-range 1 book-chapters) nil t))))
- (when chapter
- (bm--set-location bm-current-book chapter))))
- ;;;###autoload
- (defun bm-select-module ()
- "Queries user to select a new reading module for the current `bible-mode' buffer."
- (interactive)
- (let ((module (completing-read "Module: " bm-modules)))
- (setq-local bm-module module)
- (bm--display)))
- ;;;###autoload
- (defun bm-toggle-word-study()
- "Toggles the inclusion of word study for the active `bible-mode' buffer."
- (interactive)
- (setq bm-word-study-enabled (not bm-word-study-enabled))
- (if (equal major-mode 'bible-search-mode)
- (bm--display-search bm-search-query bm-search-mode bm-module)
- (bm--display)))
- ;;;###autoload
- (defun bm-split-display ()
- "Copies the active `bible-mode' buffer into a new buffer in another window."
- (interactive)
- (split-window-right)
- (balance-windows)
- (other-window 1)
- (bible-open bm-current-book-name bm-current-chapter))
- ;;;###autoload
- (defun bible-search (query)
- "Prompts the user for a Bible search query: word or phrase and type of
- search: either `lucene' or `phrase'. `lucene' mode requires an index
- to be built using the `mkfastmod' program. `lucene' is the default
- search."
- (interactive "sBible Search: ")
- (when (> (length query) 0)
- (let* ((searchmode (completing-read "Search Mode: " '("lucene" "phrase") nil t "lucene")))
- (bm--open-search query searchmode))))
- ;;;###autoload
- (defun bible-search-mode-follow-verse ()
- "Follows the hovered verse in a `bible-search-mode' buffer,
- creating a new `bible-mode' buffer positioned at the specified verse."
- (interactive)
- (let* ((text (thing-at-point 'line t))
- book
- chapter
- verse)
- (string-match ".+ [0-9]?[0-9]?[0-9]?:[0-9]?[0-9]?[0-9]?:" text)
- (setq text (match-string 0 text))
- (string-match " [0-9]?[0-9]?[0-9]?:" text)
- (setq chapter (replace-regexp-in-string "[^0-9]" "" (match-string 0 text)))
- (string-match ":[0-9]?[0-9]?[0-9]?" text)
- (setq verse (replace-regexp-in-string "[^0-9]" "" (match-string 0 text)))
- (setq book (replace-regexp-in-string "[ ][0-9]?[0-9]?[0-9]?:[0-9]?[0-9]?[0-9]?:$" "" text))
- (bible-open (string-trim book) (string-to-number chapter) (string-to-number verse))))
- (defun bible-search-mode-follow-xref ()
- "Follows the hovered verse in a `bible-search-mode' buffer,
- creating a new `bible-mode' buffer positioned at the specified verse.
- N.B. We use the default module to avoid opening cans of worms regarding
- OT/NT etc."
- (interactive)
- (let* ((xref (get-text-property (point) 'xref))
- (verse-ref (string-split xref))
- book-abbrev
- book
- chapter-verse
- chapter
- verse)
- (if (= (length verse-ref) 3) ; II Cor 3:17 or the like
- (progn
- (setq book-abbrev (concat (car verse-ref) " " (cadr verse-ref)))
- (setq chapter-verse (split-string (caddr verse-ref) ":")))
- (progn ; Mat 5 or the like
- (setq book-abbrev (car verse-ref))
- (setq chapter-verse (split-string (cadr verse-ref) ":"))))
- (setq book (cdr (assoc book-abbrev bm-book-name-abbreviations-alist)))
- (setq chapter (car chapter-verse)
- verse (cadr chapter-verse))
- (bible-open (string-trim book) (string-to-number chapter) (string-to-number verse))))
- ;;;###autoload
- (defun bible-term-hebrew (term)
- "Queries user for a Strong's Hebrew Lexicon term."
- (interactive "sTerm: ")
- (bm--open-term-hebrew term))
- ;;;###autoload
- (defun bible-term-greek (term)
- "Queries user for a Strong's Greek Lexicon term."
- (interactive "sTerm: ")
- (bm--open-term-greek term))
- ;;;###autoload
- (defun bible-insert ()
- "Queries user to select a verse for insertion into the current buffer."
- (interactive)
- (let* ((completion-ignore-case t)
- (book-data (assoc (completing-read "Book: " bm-books nil t) bm-books))
- (chapter (when book-data (completing-read "Chapter: " (bm--list-number-range 1 (cdr book-data)) nil t)))
- (verse (when chapter (read-from-minibuffer "Verse: "))))
- (when verse
- (insert (string-trim
- (replace-regexp-in-string
- (regexp-opt `(,(concat "(" bm-module ")")))
- ""
- (bm--exec-diatheke (concat (car book-data) " " chapter ":" verse) nil "plain")))))))
- ;;;;; Support
- ;;;
- ;;; XXX I've magled this in an ad-hoc manner. It needs to be
- ;;; re-written so it is clearer (and correct, for that matter).
- (defun bm--exec-diatheke (query &optional filter format searchtype module)
- "Executes `diatheke' with specified query options, returning the output."
- (let ((module (or module bm-module)))
- (with-temp-buffer
- (let ((args (list "diatheke" nil (current-buffer) t "-b" module)))
- (if filter
- (setq filter (concat filter " avmws"))
- (setq filter "avmws"))
- (when filter (setq args (append args (list "-o" filter))))
- (when searchtype
- (setq args (append args (list "-s" (pcase searchtype ("lucene" "lucene") ("phrase" "phrase"))))))
- (setq args (append args (list "-f" (pcase format ("plain" "plain") (_ "internal")) "-k" query)))
- (message "%s" args)
- (apply 'call-process args))
- (buffer-string))))
- (defvar-local bm-chapter-title nil
- "Document text at start of chapter, mostly in Psalms,
- like `Of David' or the like.")
- ;;;
- ;;; Greek and Hebrew lexicon and morphology tooltip rendering.
- ;;;
- ;;; Hash tables for Lexical definitions.
- (defvar greek-hash (make-hash-table :test 'equal))
- (defvar greek-short-hash (make-hash-table :test 'equal)) ; Hash table for ``short'' lexical lookup
- (defvar hebrew-hash (make-hash-table :test 'equal))
- (defvar hebrew-short-hash (make-hash-table :test 'equal))
- ;; Do lookups using AbbottSmith_Strongs as index to AbbottSmith lexicon.
- (defvar abbott-index-hash (make-hash-table :test 'equal))
- (defvar abbott-lex-hash (make-hash-table :test 'equal))
- ;;; Hash tables for Morphologies. Three at present.
- (defvar robinson-hash (make-hash-table :test 'equal))
- (defvar packard-hash (make-hash-table :test 'equal))
- (defvar oshm-hash (make-hash-table :test 'equal))
- ;;; Use HTMLHREF format with diatheke, post-process to render html.
- (defun bm--morph-query (query module)
- "Executes `diatheke' to do morph query, renders HTML, returns string.
- Does some tweaking specific to morphology."
- (with-temp-buffer
- (let ((args (list "diatheke" nil (current-buffer) t "-b" module "-o" "m" "-f" "HTMLHREF" "-k" query)))
- (apply 'call-process args)
- (shr-render-region (point-min) (point-max))
- (format-replace-strings
- '(("\n:" . "") ; This makes the Packard morphology display look better.
- ("Part of Speech" . "")) ; This helps the Robinson display look better.
- nil (point-min) (point-max))
- (substring (buffer-string) (+ (length query) 1))) ; This tries to get rid of unnecessary query identifier.
- ))
- ;;; Use "plain" format with diatheke.
- (defun bm--lex-query (query module)
- "Executes `diatheke' for query, plain format, returns string."
- ;; Get rid of query ID at front of string: ?????:
- (bm--exec-diatheke query nil "plain" nil module))
- (defun bm--lookup-strongs-greek (window object pos)
- "Look up Greek lexical data for object at point. If not found in hash table,
- get it from sword database, stash in hash table, and return data."
- (let* ((query (get-text-property pos 'strong object))
- (match (string-match "[0-9]+" query))
- (lookup-key (match-string 0 query)))
- (and lookup-key
- (or (gethash lookup-key greek-hash)
- (puthash lookup-key (bm--lex-query lookup-key bible-mode-short-greek-lexicon) greek-hash)))))
- (defun bm--lookup-lemma-abbott (key)
- "Given a strong's number, return the Greek lemma from AbbottSmithStrongs."
- (or (gethash key abbott-index-hash)
- (puthash key
- (string-trim
- (replace-regexp-in-string
- "(AbbottSmithStrongs)" ""
- (bm--lex-query key "AbbottSmithStrongs")))
- abbott-index-hash)))
- (defun bm--lookup-def-abbott (lemma)
- "Executes `diatheke' to do abbott query, renders HTML, sets text
- properties to allow verse cross references. Returns string."
- (with-temp-buffer
- (let ((args (list "diatheke" nil (current-buffer) t "-b" "AbbottSmith" "-o" "m" "-f" "plain" "-k" lemma)))
- (apply 'call-process args)
- (format-replace-strings
- '((" I." . "\n I.")
- (" 1." . "\n 1.")
- (" (a)" . "\n (a)")
- (". ." . ".")
- (" . " . ". ")))
- (goto-char (point-min))
- (while (search-forward-regexp bm-verse-regexp nil t)
- (put-text-property (match-beginning 0) (match-end 0) 'xref (match-string 0))
- (put-text-property (match-beginning 0) (match-end 0) 'keymap bible-search-mode-map)
- (add-face-text-property (match-beginning 0) (match-end 0) '(:foreground "blue"))
- ))
- (buffer-string)))
- (defun bm--lookup-lex-def-abbott (key)
- (let* ((abbott-lemma (bm--lookup-lemma-abbott key))
- ;; Get the lemma which is after the `@LINK' string.
- (lemma (caddr (split-string abbott-lemma)))
- ;; Use the lemma to lookup the definition.
- (lex-def (bm--lookup-def-abbott lemma)))
- lex-def))
- (defun bm--lookup-strongs-greek-abbott (window object pos)
- "To use Abbott's Lexicon we extract the Strong's key from the text in the
- buffer. Given the Strong's number, get the lemma for that number. Use
- that lemma to lookup the definition in the AbbottStrongs lexicon.
- Compiler warns about unused Window argument."
- (let* ((query (get-text-property pos 'strong object))
- (match (string-match "[0-9]+" query)) ; Compiler warns about unused match variable.
- (lookup-key (match-string 0 query)))
- (when lookup-key
- (bm--lookup-lex-def-abbott lookup-key))))
- ;;; Not used.
- (defun bm--hebrew-lex-query (query module)
- "Executes `diatheke' to do hebrew query, renders HTML, returns string.
- XXX directionality problems."
- (with-temp-buffer
- (let ((args (list "diatheke" nil (current-buffer) t "-b" module "-o" "m" "-f" "HTMLHREF" "-k" query)))
- (apply 'call-process args)
- (shr-render-region (point-min) (point-max)))))
- (defun bm--lookup-strongs-hebrew (window object pos)
- "Look up Hebrew lexical data for object at point. If not found in hash table,
- get it from sword database, stash in hash table, and return data.
- Note: compiler warns about unused `window' argument."
- (let* ((query (get-text-property pos 'strong object))
- (match (string-match "[0-9]+" query)) ; Compiler warns about match.
- (match-string (match-string 0 query)))
- (when match-string
- (let ((lookup-key (concat "H" (match-string 0 query))))
- (or (gethash lookup-key hebrew-hash)
- ;; Use PLAIN format for lookup. XXX directionality problems.
- (let ((raw-text (bm--lex-query lookup-key bm-short-hebrew-lexicon)))
- ;; XXX massage this text to handle outline formatting a bit better.
- (puthash lookup-key raw-text hebrew-hash)))))))
- (defun bm--morph-database-lookup (query database hash)
- (or (gethash query hash)
- (puthash query (bm--morph-query query database) hash)))
- ;;;
- ;;; Get string for tooltip display
- ;;;
- (defun bm--show-lex-morph (window object pos)
- (let* ((lex-morph-text "")
- (lex (get-text-property pos 'strong object))
- (lex-module nil)
- (lex-text
- (cond ((string-match "strong:G" lex)
- (setq lex-module bm-short-greek-lexicon)
- (bm--lookup-strongs-greek window object pos))
- ((string-match "strong:H" lex)
- (setq lex-module bm-short-hebrew-lexicon)
- (bm--lookup-strongs-hebrew window object pos)))))
- (setq lex-text (string-replace (concat "(" lex-module ")") "" lex-text))
- (let* ((morph (get-text-property pos 'morph object))
- (morph-module nil)
- (morph-text
- (cond ((null morph) nil)
- ((string-match "robinson:" morph)
- (setq morph-module "Robinson")
- (bm--morph-database-lookup (replace-regexp-in-string "robinson:" "" morph) morph-module robinson-hash))
- ((string-match "packard:" morph)
- (setq morph-module "Packard")
- (bm--morph-database-lookup (replace-regexp-in-string "packard:" "" morph) morph-module packard-hash))
- ((string-match "oshm:" morph)
- (setq morph-module "OSHM")
- (bm--morph-database-lookup (replace-regexp-in-string "oshm:" "" morph) morph-module oshm-hash)))))
- (when lex-text
- (setq lex-morph-text (string-trim (string-fill lex-text 75))))
- (when morph-text
- (setq lex-morph-text
- (concat lex-morph-text "\n\n"
- (string-trim (string-replace (concat "(" morph-module ")") "" morph-text)))))
- ;; This prevents bogus command substitutions in the tooltip by
- ;; removing backslashes. XXX I couldn't figure out a better way
- ;; to bypass command substitution in the tooltips.
- (setq lex-morph-text (replace-regexp-in-string "\\\\" "" lex-morph-text)))))
- (defun bm--process-word (item iproperties)
- "Word study. Add tooltips for definitions and morphologyl.
- Insert lemmas in buffer. Must be done after item is inserted in buffer."
- (let ((word (dom-text item))
- (morph (dom-attr item 'morph))
- (savlm (dom-attr item 'savlm))
- (divinename (dom-by-tag item 'divinename)))
- (insert word)
- (let ((refstart (- (point) (length word)))
- (refend (point)))
- ;; Red letter
- (when (plist-get iproperties 'jesus)
- (add-face-text-property refstart refend '(:foreground "red")))
- ;; Special case this. XXX Some modules do this differently.
- (when divinename
- (insert "LORD")
- (let* ((refstart (- (point) (length "LORD")))
- (refend (point))
- (strongs (dom-attr item 'savlm)))
- (string-match "strong:H.*" strongs)
- (let ((strongs-ref (match-string 0 strongs)))
- (add-face-text-property refstart refend 'bold)
- (put-text-property refstart refend 'keymap bm-hebrew-keymap)
- (put-text-property refstart refend 'help-echo 'bm--show-lex-morph)
- (put-text-property refstart refend 'strong strongs-ref))))
- ;; lexical definitions
- (when savlm
- (let ((matched nil))
- (cond ((string-match "strong:G.*" savlm) ; Greek
- (setq matched (match-string 0 savlm))
- (put-text-property refstart refend 'keymap bm-greek-keymap))
- ((string-match "strong:H.*" savlm) ; Hebrew
- (setq matched (match-string 0 savlm))
- (put-text-property refstart refend 'keymap bm-hebrew-keymap)))
- ;; Add help-echo, strongs reference for tooltips if match.
- (when matched
- (setq-local bm-has-strongs t)
- (put-text-property refstart refend 'help-echo 'bm--show-lex-morph)
- (put-text-property refstart refend 'strong matched))))
- ;; morphology
- (when morph
- (let ((matched nil))
- (cond ((string-match "robinson:.*" morph) ; Robinson Greek morphology
- (setq matched (match-string 0 morph)))
- ((string-match "packard:.*" morph) ; Packard Greek morphology --- LXX seems to use this
- (setq matched (match-string 0 morph)))
- ((string-match "oshm:.*" morph) ; OSHM Hebrew morphology
- (setq matched (match-string 0 morph)))
- (t nil
- ;;(message "Unknown morphology %s" morph)
- ))
- (when matched
- (setq-local bm-has-morphology t)
- (put-text-property refstart refend 'morph matched)
- (put-text-property refstart refend 'help-echo 'bm--show-lex-morph))))
- ;; Insert lemma into buffer. Lemma tag will be part of savlm item.
- (when (and bm-word-study-enabled savlm (string-match "lemma.*:.*" savlm))
- (dolist (word (split-string (match-string 0 savlm) " "))
- (setq word (replace-regexp-in-string "[.:a-zA-Z0-9]+" "" word))
- (insert " " word)
- (let ((refstart (- (point) 1 (length word)))
- (refend (point)))
- (add-face-text-property refstart refend '(:foreground "blue"))
- (put-text-property refstart refend 'keymap bm-lemma-keymap)))))))
- (defun bm--insert-domnode-recursive (node &optional iproperties notitle)
- "Recursively parses a domnode from `libxml-parse-html-region's usage on text
- produced by `bm--exec-diatheke'. Outputs text to active buffer
- with properties.
- In processing subnodes, each case will prepend a space if it needs it."
- (if (and bm-red-letter-enabled (equal (dom-attr node 'who) "Jesus"))
- ;; For red-letter display.
- (setq iproperties (plist-put iproperties 'jesus t))
- (setq iproperties nil))
- ;; (when (equal (dom-tag node) 'title)
- ;; ;; Space one line down so there's room for the title at the beginning.
- ;; (insert "\n"))
- (dolist (subnode (dom-children node))
- (cond ((null subnode) nil)
- ((stringp subnode)
- ;; Insert the subnode. Highlight the verse references.
- (insert subnode)
- ;; XXX this is still not quite right
- (let ((verse-start (string-match bm-verse-regexp subnode)))
- (when verse-start
- (let* ((verse-match (string-trim (match-string 0 subnode)))
- (verse-start-text (string-trim-left (substring subnode verse-start (length subnode))))
- (start (- (point) 1 (length (string-trim-right verse-start-text)))))
- (add-face-text-property start (+ start (length (string-trim-right verse-match))) '(:foreground "purple"))))))
- ((eq (dom-tag subnode) 'title)
- (if notitle nil
- (progn
- (setq bm-chapter-title subnode))))
- ((eq (dom-tag subnode) 'body) (bm--insert-domnode-recursive subnode iproperties notitle))
- ((eq (dom-tag subnode) 'seg) ; NASB Module uses this to indicate OT quotations (and others?).
- (bm--insert-domnode-recursive subnode iproperties notitle))
- ((eq (dom-tag subnode) 'q) (bm--insert-domnode-recursive subnode iproperties notitle))
- ((eq (dom-tag subnode) 'p) (bm--insert-domnode-recursive subnode iproperties notitle))
- ((eq (dom-tag subnode) 'w) (insert " ") (bm--process-word subnode iproperties))
- ((eq (dom-tag subnode) 'milestone) (insert "\n"))
- ((eq (dom-tag subnode) 'transchange) ; Word inserted by translation, not in original, give visual indication.
- (let ((word (dom-text subnode)))
- (insert " " word)
- (add-face-text-property (- (point) (length word)) (point) '(:foreground "gray50")))))))
- (defvar bm-debugme nil)
- (setf bm-debugme nil)
- (defun bm--display (&optional verse)
- "Renders text for `bible-mode'"
- ;; Clear buffer and insert the result of calling bm--exec-diatheke.
- (setq buffer-read-only nil)
- (erase-buffer)
- (setq bm-chapter-title nil
- bm-has-strongs nil
- bm-has-morphology nil)
- (insert (bm--exec-diatheke (concat bm-current-book-name ":" (number-to-string bm-current-chapter))))
- ;; Parse the xml in the buffer into a DOM tree.
- (let ((html-dom-tree (libxml-parse-html-region (point-min) (point-max))))
- ;; Render the DOM tree into the buffer.
- (if (not bm-debugme)
- (progn
- (erase-buffer)
- ;; Looking for the "body" tag in the DOM node.
- (bm--insert-domnode-recursive (dom-by-tag html-dom-tree 'body) nil nil)
- (goto-char (point-min)))
- ;;; (shr-render-region (point-min) (point-max))
- ))
- ;; Remove the module name from the buffer.
- (while (search-forward (concat "(" bm-module ")") nil t)
- (replace-match ""))
- ;; Set the mode line of the biffer.
- (setq mode-name (concat "Bible ("
- bm-module
- (when bm-has-strongs " Lex")
- (when bm-has-morphology " Morph")
- ")"))
- ;; Deal with chapter titles (i.e. in Psalms)
- ;; N.B. This won't change a title inside a chapter, and so it
- ;; doesn't work with Psalm 119 where the acrostic letters get
- ;; printed as "titles".
- (when bm-chapter-title ; This gets set in bm-insert-domnode-recursive.
- (goto-char (point-min))
- (let ((title-text (dom-texts bm-chapter-title))
- (refstart (point-min))
- refend)
- ;; Insert and make bold the title.
- (when (string-or-null-p title-text)
- (insert title-text "\n")
- (setq refend (point))
- (put-text-property refstart refend 'face 'bold))))
- (setq buffer-read-only t)
- (goto-char (point-min))
- ;; If optional verse specification go to that verse.
- (when verse
- (goto-char (string-match (regexp-opt `(,(concat ":" (number-to-string verse) ":"))) (buffer-string)))
- (beginning-of-line)))
- (defun bm--list-biblical-modules ()
- "Returns a list of accessible Biblical Text modules."
- (let ((text (bm--exec-diatheke "modulelist" nil nil nil "system"))
- modules)
- (catch 'done
- (dolist (line (split-string text "\n"))
- (when (equal line "Commentaries:")
- (throw 'done nil))
- (when (not (equal "Biblical Texts:" line))
- (push (split-string line " : ") modules))))
- modules))
- (defun bm-pick-module ()
- (interactive)
- (let ((item (get-text-property (point) 'module)))
- (setq-default bm-module item)
- (bible-open)))
-
- (defconst bm-module-map (make-keymap))
- (define-key bm-module-map [mouse-1] 'bm-pick-module)
- (defun bm-display-available-modules ()
- (interactive)
- (let ((buf (get-buffer-create "Modules"))
- (mods (bm--list-biblical-modules)))
- (set-buffer buf)
- (module-select-mode)
- (setq buffer-read-only nil)
- (erase-buffer)
- (dolist (mod mods)
- (insert
- (propertize (car mod)
- 'face 'bold
- 'module (car mod)
- 'help-echo (concat "Select " (car mod))
- 'keymap bm-module-map)
- "\t\t"
- (format "%s\n" (cadr mod))))
- (setq buffer-read-only t)
- (goto-char (point-min))
- (pop-to-buffer buf nil t)))
- ;;;;; Bible Searching
- (defun bm--open-search (query searchmode)
- "Opens a search buffer of QUERY using SEARCHMODE."
- (let ((buf (get-buffer-create (concat "*bible-search-" (downcase bm-module) "-" query "*"))))
- (set-buffer buf)
- (bible-search-mode)
- (bm--display-search query searchmode bm-module)
- (pop-to-buffer buf nil t)))
- (defun bm--display-search (query searchmode mod)
- "Renders results of search QUERY from SEARHCMODE"
- (setq buffer-read-only nil)
- (erase-buffer)
-
- (let* ((result (string-trim (replace-regexp-in-string
- "Entries .+?--" ""
- (bm--exec-diatheke query nil "plain" searchmode mod))))
- (match 0)
- (matchstr "")
- (verses nil)
- (query-verses "")
- fullverses)
- (if (equal result (concat "none (" bm-module ")"))
- (insert "No results found." (when (equal searchmode "lucene") " Verify index has been build with mkfastmod."))
- (progn
- (while match
- (setq match (string-match ".+?:[0-9]?[0-9]?" result (+ match (length matchstr)))
- matchstr (match-string 0 result))
- (when match
- (push
- ;; Massage match to make it more sortable, get rid of
- ;; some characters.
- (replace-regexp-in-string
- "I " "1"
- (replace-regexp-in-string
- "II " "2"
- (replace-regexp-in-string ".+; " "" matchstr)))
- verses)))
- (setq match 0)
- (setq verses (sort verses))
- (dolist (verse verses)
- (if query-verses
- (setq query-verses (concat query-verses ";" verse))
- (setq query-verses verse)))
- (setq fullverses (bm--exec-diatheke query-verses))
- (insert fullverses)
-
- (let* ((html-dom-tree (libxml-parse-html-region (point-min) (point-max))))
- (erase-buffer)
- (bm--insert-domnode-recursive (dom-by-tag html-dom-tree 'body) nil nil)
- (goto-char (point-min))
- (while (search-forward (concat "(" bm-module ")") nil t)
- (replace-match "")))))
- (setq mode-name (concat "Bible Search (" bm-module ")"))
- (setq buffer-read-only t)
- (setq-local bm-search-query query)
- (setq-local bm-search-mode searchmode)
- (goto-char (point-min))))
- ;;;;; Terms
- ;;(defun bm-display-morphology (morph)
- ;; ;; xxx Do something here?
- ;; )
- (defun bm--display-term (termtype)
- (setq buffer-read-only nil)
- (cl-do* ((text (buffer-string))
- (match (string-match "[0-9]+" text) (string-match "[0-9]+" text (match-end 0))))
- ((not match))
- (let* ((matchstr (match-string 0 text))
- (matchstrlen (length matchstr))
- (refstart (+ match 1))
- (refend (+ match 1 matchstrlen)))
- ;; This enables clicking on the Strong's numbers inside the term display.
- (cond ((eq termtype 'hebrew)
- (put-text-property refstart refend 'strong (concat "strong:H" matchstr))
- (put-text-property refstart refend 'keymap bm-hebrew-keymap)
- (add-face-text-property refstart refend `(:foreground "blue")))
- ((and (not bm-use-abbott) (eq termtype 'greek)) ; Abbott entries don't have Strong's numbers
- (put-text-property refstart refend 'strong (concat "strong:G" matchstr))
- (put-text-property refstart refend 'keymap bm-greek-keymap)
- (add-face-text-property refstart refend `(:foreground "blue"))))))
-
- (goto-char (point-min))
- ;; (while (search-forward (concat "(" bm-module ")") nil t)
- ;; (replace-match ""))
- (while (search-forward "()" nil t)
- (replace-match ""))
- (goto-char (point-min))
- (setq buffer-read-only t))
- (defun bm--open-term-hebrew (term)
- "Opens a buffer of the Strong's Hebrew TERM's definition"
- (let ((buf (get-buffer-create (concat "*bible-term-hebrew-" term "*"))))
- (set-buffer buf)
- (bible-term-hebrew-mode)
- (bm--display-term-hebrew term)
- (pop-to-buffer buf nil t)
- (fit-window-to-buffer)))
- (defun bm--open-term-greek (term)
- "Opens a buffer of the Strong's Greek TERM's definition"
- (let ((buf (get-buffer-create (concat "*bible-term-greek-" term "*"))))
- (set-buffer buf)
- (bible-term-greek-mode)
- (bm--display-term-greek term)
- (pop-to-buffer buf nil t)
- (fit-window-to-buffer)))
- ;;;
- ;;; Note: Hebrew display of terms is backwards; set bidi direction to
- ;;; 'left-to-right.
- (defun bm--display-term-hebrew (term)
- "Render the definition of the Strong's Hebrew TERM. Use
- bidi-paragraph-direction so the English text will render
- left-to-right. XXX Why doesn't this work for the tooltips?"
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert (replace-regexp-in-string
- (regexp-opt `(,bm-hebrew-lexicon))
- ""
- (bm--exec-diatheke term nil "plain" nil bm-hebrew-lexicon)
- nil nil nil 7
- ))
- (bm--display-term 'hebrew)
- (setq bidi-paragraph-direction 'left-to-right))
- (defun bm--display-term-greek (term)
- "Render the definition of the Strong's Greek TERM."
- (setq buffer-read-only nil)
- (erase-buffer)
- (if bm-use-abbott
- (insert (replace-regexp-in-string "\(AbbottSmith\)" "" (bm--lookup-lex-def-abbott term)))
- (insert (replace-regexp-in-string
- (regexp-opt `(,bm-greek-lexicon))
- ""
- (bm--exec-diatheke term nil "plain" nil bm-greek-lexicon)
- nil nil nil 7
- )))
- (bm--display-term 'greek))
- (defun bm--set-location (book chapter &optional verse)
- "Sets the global chapter of the active `bible-mode' buffer."
- (setq-local bm-current-book book)
- (setq-local bm-current-book-name (car book))
- (setq-local bm-current-chapter chapter)
- (bm--display verse))
- ;;;;; Utilities
- (defun bm--list-number-range (min max &optional prefix)
- "Returns a list containing entries for each integer between min and max.
- Used in tandem with `completing-read' for chapter selection."
- (let ((range-list nil))
- (dotimes (num (1+ max))
- (when (>= num min)
- (push (cons (concat prefix (number-to-string num)) num) range-list)))
- (nreverse range-list)))
- ;;; Provides
- (provide 'bible-mode)
- ;; Local Variables:
- ;; read-symbol-shorthands: (("bm-" . "bible-mode-"))
- ;; End:
|