Neovim plugin to query Bible verses and display them on the screen or insert them into the current buffer.
Insertion is done on the line below the current cursor position.
- Neovim >= 0.9.1
- nui.nvim: used for UI components.
- Diatheke: backend for verse querying.
Post installation, it is recommended to run
:checkhealth bible-verse
to make sure all dependencies are installed and can be accessed by the plugin.
This plugin is not set up by default. The only mandatory configuration to be supplied is diatheke.translation
.
Using lazy.nvim:
-- lazy.nvim
{
"anthony-halim/bible-verse.nvim",
-- Lazy load on plugin commands
cmd = { "BibleVerse", "BibleVerseQuery", "BibleVerseInsert" },
dependencies = {
"MunifTanjim/nui.nvim",
},
opts = {
diatheke = {
-- (MANDATORY)
-- Corresponds to the diatheke module; diatheke's -b flag.
-- In this example, we are using KJV module.
translation = "KJV",
},
},
-- plugin is not set up by default
config = true,
}
For full opts, see Configuration.
Diatheke is one of the front-ends to the SWORD Project by CrossWire Bible Society and is used as the backend of this plugin to query the verses.
Below are the installation snippets for your convenience. Note that this is not the official method of installation by any means.
MacOS Installation
# Install SWORD
brew install sword
export SWORD_PATH="${HOME}/.sword"
mkdir -p "${SWORD_PATH}/mods.d"
yes "yes" 2>/dev/null | installmgr -init # create a basic user config file
yes "yes" 2>/dev/null | installmgr -sc # sync config with known remote repos
# Sample module installation with CrossWire remote source and KJV module.
yes "yes" 2>/dev/null | installmgr -r CrossWire # refresh remote source
yes "yes" 2>/dev/null | installmgr -ri CrossWire KJV # install KJV module from the remote source
Ubuntu Installation
# Install SWORD
sudo apt install -y libsword-utils diatheke
export SWORD_PATH="${HOME}/.sword"
mkdir -p "${SWORD_PATH}/mods.d"
yes "yes" 2>/dev/null | installmgr -init # create a basic user config file
yes "yes" 2>/dev/null | installmgr -sc # sync config with known remote repos
# Sample module installation with CrossWire remote source and KJV module.
yes "yes" 2>/dev/null | installmgr -r CrossWire # refresh remote source
yes "yes" 2>/dev/null | installmgr -ri CrossWire KJV # install KJV module from the remote source
Add $SWORD_PATH
to your shell profile to ensure Diatheke modules can be found.
# Example: adding to ZSH's .zshrc
echo 'export SWORD_PATH="${HOME}/.sword" >> ~/.zshrc'
This plugin does not set any key bindings by default. Example of setting keymaps:
Via Lua Vim API
vim.keymap.set("n", "<leader>Bq", "<cmd>BibleVerse query<cr>", { desc = "Bible query" })
vim.keymap.set("n", "<leader>Bi", "<cmd>BibleVerse insert<cr>", { desc = "Bible insert" })
Via lazy.nvim at installation phase
{
... -- Other lazy.nvim configurations
init = function()
-- (OPTIONAL)
-- Register to which-key.nvim for prefix visibility
require("which-key").register({
["<leader>"] = {
B = {
name = "+Bible",
},
},
})
end,
opts = {
-- Configurations
...
}
keys = {
{ "<leader>Bq", "<cmd>BibleVerse query<cr>", desc = "Bible query" },
{ "<leader>Bi", "<cmd>BibleVerse insert<cr>", desc = "Bible insert" },
},
}
Below is the full configuration as well as the defaults. You can override any of these options during the plugin installation.
{
-- default_behaviour: behaviour to be used on empty command arg, i.e. :BibleVerse. Defaults to query.
-- Options: "query" - on verse query, display the result on the screen as a popup.
-- "insert" - on verse query, insert the result below the cursor of the current buffer.
default_behaviour = "query",
-- query_format: text format on 'query' behaviour.
-- Options: "bibleverse" - query as bibleverse formatted text.
-- "plain" - query as plain text.
query_format = "bibleverse",
-- insert_format: text format on 'insert' behaviour.
-- Options: "markdown" - insert as Markdown-formatted text.
-- "plain" - insert as plain text.
insert_format = "markdown",
-- Forbid plugin on the following buffer filetypes
exclude_buffer_filetypes = { "neo-tree", "NvimTree" },
diatheke = {
-- (MANDATORY) translation: diatheke module to be used.
translation = "",
-- locale: locale as locales in the machine.
locale = "en",
},
formatter = {
-- Formatter settings for markdown
markdown = {
-- separator: text to be used as separator between chapters. Set to empty string to disable.
separator = "---",
-- quote_block: put the formatted text within a quote block.
quote_block = true,
-- omit_translation_footnote: omit translation name from the markdown text.
omit_translation_footnote = false,
},
-- Formatter settings for plain
plain = {
-- header_delimiter: text to be used to separate between the content of verse and the verse.
header_delimiter = " ",
-- omit_translation_footnote: omit translation name from the markdown text.
omit_translation_footnote = true,
},
-- Formatter settings for bibleverse
bibleverse = {
-- separator: text to be used as separator between chapters. Set to empty string to disable.
separator = "ξ©Ό ",
-- omit_translation_footnote: omit translation name from the bibleverseFont text.
omit_translation_footnote = false,
}
},
highlighter = {
-- To see all highlight groups that are currently active,
-- :so $VIMRUNTIME/syntax/hitest.vim
-- see :h highlight
-- Highlighting for bibleverse text
bibleverse = {
-- highlighting for book and chapter of the output e.g. John 1
book_chapter = {
hlgroup = "Title", -- Highlight group to use to highlight the text
},
-- highlighting for verse number the output
verse_number = { hlgroup = "Number" },
-- highlighting for translation used in the output
translation = { hlgroup = "ModeMsg" },
-- highlighting for separator between book chapters used in the output
separator = { hlgroup = "NonText" },
},
},
ui = {
-- insert_input: configuration for input component for prompting input for 'insert' behaviour
-- see https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/input
insert_input = {
enter = true,
focusable = true,
relative = "cursor",
border = {
style = "rounded",
padding = { 0, 1 },
text = {
top = "Insert verse:",
top_align = "left",
},
},
win_options = {
winhighlight = "FloatBorder:FloatBorder",
},
size = {
-- max_width: maximum width of the insert component, in number of cells
max_width = 50, -- custom attribute
height = 1,
},
position = {
row = 1,
col = 0,
},
zindex = 20, -- Must be > popup.zindex
},
-- query_input: configuration for input component for prompting input for 'query' behaviour
-- see https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/input
query_input = {
enter = true,
focusable = true,
relative = "editor",
border = {
style = "rounded",
padding = { 0, 1 },
text = {
top = "Bible Verse",
top_align = "center",
},
},
size = {
max_width = 50,
height = 1,
},
position = "50%",
zindex = 20, -- Must be > popup.zindex
win_options = {
winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
},
},
-- popup: configuration for popup component, extending from Nui configuration.
-- see: https://github.com/MunifTanjim/nui.nvim/tree/main/lua/nui/popup
popup = {
enter = true,
focusable = true,
relative = "editor",
border = {
style = "rounded",
padding = { 1, 1 },
text = {
top = "Bible Verse",
top_align = "center",
},
},
size = {
-- width_percentage: % of current width used for the popup, in float.
-- max_width_percentage: maximum % of current width used for the popup, in float.
-- max_height_percentage: maximum % of current height used for the popup, in float.
width_percentage = 0.5, -- custom attribute
max_width_percentage = 0.8, -- custom attribute
max_height_percentage = 0.7, -- custom attribute
},
position = "50%",
zindex = 10,
win_options = {
winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
},
buf_options = {
modifiable = false,
readonly = true,
},
},
},
}
For how formatter.*
affects the output, see Formatter.
Below are the formatter configurations used to format queried verses.
Markdown
With the default Markdown settings:
separator = "---",
quote_block = true,
omit_translation_footnote = false,
Overall format
> **{book_name} {chapter}**
>
> <sup>{verse_number}</sup>{verse} [<sup>{verse_number}</sup>{verse}...]
>
> {separator}
>
> **{book_name} {chapter}**
>
> <sup>{verse_number}</sup>{verse} [<sup>{verse_number}</sup>{verse}...]
>
> <sub>*{translation}*</sub>
Unrendered sample output
> **John 1**
>
> <sup>51</sup>And he saith unto him, Verily, verily, I say unto you, Hereafter ye shall see heaven open, and the angels of God ascending and descending upon the Son of man.
>
> ---
>
> **John 2**
>
> <sup>1</sup>And the third day there was a marriage in Cana of Galilee; and the mother of Jesus was there:
>
> <sub>*KJV*</sub>
Rendered sample output
John 1
51And he saith unto him, Verily, verily, I say unto you, Hereafter ye shall see heaven open, and the angels of God ascending and descending upon the Son of man.
John 2
1And the third day there was a marriage in Cana of Galilee; and the mother of Jesus was there:
KJV
Plain
With the default plain settings:
header_delimiter = " ",
omit_translation_footnote = true,
Overall format
{book_name} {chapter}:{verse_number}{header_delimiter}{verse}
{book_name} {chapter}:{verse_number}{header_delimiter}{verse}
Sample output
John 1:51 And he saith unto him, Verily, verily, I say unto you, Hereafter ye shall see heaven open, and the angels of God ascending and descending upon the Son of man.
John 2:1 And the third day there was a marriage in Cana of Galilee; and the mother of Jesus was there:
BibleVerse
With the default bibleverse settings:
-- Formatter settings
separator = "ξ©Ό ",
omit_translation_footnote = false,
-- Highlighter settings
book_chapter = { hlgroup = "Title" },
verse_number = { hlgroup = "Number" },
translation = { hlgroup = "ModeMsg" },
separator = { hlgroup = "NonText" },
Overall format
{book_chapter}
{verse_number}{verse} [{verse_number}{verse}...]
{separator}
{book_chapter}
{verse_number}{verse} [{verse_number}{verse}...]
{translation}
Query Bible verse and returns a parsed, but unformatted, Verse[]
object.
This is intended for user who wants to integrate with the plugin programmatically and format the output themselves. For example for integrations, see Recipes.
Lua API
--- If random = true, will query a random verse. Else, we will query query_opt.query.
---@param query_opt { query: string, random: boolean }
require("bible-verse").query(query_opt)
Output:
---@class Verse
---@field book string
---@field chapter string
---@field verse_number string
---@field verse_prefix_newline boolean whether the verse is prepended with newline. Usually indicates when starting a new paragraph.
---@field verse string
---@field verse_suffix_newline boolean whether the verse is followed with newline. Usually indicates when finishing a paragraph.
-- We return Verse[], e.g.
{
{
book = "John",
chapter = "1",
verse_number = "13",
verse_prefix_newline = false,
verse = "Which were born, not of blood, nor of the will of the flesh, nor of the will of man, but of God.",
verse_suffix_newline = false,
}
}
Query Bible verse and display the result to the screen.
Command
:BibleVerseQuery
or :BibleVerse query
Lua API
--- If query_opt is not supplied, will prompt user input through input UI.
--- If random = true, will query a random verse. Else, we will query query_opt.query.
---@param query_opt? { query: string, random: boolean }
require("bible-verse").query_and_show(query_opt)
Query Bible verse and insert it below the cursor in the current buffer.
Command
:BibleVerseInsert
or :BibleVerse insert
Lua API
--- If query_opt is not supplied, will prompt user input through input UI.
--- If random = true, will query a random verse. Else, we will query query_opt.query.
---@param query_opt? { query: string, random: boolean }
require("bible-verse").query_and_insert(query_opt)
This section show examples of integration with the plugin.
Integration with splash screen
goolord/alpha-nvim configuration snippet
-- Splash screen
{
"goolord/alpha-nvim",
opts = function()
local dashboard = require("alpha.themes.dashboard")
-- Query verse
local verses_result = require("bible-verse").query({ random = true })
-- Format result into table of strings, where each element is individual lines
local verses_fmt_table = {}
for _, verse in ipairs(verses_result) do
local formatted_verse =
string.format("%s %s:%s - %s", verse.book, verse.chapter, verse.verse_number, verse.verse)
table.insert(verses_fmt_table, formatted_verse)
end
-- Apply wrapping at half of editor's width
local verses_fmt_wrap_table = require("bible-verse.utils").wrap(verses_fmt_table, math.floor(vim.o.columns * 0.5))
-- Add as footer
dashboard.section.footer.val = verses_fmt_wrap_table
return dashboard
end,
},
- vim-bible by robertrosman, the original inspiration and Vim equivalent plugin.
- bible.nvim by MasterTemple, Telescope.nvim plugin for accessing Bible within Neovim.
- vim-bible by robertrosman as inspiration for this plugin.
- noice.nvim by folke as inspiration for repository structure, management, and generally on how to write a Neovim plugin. Truly pleasant to work and extend from.