diff options
| author | lukeflo | 2025-02-24 15:29:47 +0000 |
|---|---|---|
| committer | lukeflo | 2025-02-24 15:29:47 +0000 |
| commit | 5da77a2f812a0bb6e0057f7b2e2c642142fca125 (patch) | |
| tree | 6be886693445a54e4cbd7b98151555eec220e863 | |
| parent | dd8dd9611771491e723a49b41cf27b1e9090664d (diff) | |
| parent | aff7c398da005029a293178e487cf5323e507fb4 (diff) | |
| download | bibiman-5da77a2f812a0bb6e0057f7b2e2c642142fca125.tar.gz bibiman-5da77a2f812a0bb6e0057f7b2e2c642142fca125.zip | |
Merge pull request 'Implement config file' (#15) from implement-config into main
Reviewed-on: https://codeberg.org/lukeflo/bibiman/pulls/15
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 112 | ||||
| -rw-r--r-- | Cargo.toml | 7 | ||||
| -rw-r--r-- | README.md | 156 | ||||
| -rw-r--r-- | files/bibiman.toml | 30 | ||||
| -rw-r--r-- | src/app.rs | 58 | ||||
| -rw-r--r-- | src/bibiman.rs | 71 | ||||
| -rw-r--r-- | src/bibiman/bibisetup.rs | 2 | ||||
| -rw-r--r-- | src/cliargs.rs | 34 | ||||
| -rw-r--r-- | src/config.rs | 166 | ||||
| -rw-r--r-- | src/main.rs | 18 | ||||
| -rw-r--r-- | src/tui.rs | 6 | ||||
| -rw-r--r-- | src/tui/popup.rs | 18 | ||||
| -rw-r--r-- | src/tui/ui.rs | 321 | ||||
| -rw-r--r-- | tests/biblatex-test.bib | 662 |
15 files changed, 1061 insertions, 601 deletions
@@ -10,3 +10,4 @@ res/*.png .devbox .envrc devbox.json +example-config.toml @@ -58,6 +58,15 @@ dependencies = [ ] [[package]] +name = "atomic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +dependencies = [ + "bytemuck", +] + +[[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -86,7 +95,7 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bibiman" -version = "0.10.0" +version = "0.11.0" dependencies = [ "arboard", "biblatex", @@ -94,6 +103,7 @@ dependencies = [ "crossterm", "dirs", "editor-command", + "figment", "futures", "itertools", "lexopt", @@ -101,6 +111,7 @@ dependencies = [ "rand", "ratatui", "regex", + "serde", "signal-hook", "tokio", "tokio-util", @@ -133,6 +144,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block2" @@ -250,6 +264,7 @@ dependencies = [ "itoa", "rustversion", "ryu", + "serde", "static_assertions", ] @@ -449,6 +464,21 @@ dependencies = [ ] [[package]] +name = "figment" +version = "0.10.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +dependencies = [ + "atomic", + "parking_lot", + "serde", + "tempfile", + "toml", + "uncased", + "version_check", +] + +[[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1324,6 +1354,7 @@ dependencies = [ "itertools", "lru", "paste", + "serde", "strum", "unicode-segmentation", "unicode-truncate", @@ -1480,18 +1511,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1499,6 +1530,15 @@ dependencies = [ ] [[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] name = "sharded-slab" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1628,9 +1668,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.79" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -1770,6 +1810,40 @@ dependencies = [ ] [[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1835,6 +1909,15 @@ dependencies = [ ] [[package]] +name = "uncased" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" +dependencies = [ + "version_check", +] + +[[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1936,6 +2019,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2219,6 +2308,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] +name = "winnow" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +dependencies = [ + "memchr", +] + +[[package]] name = "wl-clipboard-rs" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1,6 +1,6 @@ [package] name = "bibiman" -version = "0.10.0" +version = "0.11.0" authors = ["lukeflo <lukeflo_git@posteo.de>"] license = "GPL-3.0-or-later" repository = "https://codeberg.org/lukeflo/bibiman" @@ -27,7 +27,7 @@ rand = "0.8" itertools = "0.13.0" lexopt = "0.3.0" nucleo-matcher = "0.3.1" -ratatui = { version = "0.29.0", features = ["unstable-rendered-line-info"]} +ratatui = { version = "0.29.0", features = ["unstable-rendered-line-info", "serde"]} signal-hook = "0.3.17" tokio = { version = "1.39.3", features = ["full"] } tokio-util = "0.7.12" @@ -35,3 +35,6 @@ tui-input = "0.11.0" walkdir = "2.5.0" regex = "1.11.1" ureq = "2.12.1" +# config = { version = "0.15.8", default-features = false, features = ["async", "async-trait", "convert-case", "convert_case", "toml"] } +serde = { version = "1.0.217", features = ["serde_derive"] } +figment = { version = "0.10.19", features = [ "toml", "test" ]} @@ -1,6 +1,6 @@ <div align="center"> -# Bibiman +# Bibiman<a name="bibiman"></a> <!-- [](https://nogithub.codeberg.page/) --> @@ -8,7 +8,28 @@ </div> -## TL;DR +<!-- mdformat-toc start --slug=github --maxlevel=6 --minlevel=1 --> + +- [Bibiman](#bibiman) + - [TL;DR](#tldr) + - [Installation](#installation) + - [Usage](#usage) + - [Configuration](#configuration) + - [Location of Config File](#location-of-config-file) + - [General Configuration](#general-configuration) + - [Color Configuration](#color-configuration) + - [Features](#features) + - [Keybindings](#keybindings) + - [Search](#search) + - [Edit bib entry](#edit-bib-entry) + - [Open connected files or links](#open-connected-files-or-links) + - [Issues and code improvement](#issues-and-code-improvement) + - [Alternatives](#alternatives) + - [Comparison](#comparison) + +<!-- mdformat-toc end --> + +## TL;DR<a name="tldr"></a> `bibiman` is a simple terminal user interface for handling your BibLaTeX database as part of a terminal-based scientific workflow. @@ -17,7 +38,7 @@ Here's a small impression how it looks and works: [](https://postimg.cc/zyj2JsXt) -## Installation +## Installation<a name="installation"></a> You can install `bibiman` directly from `crates.io` using `cargo`: @@ -41,7 +62,7 @@ cargo install --path=. --locked ``` -## Usage +## Usage<a name="usage"></a> The following arguments are possible: @@ -56,6 +77,8 @@ POSITIONAL ARGS: FLAGS: -h, --help Show this help and exit -v, --version Show the version and exit + -c, --config-file= Path to config file for current session needed as argument. + Takes precedence over standard config file --light-terminal Enable color mode for light terminal background ``` @@ -85,45 +108,114 @@ bibman tests/multi-files/ bibiman tests/biblatex-test.bib tests/multi-files/ ``` -Furthermore, in issue #3 it was asked to enable a color customization to run -`bibiman` also in terminal setups with light background. Thus, now it is -possible to enable a light terminal mode with the `--light-terminal` flag. Full -color customization is not possible right now, but maybe will be added with the -implementation of a config file. +## Configuration<a name="configuration"></a> -Here is how the light terminal scheme looks: +### Location of Config File<a name="location-of-config-file"></a> - +`bibiman` can be configured through a config file. The standard location is the +user's config dir following the XDG scheme. On Linux systems this defaults to: -## Features +```bash +# XDG scheme: +$XDG_CONFIG_HOME/bibiman/bibiman.toml + +# Fallback: +$HOME/.config/bibiman/bibiman.toml +``` + +You can set a custom config file through the CLI (`-c`/`--config-file=` flag) +which takes precedence over the standard one for the active session: + +```bash +bibiman --config-file="/path/to/temporary/config" +``` + +### General Configuration<a name="general-configuration"></a> + +The following general values can be set through the config file: + +```toml +[general] +# Default files/dirs which are loaded on startup +# Use absolute paths (~ for HOME works). Otherwise, loading might not work. +bibfiles = [ "/path/to/bibfile", "path/to/dir/with/bibfiles" ] +# Default editor to use when editing files. Arguments are possible +editor = "vim" # with args: "vim -y" +# Default app to open PDFs/Epubs +pdf_opener = "xdg-open" +# Default app to open URLs/DOIs +url_opener = "xdg-open" +``` + +If no file or dir is set as `bibfiles` value, you *have to* add a path via CLI +interface. If the `bibfiles` value is set *and* a further path (or multiple) is +provided through the CLI call, the entries of all those files will be opened in +the started `bibiman` session. + +### Color Configuration<a name="color-configuration"></a> + +Furthermore, it is now possible to customize the colors. The following values +can be changed: + +```toml +[colors] +# Default values for dark-themed terminal +main_text_color = "250" +highlight_text_color = "254" +entry_color = "36" +keyword_color = "101" +info_color = "99" +confirm_color = "47" +warn_color = "124" +bar_bg_color = "234" +popup_bg_color = "234" +selected_row_bg_color = "237" +``` + +Colors can be set through three different methods: +[ANSI color names](https://docs.rs/ratatui/latest/ratatui/style/enum.Color.html), +[256-color indices](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) and +[HEX codes](https://www.w3schools.com/colors/colors_hexadecimal.asp). For +example, the following definitions are all valid: + +```toml +selected_row_bg_color = "darkgray" # ANSI color name (light_black or bright_black would also work) +selected_row_bg_color = "237" # 256-color index +selected_row_bg_color = "#3a3a3a" # HEX code +``` + +To run `bibiman` with some default values for a light-colored terminal use the +`--light-terminal` flag. + +## Features<a name="features"></a> These are the current features, the list will be updated: - [x] **Browse** through the bib entries using _Vim-like keybindings_ and a - _fuzzy search_ mode. + _fuzzy search_ mode. - [x] **Filter** the bib entries by _keywords_ (and afterwards filter further by - fuzzy searching). + fuzzy searching). - [x] **Edit** the current entry by opening a _terminal-based editor_ at the - specific line. + specific line. - [x] **Yank/Copy** the citekey of the current entry to the system clipboard. - [x] **Open related PDF** file (`file` BibLaTeX key) with keypress. - [x] **Open related URL/DOI** with keypress. - [x] **Scrollbar** for better navigating. - [x] **Sort Entries** by column (`Authors`, `Title`, `Year`, `Pubtype`), or by - position in bibfile. + position in bibfile. - [x] **Load multiple files** into one session. - [x] **Add Entry via DOI**. +- [x] **Implement config file** for setting some default values like main + bibfile, PDF-opener, or editor - [ ] **Open related notes file** for specific entry. -- [ ] **Implement config file** for setting some default values like main - bibfile, PDF-opener, or editor - [ ] **Support Hayagriva(`.yaml`)** format as input (_on hold for now_, because - the Hayagriva Yaml style doesn't offer keywords; s. issue in - [Hayagriva repo](https://github.com/typst/hayagriva/issues/240)). + the Hayagriva Yaml style doesn't offer keywords; s. issue in + [Hayagriva repo](https://github.com/typst/hayagriva/issues/240)). **Please feel free to suggest further features through the issue functionality.** -## Keybindings +## Keybindings<a name="keybindings"></a> Use the following keybindings to manage the TUI: @@ -147,7 +239,7 @@ Use the following keybindings to manage the TUI: | `ESC` | Abort search / Reset current list | | `q`, `Ctrl-c` | Quit TUI | -## Search +## Search<a name="search"></a> The search mode uses the `nucleo-matcher` crate. Thus, _fuzzy searching_ is enabled by default. You can use some special chars to alter pattern matching: @@ -156,19 +248,21 @@ enabled by default. You can use some special chars to alter pattern matching: - `...$` matches literally at end of the string. - `'...` matches literally everywhere in string. -## Edit bib entry +## Edit bib entry<a name="edit-bib-entry"></a> -For now, the TUI only supports editors set through the environment variables -`VISUAL` and `EDITOR` in this order. The fallback solution is `vi`. +The main editor can be set through the [config file](#general-configuration). +Otherwise, the environment variables `VISUAL` and `EDITOR` will be used in this +order. The last fallback solution is `vi`. -I've tested the following editors (set as value of `VISUAL`): +I've tested the following editors (set as value of `VISUAL` and through the +config file): - [x] **Helix**: `export VISUAL="hx"` - [x] **Vim/Neovim**: `export VISUAL="vim/nvim"` - [x] **Emacs (Terminal)**: `export VISUAL="emacs -nw"` - [x] **Nano**: `export VISUAL="nano"` - [x] **Emacs (GUI)**: `export VISUAL="emacs"` (open emacs in separate window, - blocks the terminal running `bibiman` as long as emacs is opened) + blocks the terminal running `bibiman` as long as emacs is opened) Feel free to try other editors and report. Important is that the editor supports the argument `+..` to set the line number that the cursor should be placed at. @@ -178,7 +272,7 @@ While this behaviour is most likely supported on UNIX-based systems (Linux, MacOS), it might not work under Windows. I can't test it on a Windows machine, thus, there might be unexpected errors with it. -## Open connected files or links +## Open connected files or links<a name="open-connected-files-or-links"></a> `bibiman` also provides the possibility to open PDFs (as value of the `file` BibLaTeX field), as well as DOIs and URLs. @@ -194,12 +288,12 @@ Furthermore, DOIs have to begin with either `https://doi...` as full URL or `10.(...)` as regular DOI style. URLs work if they begin with either `http...` or with `www...`. -## Issues and code improvement +## Issues and code improvement<a name="issues-and-code-improvement"></a> This is my first Rust project and, thus, also a learning process. If you find any issues or code flaws, please open an issue. -## Alternatives +## Alternatives<a name="alternatives"></a> `bibiman` is a project tailored to my personal needs. I use a single main file for all my bib entries and want to use `bibiman` mainly as kind of @@ -226,7 +320,7 @@ Maybe one of these might fit _your_ personal needs better: - [papis](https://github.com/papis/papis): Powerful CLI tool for managing bibliographies and documents. Has also some TUI features. -### Comparison +### Comparison<a name="comparison"></a> I compared `bibiman` only free-hand to `bibman` (Haskell) and `bibman` (Perl), since there is no simple benchmark test for TUIs. At least, I couldn't find one. diff --git a/files/bibiman.toml b/files/bibiman.toml new file mode 100644 index 0000000..2e5d51b --- /dev/null +++ b/files/bibiman.toml @@ -0,0 +1,30 @@ +# [general] +## Default files/dirs which are loaded on startup +## Use absolute paths (~ for HOME works). Otherwise, loading might not work. +# bibfiles = [ "/path/to/bibfile", "path/to/dir/with/bibfiles" ] + +## Default editor to use when editing files. Arguments are possible +# editor = "vim" # with args: "vim -y" + +## Default app to open PDFs/Epubs +# pdf_opener = "xdg-open" + +## Default app to open URLs/DOIs +# url_opener = "xdg-open" + +# [colors] +## Default values for dark-themed terminal +## Possible values are: +## ANSI color names. E.g. "bright-black" +## 256-colors indices. E.g. "250" +## Hex color codes. E.g. "#3a3a3a" +# main_text_color = "250" +# highlight_text_color = "254" +# entry_color = "36" +# keyword_color = "101" +# info_color = "99" +# confirm_color = "47" +# warn_color = "124" +# bar_bg_color = "234" +# popup_bg_color = "234" +# selected_row_bg_color = "237" @@ -16,6 +16,7 @@ ///// use crate::bibiman::{CurrentArea, FormerArea}; +use crate::config::BibiConfig; use color_eyre::eyre::{Context, Ok, Result}; // use super::Event; use crate::cliargs::CLIArgs; @@ -23,7 +24,6 @@ use crate::tui::commands::InputCmdAction; use crate::tui::popup::PopupKind; use crate::tui::{self, Tui}; use crate::{bibiman::Bibiman, tui::commands::CmdAction}; -use core::panic; use std::ffi::OsStr; use std::path::PathBuf; use std::process::{Command, Stdio}; @@ -46,11 +46,11 @@ pub struct App { impl App { // Constructs a new instance of [`App`]. - pub fn new(args: &CLIArgs) -> Result<Self> { + pub fn new(args: &mut CLIArgs, cfg: &mut BibiConfig) -> Result<Self> { // Self::default() let running = true; let input = Input::default(); - let bibiman = Bibiman::new(args)?; + let bibiman = Bibiman::new(args, cfg)?; Ok(Self { running, bibiman, @@ -59,14 +59,14 @@ impl App { }) } - pub async fn run(&mut self, args: &mut CLIArgs) -> Result<()> { + pub async fn run(&mut self, cfg: &BibiConfig) -> Result<()> { let mut tui = tui::Tui::new()?; tui.enter()?; // Start the main loop. while self.running { // Render the user interface. - tui.draw(self, args)?; + tui.draw(self, cfg)?; // Handle events. match tui.next().await? { Event::Tick => self.tick(), @@ -85,10 +85,10 @@ impl App { } else { CmdAction::from(key_event) }; - self.run_command(command, args, &mut tui)? + self.run_command(command, cfg, &mut tui)? } Event::Mouse(mouse_event) => { - self.run_command(CmdAction::from(mouse_event), args, &mut tui)? + self.run_command(CmdAction::from(mouse_event), cfg, &mut tui)? } Event::Resize(_, _) => {} @@ -110,7 +110,7 @@ impl App { self.running = false; } - pub fn run_command(&mut self, cmd: CmdAction, args: &mut CLIArgs, tui: &mut Tui) -> Result<()> { + pub fn run_command(&mut self, cmd: CmdAction, cfg: &BibiConfig, tui: &mut Tui) -> Result<()> { match cmd { CmdAction::Input(cmd) => match cmd { InputCmdAction::Nothing => {} @@ -142,7 +142,7 @@ impl App { || doi.starts_with("http://doi.org") || doi.starts_with("http://dx.doi.org") { - self.bibiman.handle_new_entry_submission(args, doi); + self.bibiman.handle_new_entry_submission(doi); } else { self.bibiman.popup_area.popup_message( "No valid DOI pattern: ", @@ -268,10 +268,10 @@ impl App { if let Some(PopupKind::Help) = self.bibiman.popup_area.popup_kind { self.bibiman.close_popup(); } else if let Some(PopupKind::OpenRes) = self.bibiman.popup_area.popup_kind { - self.bibiman.open_connected_res()?; + self.bibiman.open_connected_res(cfg)?; } else if let Some(PopupKind::AppendToFile) = self.bibiman.popup_area.popup_kind { - self.bibiman.append_entry_to_file(args)? + self.bibiman.append_entry_to_file()? } } } @@ -303,7 +303,7 @@ impl App { } CmdAction::EditFile => { if let CurrentArea::EntryArea = self.bibiman.current_area { - self.bibiman.run_editor(args, tui)?; + self.bibiman.run_editor(cfg, tui)?; } } CmdAction::Open => { @@ -355,18 +355,9 @@ impl App { } } -pub fn open_connected_file(file: &OsStr) -> Result<()> { +pub fn open_connected_file(cfg: &BibiConfig, file: &OsStr) -> Result<()> { // Build command to execute pdf-reader. 'xdg-open' is Linux standard - // TODO: make custom opener command possible through config - let cmd = { - match std::env::consts::OS { - "linux" => String::from("xdg-open"), - "macos" => String::from("open"), - "windows" => String::from("start"), - _ => panic!("Couldn't detect OS for setting correct opener"), - } - }; - + let cmd = &cfg.general.pdf_opener; // If necessary, replace ~ with /home dir let file = PathBuf::from(file); @@ -374,7 +365,7 @@ pub fn open_connected_file(file: &OsStr) -> Result<()> { // Pass filepath as argument, pipe stdout and stderr to /dev/null // to keep the TUI clean (where is it piped on Windows???) - let _ = Command::new(&cmd) + let _ = Command::new(cmd) .arg(file) .stdout(Stdio::null()) .stderr(Stdio::null()) @@ -384,21 +375,12 @@ pub fn open_connected_file(file: &OsStr) -> Result<()> { Ok(()) } -pub fn open_connected_link(link: &str) -> Result<()> { +pub fn open_connected_link(cfg: &BibiConfig, link: &str) -> Result<()> { // Build command to execute pdf-reader. 'xdg-open' is Linux standard - // TODO: make custom opener command possible through config - let cmd = { - match std::env::consts::OS { - "linux" => String::from("xdg-open"), - "macos" => String::from("open"), - "windows" => String::from("start"), - _ => panic!("Couldn't detect OS for setting correct opener"), - } - }; - + let cmd = &cfg.general.url_opener; // Pass filepath as argument, pipe stdout and stderr to /dev/null // to keep the TUI clean (where is it piped on Windows???) - let _ = Command::new(&cmd) + let _ = Command::new(cmd) .arg(link) .stdout(Stdio::null()) .stderr(Stdio::null()) @@ -418,8 +400,8 @@ pub fn prepare_weblink(url: &str) -> String { } } -fn expand_home(path: &PathBuf) -> PathBuf { - // let path = PathBuf::from(path); +/// Expand leading tilde (`~`) to `/home/user` +pub fn expand_home(path: &PathBuf) -> PathBuf { if path.starts_with("~") { let mut home = dirs::home_dir().unwrap(); let path = path.strip_prefix("~").unwrap(); diff --git a/src/bibiman.rs b/src/bibiman.rs index 71288ce..e36d268 100644 --- a/src/bibiman.rs +++ b/src/bibiman.rs @@ -15,12 +15,13 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// -use crate::app; use crate::bibiman::entries::EntryTableColumn; use crate::bibiman::{bibisetup::*, search::BibiSearch}; use crate::cliargs::CLIArgs; +use crate::config::BibiConfig; use crate::tui::popup::{PopupArea, PopupKind}; use crate::tui::Tui; +use crate::{app, cliargs}; use crate::{bibiman::entries::EntryTable, bibiman::keywords::TagList}; use arboard::Clipboard; use color_eyre::eyre::Result; @@ -61,7 +62,7 @@ pub enum FormerArea { #[derive(Debug)] pub struct Bibiman { // main bib file - // pub main_bibfiles: Vec<PathBuf>, + pub main_bibfiles: Vec<PathBuf>, // main bibliography pub main_biblio: BibiSetup, // search struct: @@ -82,15 +83,19 @@ pub struct Bibiman { impl Bibiman { // Constructs a new instance of [`App`]. - pub fn new(args: &CLIArgs) -> Result<Self> { - // let main_bibfiles = args.fileargs.clone(); - let main_biblio = BibiSetup::new(&args.files); + pub fn new(args: &mut CLIArgs, cfg: &mut BibiConfig) -> Result<Self> { + let mut main_bibfiles: Vec<PathBuf> = args.pos_args.clone(); + if cfg.general.bibfiles.is_some() { + main_bibfiles.append(cfg.general.bibfiles.as_mut().unwrap()) + }; + let main_bibfiles = cliargs::parse_files(main_bibfiles); + let main_biblio = BibiSetup::new(&main_bibfiles); let tag_list = TagList::new(main_biblio.keyword_list.clone()); let search_struct = BibiSearch::default(); let entry_table = EntryTable::new(main_biblio.entry_list.clone()); let current_area = CurrentArea::EntryArea; Ok(Self { - // main_bibfiles, + main_bibfiles, main_biblio, tag_list, search_struct, @@ -128,8 +133,8 @@ impl Bibiman { self.former_area = None; } - pub fn update_lists(&mut self, args: &CLIArgs) { - self.main_biblio = BibiSetup::new(&args.files); + pub fn update_lists(&mut self) { + self.main_biblio = BibiSetup::new(&self.main_bibfiles); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); self.entry_table = EntryTable::new(self.main_biblio.entry_list.clone()); } @@ -325,7 +330,7 @@ impl Bibiman { self.entry_table.entry_table_state.select(Some(idx_count)); } - pub fn run_editor(&mut self, args: &CLIArgs, tui: &mut Tui) -> Result<()> { + pub fn run_editor(&mut self, cfg: &BibiConfig, tui: &mut Tui) -> Result<()> { // get filecontent and citekey for calculating line number let citekey: &str = &self.entry_table.entry_table_items [self.entry_table.entry_table_state.selected().unwrap()] @@ -338,17 +343,17 @@ impl Bibiman { // Check if multiple files were passed to bibiman and // return the correct file path - let filepath = if args.files.len() == 1 { - args.files.first().unwrap().as_os_str() + let filepath = if self.main_bibfiles.len() == 1 { + self.main_bibfiles.first().unwrap().as_os_str() } else { let mut idx = 0; - for f in &args.files { + for f in &self.main_bibfiles { if search::search_pattern_in_file(&citekey_pattern, &f).is_some() { break; } idx += 1; } - args.files[idx].as_os_str() + self.main_bibfiles[idx].as_os_str() }; let filecontent = fs::read_to_string(&filepath).unwrap(); @@ -376,6 +381,7 @@ impl Bibiman { tui.exit()?; // Use VISUAL or EDITOR. Set "vi" as last fallback let mut cmd: Command = EditorBuilder::new() + .source(cfg.general.editor.as_ref()) .environment() .source(Some("vi")) .build() @@ -391,7 +397,7 @@ impl Bibiman { tui.terminal.clear()?; // Update the database and the lists to show changes - Self::update_lists(self, args); + Self::update_lists(self); // Select entry which was selected before entering editor self.select_entry_by_citekey(citekey); @@ -412,7 +418,7 @@ impl Bibiman { ///the new entry via `append_to_file()` function. If not, show error popup /// ///The method needs two arguments: the CLIArgs struct and the `str` containing the DOI - pub fn handle_new_entry_submission(&mut self, args: &CLIArgs, doi_string: &str) { + pub fn handle_new_entry_submission(&mut self, doi_string: &str) { let doi_string = if doi_string.starts_with("10.") { "https://doi.org/".to_string() + doi_string } else { @@ -431,7 +437,7 @@ impl Bibiman { .expect("Couldn't parse fetched entry into string"); self.popup_area.popup_sel_item = entry; self.popup_area.popup_kind = Some(PopupKind::AppendToFile); - self.append_to_file(args); + self.append_to_file(); self.former_area = Some(FormerArea::EntryArea); self.current_area = CurrentArea::PopupArea; self.popup_area.popup_state.select(Some(0)) @@ -441,19 +447,26 @@ impl Bibiman { } } - pub fn append_to_file(&mut self, args: &CLIArgs) { + pub fn append_to_file(&mut self) { let mut items = vec!["Create new file".to_owned()]; - if args.files.len() > 1 { - for f in args.files.clone() { + if self.main_bibfiles.len() > 1 { + for f in self.main_bibfiles.clone() { items.push(f.to_str().unwrap().to_owned()); } } else { - items.push(args.files.first().unwrap().to_str().unwrap().to_owned()); + items.push( + self.main_bibfiles + .first() + .unwrap() + .to_str() + .unwrap() + .to_owned(), + ); } self.popup_area.popup_selection(items); } - pub fn append_entry_to_file(&mut self, args: &mut CLIArgs) -> Result<()> { + pub fn append_entry_to_file(&mut self) -> Result<()> { // Index of selected popup field let popup_idx = self.popup_area.popup_state.selected().unwrap(); @@ -472,8 +485,8 @@ impl Bibiman { let mut file = if self.popup_area.popup_list[popup_idx].contains("Create new file") { let citekey = PathBuf::from(&citekey); // Get path of current files - let path: PathBuf = if args.files[0].is_file() { - args.files[0].parent().unwrap().to_owned() + let path: PathBuf = if self.main_bibfiles[0].is_file() { + self.main_bibfiles[0].parent().unwrap().to_owned() } else { dirs::home_dir().unwrap() // home dir as fallback }; @@ -482,11 +495,11 @@ impl Bibiman { let newfile = path.join(citekey); - args.files.push(newfile.clone()); + self.main_bibfiles.push(newfile.clone()); File::create_new(newfile).unwrap() } else { - let file_path = &args.files[popup_idx - 1]; + let file_path = &self.main_bibfiles[popup_idx - 1]; // Check if similar citekey already exists let file_string = read_to_string(&file_path).unwrap(); @@ -522,7 +535,7 @@ impl Bibiman { // Write content to file file.write_all(self.popup_area.popup_sel_item.as_bytes())?; // Update the database and the lists to reflect the new content - self.update_lists(args); + self.update_lists(); self.close_popup(); // Select newly created entry @@ -531,7 +544,7 @@ impl Bibiman { Ok(()) } - pub fn open_connected_res(&mut self) -> Result<()> { + pub fn open_connected_res(&mut self, cfg: &BibiConfig) -> Result<()> { // Index of selected entry let entry_idx = self.entry_table.entry_table_state.selected().unwrap(); @@ -542,10 +555,10 @@ impl Bibiman { if self.popup_area.popup_list[popup_idx].contains("Weblink") { let object = self.entry_table.entry_table_items[entry_idx].doi_url(); let url = app::prepare_weblink(object); - app::open_connected_link(&url)?; + app::open_connected_link(cfg, &url)?; } else if self.popup_area.popup_list[popup_idx].contains("File") { let object = self.entry_table.entry_table_items[entry_idx].filepath(); - app::open_connected_file(object)?; + app::open_connected_file(cfg, object)?; } else { eprintln!("Unable to find ressource to open"); }; diff --git a/src/bibiman/bibisetup.rs b/src/bibiman/bibisetup.rs index 21b3c4b..3f64d9c 100644 --- a/src/bibiman/bibisetup.rs +++ b/src/bibiman/bibisetup.rs @@ -144,7 +144,7 @@ impl BibiSetup { if main_bibfiles.is_empty() { println!( "{}", - "No bibfile passed as argument. Please select a valid file." + "No bibfile passed as argument or through config file. Please select a valid file." .red() .bold() ); diff --git a/src/cliargs.rs b/src/cliargs.rs index 71ba38c..3c302f4 100644 --- a/src/cliargs.rs +++ b/src/cliargs.rs @@ -17,12 +17,13 @@ use color_eyre::eyre::Result; use color_eyre::owo_colors::OwoColorize; +use dirs::{config_dir, home_dir}; use lexopt::prelude::*; use std::env; use std::path::PathBuf; use walkdir::WalkDir; -use crate::tui::colors::AppColors; +use crate::app; // struct for CLIArgs #[derive(Debug, Default, Clone)] @@ -30,10 +31,8 @@ pub struct CLIArgs { pub helparg: bool, pub versionarg: bool, pub pos_args: Vec<PathBuf>, - pub files: Vec<PathBuf>, - // INFO: AppColors struct later should be moved to config/app struct - // when config file is implemented - pub colors: AppColors, + pub cfg_path: PathBuf, + pub light_theme: bool, } impl CLIArgs { @@ -41,22 +40,25 @@ impl CLIArgs { let mut args = CLIArgs::default(); let mut parser = lexopt::Parser::from_env(); + // Default config + args.cfg_path = if config_dir().is_some() { + config_dir().unwrap().join("bibiman/bibiman.toml") + } else { + home_dir().unwrap().join(".config/bibiman/bibiman.toml") + }; + while let Some(arg) = parser.next()? { match arg { Short('h') | Long("help") => args.helparg = true, Short('v') | Long("version") => args.versionarg = true, - Long("light-terminal") => { - args.colors.light_colors(); - args.colors.toggle_color_scheme() - } + Short('c') | Long("config-file") => args.cfg_path = parser.value()?.parse()?, + Long("light-terminal") => args.light_theme = true, // Value(pos_arg) => parse_files(&mut args, pos_arg), Value(pos_arg) => args.pos_args.push(pos_arg.into()), _ => return Err(arg.unexpected()), } } - args.files = parse_files(args.pos_args.clone()); - Ok(args) } } @@ -64,10 +66,16 @@ impl CLIArgs { /// This function maps a vector containing paths to another vector containing paths. /// But it will walk all entries of the first vec which are directories /// and put only valid file paths with `.bib` ending to the resulting vec. -fn parse_files(args: Vec<PathBuf>) -> Vec<PathBuf> { +pub fn parse_files(args: Vec<PathBuf>) -> Vec<PathBuf> { let mut files: Vec<PathBuf> = Vec::new(); // If pos arg is file, just push it to path vec for i in args { + // Expand tilde to /home/user + let i = if i.starts_with("~") { + app::expand_home(&i) + } else { + i + }; if i.is_file() { files.push(i); // If pos arg is dir, walk dir and collect bibfiles @@ -114,6 +122,8 @@ POSITIONAL ARGS: FLAGS: -h, --help Show this help and exit -v, --version Show the version and exit + -c, --config-file Path to config file used for current session. + Takes precedence over standard config file. --light-terminal Enable color mode for light terminal background", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..956b724 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,166 @@ +// bibiman - a TUI for managing BibLaTeX databases +// Copyright (C) 2024 lukeflo +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. +///// + +use std::path::PathBuf; + +use color_eyre::eyre::Result; +use figment::{ + providers::{Format, Serialized, Toml}, + Figment, +}; +use ratatui::style::Color; +use serde::{Deserialize, Serialize}; + +use crate::cliargs::CLIArgs; + +/// Main struct of the config file. Contains substructs/headings in toml +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct BibiConfig { + pub general: General, + pub colors: Colors, +} + +/// Substruct [general] in config.toml +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +pub struct General { + pub bibfiles: Option<Vec<PathBuf>>, + pub editor: Option<String>, + pub pdf_opener: String, + pub url_opener: String, +} + +/// Substruct [colors] in config.toml +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +pub struct Colors { + pub main_text_color: Color, + pub highlight_text_color: Color, + pub entry_color: Color, + pub keyword_color: Color, + pub info_color: Color, + pub confirm_color: Color, + pub warn_color: Color, + pub bar_bg_color: Color, + pub popup_bg_color: Color, + pub selected_row_bg_color: Color, +} + +impl Default for BibiConfig { + fn default() -> Self { + Self { + general: General { + bibfiles: None, + editor: None, + pdf_opener: select_opener(), + url_opener: select_opener(), + }, + colors: Colors { + main_text_color: Color::Indexed(250), + highlight_text_color: Color::Indexed(254), + entry_color: Color::Indexed(36), + keyword_color: Color::Indexed(101), + info_color: Color::Indexed(99), + confirm_color: Color::Indexed(47), + warn_color: Color::Indexed(124), + bar_bg_color: Color::Indexed(235), + popup_bg_color: Color::Indexed(234), + selected_row_bg_color: Color::Indexed(237), + }, + } + } +} + +impl BibiConfig { + pub fn parse_config(args: &CLIArgs) -> Result<BibiConfig> { + let cfg_file: BibiConfig = if args.cfg_path.is_file() { + Figment::from(Serialized::defaults(BibiConfig::default())) + .merge(Toml::file(&args.cfg_path)) + .extract()? + } else { + BibiConfig::default() + }; + + Ok(cfg_file) + } + + /// Activates the default color scheme for light background terminals + pub fn light_colors(&mut self) { + self.colors.main_text_color = Color::Indexed(235); + self.colors.highlight_text_color = Color::Indexed(232); + self.colors.entry_color = Color::Indexed(23); + self.colors.keyword_color = Color::Indexed(58); + self.colors.info_color = Color::Indexed(57); + self.colors.bar_bg_color = Color::Indexed(144); + self.colors.popup_bg_color = Color::Indexed(187); + self.colors.confirm_color = Color::Indexed(22); + self.colors.selected_row_bg_color = Color::Indexed(107); + } +} + +fn select_opener() -> String { + match std::env::consts::OS { + "linux" => String::from("xdg-open"), + "macos" => String::from("open"), + "windows" => String::from("start"), + _ => panic!("Couldn't detect OS for setting correct opener"), + } +} + +#[cfg(test)] +mod tests { + use figment::{ + providers::{Format, Toml}, + Figment, + }; + + use super::BibiConfig; + + #[test] + fn parse_default_config() { + figment::Jail::expect_with(|jail| { + jail.create_file( + "bibiman.toml", + r#" + [general] + pdf_opener = "xdg-open" + url_opener = "xdg-open" + + [colors] + main_text_color = "250" + highlight_text_color = "254" + entry_color = "36" + keyword_color = "101" + info_color = "99" + confirm_color = "47" + warn_color = "124" + bar_bg_color = "235" + popup_bg_color = "234" + selected_row_bg_color = "237" + "#, + )?; + + let config: BibiConfig = Figment::new().merge(Toml::file("bibiman.toml")).extract()?; + + let default_config: BibiConfig = BibiConfig::default(); + + assert_eq!(config, default_config); + assert_eq!(config.general.bibfiles, None); + assert_eq!(config.general.editor, None); + + Ok(()) + }); + } +} diff --git a/src/main.rs b/src/main.rs index 78c5075..302ba7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,18 +18,20 @@ use app::App; use cliargs::CLIArgs; use color_eyre::eyre::Result; +use config::BibiConfig; use errorsetup::init_error_hooks; pub mod app; pub mod bibiman; pub mod cliargs; +pub mod config; pub mod errorsetup; pub mod tui; #[tokio::main] async fn main() -> Result<()> { // Parse CLI arguments - let mut parsed_args = CLIArgs::parse_args().unwrap(); + let mut parsed_args = CLIArgs::parse_args()?; // Print help if -h/--help flag is passed and exit if parsed_args.helparg { @@ -43,11 +45,21 @@ async fn main() -> Result<()> { std::process::exit(0); } + // Build default config + // let mut cfg = BibiConfig::default(); + + // if parsed_args.light_theme { + // cfg.light_colors(); + // } + // // Merge values from config file if present + // cfg.parse_config(&parsed_args)?; + + let mut cfg = BibiConfig::parse_config(&parsed_args)?; init_error_hooks()?; // Create an application. - let mut app = App::new(&parsed_args)?; + let mut app = App::new(&mut parsed_args, &mut cfg)?; - app.run(&mut parsed_args).await?; + app.run(&cfg).await?; Ok(()) } @@ -20,7 +20,7 @@ pub mod commands; pub mod popup; pub mod ui; -use crate::{cliargs::CLIArgs, App}; +use crate::{config::BibiConfig, App}; use crossterm::{ cursor, event::{ @@ -195,11 +195,11 @@ impl Tui { // // [`Draw`]: ratatui::Terminal::draw // [`rendering`]: crate::ui::render - pub fn draw(&mut self, app: &mut App, args: &CLIArgs) -> Result<()> { + pub fn draw(&mut self, app: &mut App, cfg: &BibiConfig) -> Result<()> { // self.terminal.draw(|frame| ui::render(app, frame))?; self.terminal // .draw(|frame| frame.render_widget(app, frame.area()))?; - .draw(|frame| ui::render_ui(app, args, frame))?; + .draw(|frame| ui::render_ui(app, cfg, frame))?; Ok(()) } diff --git a/src/tui/popup.rs b/src/tui/popup.rs index 4ef9fc3..f226429 100644 --- a/src/tui/popup.rs +++ b/src/tui/popup.rs @@ -16,12 +16,12 @@ ///// use ratatui::{ - style::{Color, Stylize}, + style::Stylize, text::{Line, Span, Text}, widgets::ListState, }; -use crate::cliargs::CLIArgs; +use crate::config::BibiConfig; #[derive(Debug)] pub enum PopupKind { @@ -47,7 +47,7 @@ pub struct PopupArea { } impl PopupArea { - pub fn popup_help<'a>(args: &CLIArgs) -> Text<'a> { + pub fn popup_help<'a>(cfg: &BibiConfig) -> Text<'a> { let help = [ ("General", "first"), ("TAB: ", "Toggle areas (Entries, Keywords)"), @@ -89,22 +89,16 @@ impl PopupArea { for (keys, help) in help { if help == "first" { helptext.push(Line::from( - Span::raw(keys) - .bold() - .fg(Color::Indexed(args.colors.main_text_color)), + Span::raw(keys).bold().fg(cfg.colors.main_text_color), )) } else if help == "sub" { helptext.push(Line::from("")); helptext.push(Line::from( - Span::raw(keys) - .bold() - .fg(Color::Indexed(args.colors.main_text_color)), + Span::raw(keys).bold().fg(cfg.colors.main_text_color), )) } else { helptext.push(Line::from(vec![ - Span::raw(keys) - .bold() - .fg(Color::Indexed(args.colors.keyword_color)), + Span::raw(keys).bold().fg(cfg.colors.main_text_color), Span::raw(help), ])) } diff --git a/src/tui/ui.rs b/src/tui/ui.rs index d85f318..2d58aec 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -17,11 +17,11 @@ use std::path::PathBuf; -use super::colors::AppColorScheme; use super::popup::PopupArea; use crate::bibiman::entries::EntryTableColumn; use crate::bibiman::{CurrentArea, FormerArea}; use crate::cliargs::CLIArgs; +use crate::config::BibiConfig; use crate::tui::popup::PopupKind; use crate::App; use ratatui::layout::{Direction, Position}; @@ -52,8 +52,8 @@ pub fn color_list( highlight: u8, max_diff: i32, ) -> Color { - match args.colors.color_scheme { - AppColorScheme::Dark => { + match args.light_theme { + false => { if list_item == sel_item { Color::Indexed(highlight) } else if (list_item - sel_item) > max_diff @@ -68,7 +68,7 @@ pub fn color_list( Color::Indexed(highlight - (list_item - sel_item) as u8) } } - AppColorScheme::Light => { + true => { if list_item == sel_item { Color::Indexed(highlight) } else if (list_item - sel_item) > max_diff @@ -103,7 +103,7 @@ fn count_files(files: &[PathBuf]) -> u16 { count } -pub fn render_ui(app: &mut App, args: &CLIArgs, frame: &mut Frame) { +pub fn render_ui(app: &mut App, cfg: &BibiConfig, frame: &mut Frame) { let [header_area, main_area, footer_area] = Layout::new( Direction::Vertical, [ @@ -128,20 +128,20 @@ pub fn render_ui(app: &mut App, args: &CLIArgs, frame: &mut Frame) { let [tag_area, info_area] = Layout::horizontal([Constraint::Max(25), Constraint::Min(35)]).areas(item_area); - render_header(args, frame, header_area); + render_header(cfg, frame, header_area); if let CurrentArea::SearchArea = app.bibiman.current_area { - render_footer(app, args, frame, footer_area); + render_footer(app, cfg, frame, footer_area); } - render_entrytable(app, args, frame, entry_area); - render_selected_item(app, args, frame, info_area); - render_taglist(app, args, frame, tag_area); - render_file_info(app, args, frame, entry_info_area); + render_entrytable(app, cfg, frame, entry_area); + render_selected_item(app, cfg, frame, info_area); + render_taglist(app, cfg, frame, tag_area); + render_file_info(app, cfg, frame, entry_info_area); if app.bibiman.popup_area.is_popup { - render_popup(app, args, frame); + render_popup(app, cfg, frame); } } -pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { +pub fn render_popup(app: &mut App, cfg: &BibiConfig, frame: &mut Frame) { match app.bibiman.popup_area.popup_kind { Some(PopupKind::Help) => { let block = Block::bordered() @@ -150,13 +150,13 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { .title_alignment(Alignment::Center) .style( Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.popup_bg_color)), + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.popup_bg_color), ) .border_set(symbols::border::THICK) - .border_style(Style::new().fg(Color::Indexed(args.colors.entry_color))); + .border_style(Style::new().fg(cfg.colors.entry_color)); - let text: Text = PopupArea::popup_help(args); + let text: Text = PopupArea::popup_help(cfg); // Calculate max scroll position depending on hight of terminal window // Needed length is number of text lines plus two for borders at bottom and top @@ -191,23 +191,20 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { .title_alignment(Alignment::Center) .style( Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.popup_bg_color)), + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.popup_bg_color), ) .border_set(symbols::border::THICK) - .border_style(Style::new().fg(Color::Indexed(args.colors.entry_color))); + .border_style(Style::new().fg(cfg.colors.entry_color)); // Prepare the input fields let content = vec![Line::from(vec![ - Span::styled( - "DOI: ", - Style::new().fg(Color::Indexed(args.colors.entry_color)), - ), + Span::styled("DOI: ", Style::new().fg(cfg.colors.entry_color)), Span::raw(app.input.value().to_string().clone()), ])]; let paragraph = Paragraph::new(content) .block(block.clone()) - .style(Style::new().fg(Color::Indexed(args.colors.main_text_color))) + .style(Style::new().fg(cfg.colors.main_text_color)) .wrap(Wrap { trim: false }); let doi_lines = paragraph.line_count(area.width / 2); @@ -225,21 +222,17 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { let area = frame.area(); let block = Block::bordered() - .title_top( - " Message " - .bold() - .fg(Color::Indexed(args.colors.confirm_color)), - ) - .border_style(Style::new().fg(Color::Indexed(args.colors.confirm_color))) + .title_top(" Message ".bold().fg(cfg.colors.confirm_color)) + .border_style(Style::new().fg(cfg.colors.confirm_color)) .style( Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.popup_bg_color)), + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.popup_bg_color), ); let content = Paragraph::new(app.bibiman.popup_area.popup_message.clone()) .block(block) - .style(Style::new().fg(Color::Indexed(args.colors.confirm_color))); + .style(Style::new().fg(cfg.colors.confirm_color)); // Calculate popup size. Width is number of string chars plus 2 for border let popup_area = popup_area( @@ -256,21 +249,17 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { let area = frame.area(); let block = Block::bordered() - .title_top( - " Warning " - .bold() - .fg(Color::Indexed(args.colors.warn_color)), - ) + .title_top(" Warning ".bold().fg(cfg.colors.warn_color)) .border_style(Style::new().fg(Color::Red)) .style( Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.popup_bg_color)), + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.popup_bg_color), ); let content = Paragraph::new(app.bibiman.popup_area.popup_message.clone()) .block(block) - .style(Style::new().fg(Color::Indexed(args.colors.warn_color))); + .style(Style::new().fg(cfg.colors.warn_color)); // Calculate popup size. Width is number of string chars plus 2 for border let popup_area = popup_area( @@ -306,15 +295,15 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { .title_alignment(Alignment::Center) .style( Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.popup_bg_color)), + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.popup_bg_color), ) .border_set(symbols::border::THICK) - .border_style(Style::new().fg(Color::Indexed(args.colors.keyword_color))); + .border_style(Style::new().fg(cfg.colors.keyword_color)); let list = List::new(list_items).block(block).highlight_style( Style::new() - // .fg(Color::Indexed(args.colors.entry_color)) + // .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD) .add_modifier(Modifier::REVERSED), ); @@ -330,15 +319,15 @@ pub fn render_popup(app: &mut App, args: &CLIArgs, frame: &mut Frame) { } } -pub fn render_header(args: &CLIArgs, frame: &mut Frame, rect: Rect) { +pub fn render_header(cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { let main_header = Paragraph::new("BIBIMAN – BibLaTeX manager TUI") .bold() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .centered(); frame.render_widget(main_header, rect) } -pub fn render_footer(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rect) { +pub fn render_footer(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { let search_title = { match app.bibiman.former_area { Some(FormerArea::EntryArea) => "Search Entries: ".to_string(), @@ -351,27 +340,27 @@ pub fn render_footer(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rec let block = Block::new() .padding(Padding::horizontal(1)) - .bg(Color::Indexed(args.colors.bar_bg_color)); + .bg(cfg.colors.bar_bg_color); let search_string = Paragraph::new(Line::from(vec![ Span::styled( search_title, if let Some(FormerArea::EntryArea) = app.bibiman.former_area { Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD) } else if let Some(FormerArea::TagArea) = app.bibiman.former_area { Style::new() - .fg(Color::Indexed(args.colors.keyword_color)) + .fg(cfg.colors.keyword_color) .add_modifier(Modifier::BOLD) } else { Style::new() - .fg(Color::Indexed(args.colors.highlight_text_color)) + .fg(cfg.colors.highlight_text_color) .add_modifier(Modifier::BOLD) }, ), Span::raw(app.bibiman.search_struct.search_string.clone()) - .fg(Color::Indexed(args.colors.highlight_text_color)), + .fg(cfg.colors.highlight_text_color), ])) .block(block); @@ -383,7 +372,7 @@ pub fn render_footer(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rec // 1. Basename of the currently loaded file // 2. Keyword by which the entries are filtered at the moment // 3. Currently selected entry and total count of entries -pub fn render_file_info(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rect) { +pub fn render_file_info(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { let block = Block::new() // can also be Block::new // Leave Top empty to simulate one large box with borders of entry list .borders(Borders::LEFT | Borders::RIGHT | Borders::BOTTOM) @@ -393,10 +382,10 @@ pub fn render_file_info(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: symbols::border::PLAIN }) .border_style(if let CurrentArea::EntryArea = app.bibiman.current_area { - Style::new().fg(Color::Indexed(args.colors.highlight_text_color)) + Style::new().fg(cfg.colors.highlight_text_color) } else { Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD) }); @@ -410,47 +399,37 @@ pub fn render_file_info(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: .horizontal_margin(1) .areas(rect); - let file_info = if args.pos_args.len() == 1 && args.pos_args.first().unwrap().is_file() { + let file_info = if app.bibiman.main_bibfiles.len() == 1 + && app.bibiman.main_bibfiles.first().unwrap().is_file() + { Line::from(vec![ - Span::raw("File: ") - .fg(Color::Indexed(args.colors.main_text_color)) - .bold(), - Span::raw(args.pos_args[0].file_name().unwrap().to_string_lossy()) - .fg(Color::Indexed(args.colors.main_text_color)) - .bold(), - ]) - .bg(Color::Indexed(args.colors.bar_bg_color)) - } else if args.pos_args.len() == 1 && args.pos_args.first().unwrap().is_dir() { - Line::from(vec![ - Span::raw("Directory: ") - .bold() - .fg(Color::Indexed(args.colors.main_text_color)), - Span::raw(args.pos_args[0].file_name().unwrap().to_string_lossy()) - .fg(Color::Indexed(args.colors.main_text_color)) - .bold(), - Span::raw("/*.bib") - .fg(Color::Indexed(args.colors.main_text_color)) - .bold(), + Span::raw("File: ").fg(cfg.colors.main_text_color).bold(), + Span::raw( + app.bibiman.main_bibfiles[0] + .file_name() + .unwrap() + .to_string_lossy(), + ) + .fg(cfg.colors.main_text_color) + .bold(), ]) - .bg(Color::Indexed(args.colors.bar_bg_color)) + .bg(cfg.colors.bar_bg_color) } else { Line::from(vec![ Span::raw("Multiple files (") - .fg(Color::Indexed(args.colors.main_text_color)) - .bold(), - Span::raw(count_files(&args.files).to_string()) - .fg(Color::Indexed(args.colors.main_text_color)) + .fg(cfg.colors.main_text_color) .bold(), - Span::raw(")") - .fg(Color::Indexed(args.colors.main_text_color)) + Span::raw(count_files(&app.bibiman.main_bibfiles).to_string()) + .fg(cfg.colors.main_text_color) .bold(), + Span::raw(")").fg(cfg.colors.main_text_color).bold(), ]) - .bg(Color::Indexed(args.colors.bar_bg_color)) + .bg(cfg.colors.bar_bg_color) }; let cur_keywords = Line::from(if !app.bibiman.tag_list.selected_keywords.is_empty() { vec![ - Span::raw("Selected keywords: ").fg(Color::Indexed(args.colors.main_text_color)), + Span::raw("Selected keywords: ").fg(cfg.colors.main_text_color), // Show all keywords in correct order if list is filtered // successively by multiple keywords Span::raw(app.bibiman.tag_list.selected_keywords.join(" → ")) @@ -460,7 +439,7 @@ pub fn render_file_info(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: } else { vec![Span::raw(" ")] }) - .bg(Color::Indexed(args.colors.bar_bg_color)); + .bg(cfg.colors.bar_bg_color); // .render(keyword_area, buf); let item_count = Line::from( @@ -496,38 +475,36 @@ pub fn render_file_info(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: .to_string() }, ) - .fg(Color::Indexed(args.colors.main_text_color)) + .fg(cfg.colors.main_text_color) .bold(), - Span::raw("/").fg(Color::Indexed(args.colors.main_text_color)), + Span::raw("/").fg(cfg.colors.main_text_color), Span::raw(app.bibiman.entry_table.entry_table_items.len().to_string()) - .fg(Color::Indexed(args.colors.main_text_color)), + .fg(cfg.colors.main_text_color), ] } else { vec![Span::raw("No entries")] }, ) .right_aligned() - .bg(Color::Indexed(args.colors.bar_bg_color)); + .bg(cfg.colors.bar_bg_color); frame.render_widget(file_info, file_area); frame.render_widget(cur_keywords, keyword_area); frame.render_widget(item_count, count_area); } -pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rect) { - let entry_box_selected_border_style: Style = - Style::new().fg(Color::Indexed(args.colors.highlight_text_color)); +pub fn render_entrytable(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { + let entry_box_selected_border_style: Style = Style::new().fg(cfg.colors.highlight_text_color); let entry_box_selected_title_style: Style = Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD); - let entry_box_unselected_border_style: Style = - Style::new().fg(Color::Indexed(args.colors.main_text_color)); + let entry_box_unselected_border_style: Style = Style::new().fg(cfg.colors.main_text_color); let entry_box_unselected_title_style: Style = Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD); let selected_table_col_style: Style = Style::new().add_modifier(Modifier::BOLD); let selectec_table_cell_style: Style = Style::new().add_modifier(Modifier::REVERSED); let entry_selected_row_style: Style = Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::BOLD) .add_modifier(Modifier::REVERSED); @@ -557,8 +534,8 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: let header_style = Style::default() .bold() - .fg(Color::Indexed(args.colors.main_text_color)) - .bg(Color::Indexed(args.colors.bar_bg_color)); + .fg(cfg.colors.main_text_color) + .bg(cfg.colors.bar_bg_color); let header = Row::new(vec![ Cell::from( @@ -582,9 +559,9 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: if let EntryTableColumn::Authors = app.bibiman.entry_table.entry_table_selected_column { - Color::Indexed(args.colors.selected_row_bg_color) + cfg.colors.selected_row_bg_color } else { - Color::Indexed(args.colors.bar_bg_color) + cfg.colors.bar_bg_color }, ), ), @@ -608,9 +585,9 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: .bg( if let EntryTableColumn::Title = app.bibiman.entry_table.entry_table_selected_column { - Color::Indexed(args.colors.selected_row_bg_color) + cfg.colors.selected_row_bg_color } else { - Color::Indexed(args.colors.bar_bg_color) + cfg.colors.bar_bg_color }, ), ), @@ -634,9 +611,9 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: .bg( if let EntryTableColumn::Year = app.bibiman.entry_table.entry_table_selected_column { - Color::Indexed(args.colors.selected_row_bg_color) + cfg.colors.selected_row_bg_color } else { - Color::Indexed(args.colors.bar_bg_color) + cfg.colors.bar_bg_color }, ), ), @@ -661,9 +638,9 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: if let EntryTableColumn::Pubtype = app.bibiman.entry_table.entry_table_selected_column { - Color::Indexed(args.colors.selected_row_bg_color) + cfg.colors.selected_row_bg_color } else { - Color::Indexed(args.colors.bar_bg_color) + cfg.colors.bar_bg_color }, ), ), @@ -678,23 +655,24 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: .entry_table_items .iter_mut() .enumerate() - .map(|(i, data)| { + .map(|(_i, data)| { let item = data.ref_vec(); item.into_iter() .map(|content| Cell::from(Text::from(content.to_string()))) .collect::<Row>() .style( - Style::new().fg(color_list( - args, - i as i32, - app.bibiman - .entry_table - .entry_table_state - .selected() - .unwrap_or(0) as i32, - args.colors.highlight_text_color, - 20, - )), + // Style::new().fg(color_list( + // args, + // i as i32, + // app.bibiman + // .entry_table + // .entry_table_state + // .selected() + // .unwrap_or(0) as i32, + // args.colors.highlight_text_color, + // 20, + // )), + Style::new().fg(cfg.colors.highlight_text_color), ) .height(1) }); @@ -747,11 +725,9 @@ pub fn render_entrytable(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: } } -pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rect) { +pub fn render_selected_item(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { // We get the info depending on the item's state. - let style_value = Style::new() - .bold() - .fg(Color::Indexed(args.colors.main_text_color)); + let style_value = Style::new().bold().fg(cfg.colors.main_text_color); let lines = { if app .bibiman @@ -771,10 +747,7 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re lines.push(Line::from(vec![ Span::styled("Authors: ", style_value), // Span::styled(cur_entry.authors.clone(), Style::new().green()), - Span::styled( - cur_entry.authors(), - Style::new().fg(Color::Indexed(args.colors.info_color)), - ), + Span::styled(cur_entry.authors(), Style::new().fg(cfg.colors.info_color)), ])); if cur_entry.subtitle.is_some() { lines.push(Line::from(vec![ @@ -782,19 +755,19 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re Span::styled( cur_entry.title(), Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::ITALIC), ), Span::styled( ": ", Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::ITALIC), ), Span::styled( cur_entry.subtitle(), Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::ITALIC), ), ])); @@ -804,17 +777,14 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re Span::styled( cur_entry.title(), Style::new() - .fg(Color::Indexed(args.colors.entry_color)) + .fg(cfg.colors.entry_color) .add_modifier(Modifier::ITALIC), ), ])); } lines.push(Line::from(vec![ Span::styled("Year: ", style_value), - Span::styled( - cur_entry.year(), - Style::new().fg(Color::Indexed(args.colors.keyword_color)), - ), + Span::styled(cur_entry.year(), Style::new().fg(cfg.colors.keyword_color)), ])); // Render keywords in info box in Markdown code style if !cur_entry.keywords.is_empty() { @@ -827,27 +797,25 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re let mut content = vec![Span::styled("Keywords: ", style_value)]; for k in kw { // Add half block highlighted in bg color to enlarge block - content.push(Span::raw("▐").fg(Color::Indexed(args.colors.bar_bg_color))); + content.push(Span::raw("▐").fg(cfg.colors.bar_bg_color)); content.push(Span::styled( k, - Style::default() - .bg(Color::Indexed(args.colors.bar_bg_color)) - .fg( - // Highlight selected keyword green - if app - .bibiman - .tag_list - .selected_keywords - .iter() - .any(|e| e == k) - { - Color::Green - } else { - Color::Indexed(args.colors.main_text_color) - }, - ), + Style::default().bg(cfg.colors.bar_bg_color).fg( + // Highlight selected keyword green + if app + .bibiman + .tag_list + .selected_keywords + .iter() + .any(|e| e == k) + { + Color::Green + } else { + cfg.colors.main_text_color + }, + ), )); - content.push(Span::raw("▌").fg(Color::Indexed(args.colors.bar_bg_color))); + content.push(Span::raw("▌").fg(cfg.colors.bar_bg_color)); } lines.push(Line::from(content)) } @@ -859,9 +827,7 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re Span::styled("DOI/URL: ", style_value), Span::styled( cur_entry.doi_url(), - Style::new() - .fg(Color::Indexed(args.colors.main_text_color)) - .underlined(), + Style::new().fg(cfg.colors.main_text_color).underlined(), ), ])); } @@ -870,14 +836,14 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re Span::styled("File: ", style_value), Span::styled( cur_entry.filepath().to_string_lossy(), - Style::new().fg(Color::Indexed(args.colors.main_text_color)), + Style::new().fg(cfg.colors.main_text_color), ), ])); } lines.push(Line::from("")); lines.push(Line::from(vec![Span::styled( cur_entry.abstract_text.clone(), - Style::new().fg(Color::Indexed(args.colors.main_text_color)), + Style::new().fg(cfg.colors.main_text_color), )])); lines } else { @@ -894,7 +860,7 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re let block = Block::bordered() .title(Line::raw(" Entry Information ").centered().bold()) .border_set(symbols::border::PLAIN) - .border_style(Style::new().fg(Color::Indexed(args.colors.main_text_color))) + .border_style(Style::new().fg(cfg.colors.main_text_color)) .padding(Padding::horizontal(1)); // INFO: '.line_count' method only possible with unstable-rendered-line-info feature -> API might change: https://github.com/ratatui/ratatui/issues/293#ref-pullrequest-2027056434 @@ -947,19 +913,17 @@ pub fn render_selected_item(app: &mut App, args: &CLIArgs, frame: &mut Frame, re frame.render_widget(item_info, rect); } -pub fn render_taglist(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Rect) { - let keyword_box_selected_border_style: Style = - Style::new().fg(Color::Indexed(args.colors.highlight_text_color)); +pub fn render_taglist(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rect: Rect) { + let keyword_box_selected_border_style: Style = Style::new().fg(cfg.colors.highlight_text_color); let keyword_box_selected_title_style: Style = Style::new() - .fg(Color::Indexed(args.colors.keyword_color)) + .fg(cfg.colors.keyword_color) .add_modifier(Modifier::BOLD); - let keyword_box_unselected_border_style: Style = - Style::new().fg(Color::Indexed(args.colors.main_text_color)); + let keyword_box_unselected_border_style: Style = Style::new().fg(cfg.colors.main_text_color); let keyword_box_unselected_title_style: Style = Style::new() - .fg(Color::Indexed(args.colors.keyword_color)) + .fg(cfg.colors.keyword_color) .add_modifier(Modifier::BOLD); let keyword_selected_row_style: Style = Style::new() - .fg(Color::Indexed(args.colors.keyword_color)) + .fg(cfg.colors.keyword_color) .add_modifier(Modifier::BOLD) .add_modifier(Modifier::REVERSED); @@ -993,18 +957,19 @@ pub fn render_taglist(app: &mut App, args: &CLIArgs, frame: &mut Frame, rect: Re .tag_list_items .iter() .enumerate() - .map(|(i, keyword)| { + .map(|(_i, keyword)| { ListItem::from(keyword.to_owned()).style(Style::new().fg( if app.bibiman.tag_list.tag_list_state.selected().is_some() { - color_list( - args, - i as i32, - app.bibiman.tag_list.tag_list_state.selected().unwrap() as i32, - args.colors.highlight_text_color, - 20, - ) + // color_list( + // args, + // i as i32, + // app.bibiman.tag_list.tag_list_state.selected().unwrap() as i32, + // args.colors.highlight_text_color, + // 20, + // ) + cfg.colors.highlight_text_color } else { - Color::Indexed(args.colors.main_text_color) + cfg.colors.main_text_color }, )) //.bg(color) }) diff --git a/tests/biblatex-test.bib b/tests/biblatex-test.bib index d0fc0a6..0a1202e 100644 --- a/tests/biblatex-test.bib +++ b/tests/biblatex-test.bib @@ -1,378 +1,470 @@ @set{set, - entryset = {herrmann,aksin,yoon}, - annotation = {A \texttt{set} with three members.}, + entryset = {herrmann,aksin,yoon}, + annotation = {A \texttt{set} with three members.}, } @set{stdmodel, - entryset = {glashow,weinberg,salam}, - annotation = {A \texttt{set} with three members discussing the standard model of particle physics.}, + entryset = {glashow,weinberg,salam}, + annotation = {A \texttt{set} with three members discussing the standard + model of particle physics.}, } @collection{matuz:doody, - title = {Contemporary Literary Criticism}, - year = {1990}, - location = {Detroit}, - publisher = {Gale}, - volume = {61}, - pages = {204--208}, - editor = {Matuz, Roger and Miller, Helen}, - keywords = {narration}, - langid = {english}, - langidopts = {variant=american}, - annotation = {A \texttt{collection} entry providing the excerpt information for the \texttt{doody} entry. Note the format of the \texttt{pages} field}, + title = {Contemporary Literary Criticism}, + year = {1990}, + location = {Detroit}, + publisher = {Gale}, + volume = {61}, + pages = {204--208}, + editor = {Matuz, Roger and Miller, Helen}, + keywords = {narration}, + langid = {english}, + langidopts = {variant=american}, + annotation = {A \texttt{collection} entry providing the excerpt information + for the \texttt{doody} entry. Note the format of the \texttt{ + pages} field}, } @article{aksin, - title = {Effect of immobilization on catalytic characteristics of saturated {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck} reactions}, - author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent and {\c{C}}etinkaya, Bekir and Ni, Chaoying and B{\"u}y{\"u}kg{\"u}ng{\"o}r, Orhan and {\"O}zkal, Erhan}, - volume = {691}, - number = {13}, - pages = {3027--3036}, - journaltitle = jomch, - date = {2006}, - indextitle = {Effect of immobilization on catalytic characteristics}, + title = {Effect of immobilization on catalytic characteristics of saturated + {Pd-N}-heterocyclic carbenes in {Mizoroki-Heck} reactions}, + author = {Aks{\i}n, {\"O}zge and T{\"u}rkmen, Hayati and Artok, Levent and { + \c{C}}etinkaya, Bekir and Ni, Chaoying and B{\"u}y{\"u}kg{\"u}ng{\" + o}r, Orhan and {\"O}zkal, Erhan}, + volume = {691}, + number = {13}, + pages = {3027--3036}, + journaltitle = jomch, + date = {2006}, + indextitle = {Effect of immobilization on catalytic characteristics}, } @article{angenendt, - title = {In Honore Salvatoris~-- Vom Sinn und Unsinn der Patrozinienkunde}, - shorttitle = {In Honore Salvatoris}, - author = {Angenendt, Arnold}, - volume = {97}, - pages = {431--456, 791--823}, - journaltitle = {Revue d'Histoire Eccl{\'e}siastique}, - date = {2002}, - langid = {german}, - indextitle = {In Honore Salvatoris}, - annotation = {A German article in a French journal. Apart from that, a typical \texttt{article} entry. Note the \texttt{indextitle} field}, + title = {In Honore Salvatoris~-- Vom Sinn und Unsinn der Patrozinienkunde}, + shorttitle = {In Honore Salvatoris}, + author = {Angenendt, Arnold}, + volume = {97}, + pages = {431--456, 791--823}, + journaltitle = {Revue d'Histoire Eccl{\'e}siastique}, + date = {2002}, + langid = {german}, + indextitle = {In Honore Salvatoris}, + annotation = {A German article in a French journal. Apart from that, a + typical \texttt{article} entry. Note the \texttt{indextitle} + field}, } @book{aristotle:anima, - title = {De Anima}, - author = {Aristotle}, - location = {Cambridge}, - publisher = cup, - date = {1907}, - editor = {Hicks, Robert Drew}, - keywords = {primary, ancient, philosophy, athens}, - langid = {english}, - langidopts = {variant=british}, - annotation = {A \texttt{book} entry with an \texttt{author} and an \texttt{editor}}, + title = {De Anima}, + author = {Aristotle}, + location = {Cambridge}, + publisher = cup, + date = {1907}, + editor = {Hicks, Robert Drew}, + keywords = {primary, ancient, philosophy, athens}, + langid = {english}, + langidopts = {variant=british}, + annotation = {A \texttt{book} entry with an \texttt{author} and an \texttt{ + editor}}, } @book{aristotle:physics, - title = {Physics}, - shorttitle = {Physics}, - author = {Aristotle}, - location = {New York}, - publisher = {G. P. Putnam}, - url = {https://www.infobooks.org/authors/classic/aristotle-books/#Physic}, - date = {1929}, - translator = {Wicksteed, P. H. and Cornford, F. M.}, - keywords = {primary, ancient, philosophy}, - langid = {english}, - langidopts = {variant=american}, - file = {~/Documents/projects/coding/bibiman/tests/aristotle_physics.pdf}, - annotation = {A \texttt{book} entry with a \texttt{translator} field}, + title = {Physics}, + shorttitle = {Physics}, + author = {Aristotle}, + location = {New York}, + publisher = {G. P. Putnam}, + url = {https://www.infobooks.org/authors/classic/aristotle-books/#Physic}, + date = {1929}, + translator = {Wicksteed, P. H. and Cornford, F. M.}, + keywords = {primary, ancient, philosophy}, + langid = {english}, + langidopts = {variant=american}, + file = {~/Documents/projects/coding/bibiman/tests/aristotle_physics.pdf}, + annotation = {A \texttt{book} entry with a \texttt{translator} field}, } @book{aristotle:poetics, - title = {Poetics}, - shorttitle = {Poetics}, - author = {Aristotle}, - location = {Oxford}, - publisher = {Clarendon Press}, - series = {Clarendon {Aristotle}}, - date = {1968}, - editor = {Lucas, D. W.}, - keywords = {primary}, - langid = {english}, - langidopts = {variant=british}, - annotation = {A \texttt{book} entry with an \texttt{author} and an \texttt{editor} as well as a \texttt{series} field}, + title = {Poetics}, + shorttitle = {Poetics}, + author = {Aristotle}, + location = {Oxford}, + publisher = {Clarendon Press}, + series = {Clarendon {Aristotle}}, + date = {1968}, + editor = {Lucas, D. W.}, + keywords = {primary}, + langid = {english}, + langidopts = {variant=british}, + annotation = {A \texttt{book} entry with an \texttt{author} and an \texttt{ + editor} as well as a \texttt{series} field}, } @mvbook{aristotle:rhetoric, - title = {The Rhetoric of {Aristotle} with a commentary by the late {Edward Meredith Cope}}, - shorttitle = {Rhetoric}, - author = {Aristotle}, - publisher = cup, - date = {1877}, - editor = {Cope, Edward Meredith}, - commentator = {Cope, Edward Meredith}, - volumes = {3}, - keywords = {primary}, - langid = {english}, - langidopts = {variant=british}, - sorttitle = {Rhetoric of Aristotle}, - indextitle = {Rhetoric of {Aristotle}, The}, - annotation = {A commented edition. Note the concatenation of the \texttt{editor} and \texttt{commentator} fields as well as the \texttt{volumes}, \texttt{sorttitle}, and \texttt{indextitle} fields}, + title = {The Rhetoric of {Aristotle} with a commentary by the late {Edward + Meredith Cope}}, + shorttitle = {Rhetoric}, + author = {Aristotle}, + publisher = cup, + date = {1877}, + editor = {Cope, Edward Meredith}, + commentator = {Cope, Edward Meredith}, + volumes = {3}, + keywords = {primary}, + langid = {english}, + langidopts = {variant=british}, + sorttitle = {Rhetoric of Aristotle}, + indextitle = {Rhetoric of {Aristotle}, The}, + annotation = {A commented edition. Note the concatenation of the \texttt{ + editor} and \texttt{commentator} fields as well as the \texttt{ + volumes}, \texttt{sorttitle}, and \texttt{indextitle} fields}, } @book{augustine, - title = {Heterogeneous catalysis for the synthetic chemist}, - shorttitle = {Heterogeneous catalysis}, - author = {Augustine, Robert L.}, - location = {New York}, - publisher = {Marcel Dekker}, - date = {1995}, - langid = {english}, - langidopts = {variant=american}, - annotation = {A plain \texttt{book} entry}, - keywords = {chemistry}, + title = {Heterogeneous catalysis for the synthetic chemist}, + shorttitle = {Heterogeneous catalysis}, + author = {Augustine, Robert L.}, + location = {New York}, + publisher = {Marcel Dekker}, + date = {1995}, + langid = {english}, + langidopts = {variant=american}, + annotation = {A plain \texttt{book} entry}, + keywords = {chemistry}, } @book{averroes/bland, - title = {The Epistle on the Possibility of Conjunction with the Active Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}}, - shorttitle = {Possibility of Conjunction}, - author = {Averroes}, - location = {New York}, - publisher = {Jewish Theological Seminary of America}, - series = {Moreshet: Studies in {Jewish} History, Literature and Thought}, - number = {7}, - date = {1982}, - editor = {Bland, Kalman P.}, - translator = {Bland, Kalman P.}, - keywords = {primary}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {Epistle on the Possibility of Conjunction, The}, - annotation = {A \texttt{book} entry with a \texttt{series} and a \texttt{number}. Note the concatenation of the \texttt{editor} and \texttt{translator} fields as well as the \texttt{indextitle} field}, + title = {The Epistle on the Possibility of Conjunction with the Active + Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}}, + shorttitle = {Possibility of Conjunction}, + author = {Averroes}, + location = {New York}, + publisher = {Jewish Theological Seminary of America}, + series = {Moreshet: Studies in {Jewish} History, Literature and Thought}, + number = {7}, + date = {1982}, + editor = {Bland, Kalman P.}, + translator = {Bland, Kalman P.}, + keywords = {primary}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Epistle on the Possibility of Conjunction, The}, + annotation = {A \texttt{book} entry with a \texttt{series} and a \texttt{ + number}. Note the concatenation of the \texttt{editor} and + \texttt{translator} fields as well as the \texttt{indextitle} + field}, } @article{baez/article, - title = {Higher-Dimensional Algebra {V}: 2-Groups}, - author = {Baez, John C. and Lauda, Aaron D.}, - volume = {12}, - pages = {423--491}, - journaltitle = {Theory and Applications of Categories}, - date = {2004}, - version = {3}, - eprint = {math/0307200v3}, - eprinttype = {arxiv}, - langid = {english}, - keywords = {math}, - langidopts = {variant=american}, - annotation = {An \texttt{article} with \texttt{eprint} and \texttt{eprinttype} fields. Note that the arXiv reference is transformed into a clickable link if \texttt{hyperref} support has been enabled. Compare \texttt{baez\slash online}, which is the same item given as an \texttt{online} entry}, + title = {Higher-Dimensional Algebra {V}: 2-Groups}, + author = {Baez, John C. and Lauda, Aaron D.}, + volume = {12}, + pages = {423--491}, + journaltitle = {Theory and Applications of Categories}, + date = {2004}, + version = {3}, + eprint = {math/0307200v3}, + eprinttype = {arxiv}, + langid = {english}, + keywords = {math}, + langidopts = {variant=american}, + annotation = {An \texttt{article} with \texttt{eprint} and \texttt{ + eprinttype} fields. Note that the arXiv reference is + transformed into a clickable link if \texttt{hyperref} support + has been enabled. Compare \texttt{baez\slash online}, which is + the same item given as an \texttt{online} entry}, } @article{bertram, - title = {Gromov invariants for holomorphic maps on {Riemann} surfaces}, - shorttitle = {Gromov invariants}, - author = {Bertram, Aaron and Wentworth, Richard}, - volume = {9}, - number = {2}, - pages = {529--571}, - journaltitle = jams, - date = {1996}, - langid = {english}, - langidopts = {variant=american}, - annotation = {An \texttt{article} entry with a \texttt{volume} and a \texttt{number} field}, + title = {Gromov invariants for holomorphic maps on {Riemann} surfaces}, + shorttitle = {Gromov invariants}, + author = {Bertram, Aaron and Wentworth, Richard}, + volume = {9}, + number = {2}, + pages = {529--571}, + journaltitle = jams, + date = {1996}, + langid = {english}, + langidopts = {variant=american}, + annotation = {An \texttt{article} entry with a \texttt{volume} and a \texttt + {number} field}, } @article{doody, - title = {Hemingway's Style and {Jake's} Narration}, - author = {Doody, Terrence}, - year = {1974}, - journal = {The Journal of Narrative Technique}, - volume = {4}, - number = {3}, - pages = {212--225}, - langid = {english}, - langidopts = {variant=american}, - related = {matuz:doody}, + title = {Hemingway's Style and {Jake's} Narration}, + author = {Doody, Terrence}, + year = {1974}, + journal = {The Journal of Narrative Technique}, + volume = {4}, + number = {3}, + pages = {212--225}, + langid = {english}, + langidopts = {variant=american}, + related = {matuz:doody}, relatedstring = {\autocap{e}xcerpt in}, - annotation = {An \texttt{article} entry cited as an excerpt from a \texttt{collection} entry. Note the format of the \texttt{related} and \texttt{relatedstring} fields}, + annotation = {An \texttt{article} entry cited as an excerpt from a \texttt{ + collection} entry. Note the format of the \texttt{related} and + \texttt{relatedstring} fields}, } @article{gillies, - title = {Herder and the Preparation of {Goethe's} Idea of World Literature}, - author = {Gillies, Alexander}, - series = {newseries}, - volume = {9}, - pages = {46--67}, - journaltitle = {Publications of the English Goethe Society}, - date = {1933}, - langid = {english}, - langidopts = {variant=british}, - annotation = {An \texttt{article} entry with a \texttt{series} and a \texttt{volume} field. Note that format of the \texttt{series} field in the database file}, + title = {Herder and the Preparation of {Goethe's} Idea of World Literature}, + author = {Gillies, Alexander}, + series = {newseries}, + volume = {9}, + pages = {46--67}, + journaltitle = {Publications of the English Goethe Society}, + date = {1933}, + langid = {english}, + langidopts = {variant=british}, + annotation = {An \texttt{article} entry with a \texttt{series} and a \texttt + {volume} field. Note that format of the \texttt{series} field + in the database file}, } @article{glashow, - title = {Partial Symmetries of Weak Interactions}, - author = {Glashow, Sheldon}, - volume = {22}, - pages = {579--588}, - journaltitle = {Nucl.~Phys.}, - date = {1961}, + title = {Partial Symmetries of Weak Interactions}, + author = {Glashow, Sheldon}, + volume = {22}, + pages = {579--588}, + journaltitle = {Nucl.~Phys.}, + date = {1961}, } @article{herrmann, - title = {A carbocyclic carbene as an efficient catalyst ligand for {C--C} coupling reactions}, - author = {Herrmann, Wolfgang A. and {\"O}fele, Karl and Schneider, Sabine K. and Herdtweck, Eberhardt and Hoffmann, Stephan D.}, - volume = {45}, - number = {23}, - pages = {3859--3862}, - journaltitle = anch-ie, - date = {2006}, - indextitle = {Carbocyclic carbene as an efficient catalyst, A}, + title = {A carbocyclic carbene as an efficient catalyst ligand for {C--C} + coupling reactions}, + author = {Herrmann, Wolfgang A. and {\"O}fele, Karl and Schneider, Sabine K. + and Herdtweck, Eberhardt and Hoffmann, Stephan D.}, + volume = {45}, + number = {23}, + pages = {3859--3862}, + journaltitle = anch-ie, + date = {2006}, + indextitle = {Carbocyclic carbene as an efficient catalyst, A}, } @article{murray, - title = {Alkanethiolate gold cluster molecules with core diameters from 1.5 to 5.2~{nm}}, - shorttitle = {Alkanethiolate gold cluster molecules}, - author = {Hostetler, Michael J. and Wingate, Julia E. and Zhong, Chuan-Jian and Harris, Jay E. and Vachet, Richard W. and Clark, Michael R. and Londono, J. David and Green, Stephen J. and Stokes, Jennifer J. and Wignall, George D. and Glish, Gary L. and Porter, Marc D. and Evans, Neal D. and Murray, Royce W.}, - volume = {14}, - number = {1}, - pages = {17--30}, - journaltitle = {Langmuir}, - date = {1998}, - subtitle = {Core and monolayer properties as a function of core size}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {Alkanethiolate gold cluster molecules}, - annotation = {An \texttt{article} entry with \arabic{author} authors. By default, long author and editor lists are automatically truncated. This is configurable}, + title = {Alkanethiolate gold cluster molecules with core diameters from 1.5 + to 5.2~{nm}}, + shorttitle = {Alkanethiolate gold cluster molecules}, + author = {Hostetler, Michael J. and Wingate, Julia E. and Zhong, Chuan-Jian + and Harris, Jay E. and Vachet, Richard W. and Clark, Michael R. and + Londono, J. David and Green, Stephen J. and Stokes, Jennifer J. and + Wignall, George D. and Glish, Gary L. and Porter, Marc D. and Evans + , Neal D. and Murray, Royce W.}, + volume = {14}, + number = {1}, + pages = {17--30}, + journaltitle = {Langmuir}, + date = {1998}, + subtitle = {Core and monolayer properties as a function of core size}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Alkanethiolate gold cluster molecules}, + annotation = {An \texttt{article} entry with \arabic{author} authors. By + default, long author and editor lists are automatically + truncated. This is configurable}, } @article{kastenholz, - title = {Computation of methodology\hyphen independent ionic solvation free energies from molecular simulations}, - author = {Kastenholz, M. A. and H{\"u}nenberger, Philippe H.}, - volume = {124}, - doi = {10.1063/1.2172593}, - journaltitle = jchph, - date = {2006}, - subtitle = {{I}. {The} electrostatic potential in molecular liquids}, - eid = {124106}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {Computation of ionic solvation free energies}, - annotation = {An \texttt{article} entry with an \texttt{eid} and a \texttt{doi} field. Note that the \textsc{doi} is transformed into a clickable link if \texttt{hyperref} support has been enabled}, - abstract = {The computation of ionic solvation free energies from atomistic simulations is a surprisingly difficult problem that has found no satisfactory solution for more than 15 years. The reason is that the charging free energies evaluated from such simulations are affected by very large errors. One of these is related to the choice of a specific convention for summing up the contributions of solvent charges to the electrostatic potential in the ionic cavity, namely, on the basis of point charges within entire solvent molecules (M scheme) or on the basis of individual point charges (P scheme). The use of an inappropriate convention may lead to a charge-independent offset in the calculated potential, which depends on the details of the summation scheme, on the quadrupole-moment trace of the solvent molecule, and on the approximate form used to represent electrostatic interactions in the system. However, whether the M or P scheme (if any) represents the appropriate convention is still a matter of on-going debate. The goal of the present article is to settle this long-standing controversy by carefully analyzing (both analytically and numerically) the properties of the electrostatic potential in molecular liquids (and inside cavities within them).}, + title = {Computation of methodology\hyphen independent ionic solvation free + energies from molecular simulations}, + author = {Kastenholz, M. A. and H{\"u}nenberger, Philippe H.}, + volume = {124}, + doi = {10.1063/1.2172593}, + journaltitle = jchph, + date = {2006}, + subtitle = {{I}. {The} electrostatic potential in molecular liquids}, + eid = {124106}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Computation of ionic solvation free energies}, + annotation = {An \texttt{article} entry with an \texttt{eid} and a \texttt{ + doi} field. Note that the \textsc{doi} is transformed into a + clickable link if \texttt{hyperref} support has been enabled}, + abstract = {The computation of ionic solvation free energies from atomistic + simulations is a surprisingly difficult problem that has found no + satisfactory solution for more than 15 years. The reason is that + the charging free energies evaluated from such simulations are + affected by very large errors. One of these is related to the + choice of a specific convention for summing up the contributions + of solvent charges to the electrostatic potential in the ionic + cavity, namely, on the basis of point charges within entire + solvent molecules (M scheme) or on the basis of individual point + charges (P scheme). The use of an inappropriate convention may + lead to a charge-independent offset in the calculated potential, + which depends on the details of the summation scheme, on the + quadrupole-moment trace of the solvent molecule, and on the + approximate form used to represent electrostatic interactions in + the system. However, whether the M or P scheme (if any) + represents the appropriate convention is still a matter of + on-going debate. The goal of the present article is to settle + this long-standing controversy by carefully analyzing (both + analytically and numerically) the properties of the electrostatic + potential in molecular liquids (and inside cavities within them). + }, } @article{sarfraz, - title = {Technical section: {An} algorithm for automatic capturing of the font outlines}, - author = {M. Sarfraz and M. F. A. Razzak}, - year = {2002}, - journal = {Computers and Graphics}, - volume = {26}, - number = {5}, - pages = {795--804}, - issn = {0097-8493}, - annotation = {An \texttt{article} entry with an \texttt{issn} field}, + title = {Technical section: {An} algorithm for automatic capturing of the + font outlines}, + author = {M. Sarfraz and M. F. A. Razzak}, + year = {2002}, + journal = {Computers and Graphics}, + volume = {26}, + number = {5}, + pages = {795--804}, + issn = {0097-8493}, + annotation = {An \texttt{article} entry with an \texttt{issn} field}, } @article{reese, - title = {Georgia in {Anglo-Spanish} Diplomacy, 1736--1739}, - author = {Reese, Trevor R.}, - series = {3}, - volume = {15}, - pages = {168--190}, - journaltitle = {William and Mary Quarterly}, - date = {1958}, - langid = {english}, - langidopts = {variant=american}, - annotation = {An \texttt{article} entry with a \texttt{series} and a \texttt{volume} field. Note the format of the series. If the value of the \texttt{series} field is an integer, this number is printed as an ordinal and the string \enquote*{series} is appended automatically}, + title = {Georgia in {Anglo-Spanish} Diplomacy, 1736--1739}, + author = {Reese, Trevor R.}, + series = {3}, + volume = {15}, + pages = {168--190}, + journaltitle = {William and Mary Quarterly}, + date = {1958}, + langid = {english}, + langidopts = {variant=american}, + annotation = {An \texttt{article} entry with a \texttt{series} and a \texttt + {volume} field. Note the format of the series. If the value of + the \texttt{series} field is an integer, this number is printed + as an ordinal and the string \enquote*{series} is appended + automatically}, } @article{shore, - title = {Twice-Born, Once Conceived}, - author = {Shore, Bradd}, - series = {newseries}, - volume = {93}, - number = {1}, - pages = {9--27}, - journaltitle = {American Anthropologist}, - date = {1991-03}, - subtitle = {Meaning Construction and Cultural Cognition}, - annotation = {An \texttt{article} entry with \texttt{series}, \texttt{volume}, and \texttt{number} fields. Note the format of the \texttt{series} which is a localization key}, + title = {Twice-Born, Once Conceived}, + author = {Shore, Bradd}, + series = {newseries}, + volume = {93}, + number = {1}, + pages = {9--27}, + journaltitle = {American Anthropologist}, + date = {1991-03}, + subtitle = {Meaning Construction and Cultural Cognition}, + annotation = {An \texttt{article} entry with \texttt{series}, \texttt{volume + }, and \texttt{number} fields. Note the format of the \texttt{ + series} which is a localization key}, } @article{sigfridsson, - title = {Comparison of methods for deriving atomic charges from the electrostatic potential and moments}, - author = {Sigfridsson, Emma and Ryde, Ulf}, - volume = {19}, - number = {4}, - pages = {377--395}, - doi = {10.1002/(SICI)1096-987X(199803)19:4<377::AID-JCC1>3.0.CO;2-P}, - journaltitle = {Journal of Computational Chemistry}, - date = {1998}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {Methods for deriving atomic charges}, - annotation = {An \texttt{article} entry with \texttt{volume}, \texttt{number}, and \texttt{doi} fields. Note that the \textsc{doi} is transformed into a clickable link if \texttt{hyperref} support has been enabled}, - abstract = {Four methods for deriving partial atomic charges from the quantum chemical electrostatic potential (CHELP, CHELPG, Merz-Kollman, and RESP) have been compared and critically evaluated. It is shown that charges strongly depend on how and where the potential points are selected. Two alternative methods are suggested to avoid the arbitrariness in the point-selection schemes and van der Waals exclusion radii: CHELP-BOW, which also estimates the charges from the electrostatic potential, but with potential points that are Boltzmann-weighted after their occurrence in actual simulations using the energy function of the program in which the charges will be used, and CHELMO, which estimates the charges directly from the electrostatic multipole moments. Different criteria for the quality of the charges are discussed.}, + title = {Comparison of methods for deriving atomic charges from the + electrostatic potential and moments}, + author = {Sigfridsson, Emma and Ryde, Ulf}, + volume = {19}, + number = {4}, + pages = {377--395}, + doi = {10.1002/(SICI)1096-987X(199803)19:4<377::AID-JCC1>3.0.CO;2-P}, + journaltitle = {Journal of Computational Chemistry}, + date = {1998}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {Methods for deriving atomic charges}, + annotation = {An \texttt{article} entry with \texttt{volume}, \texttt{number + }, and \texttt{doi} fields. Note that the \textsc{doi} is + transformed into a clickable link if \texttt{hyperref} support + has been enabled}, + abstract = {Four methods for deriving partial atomic charges from the + quantum chemical electrostatic potential (CHELP, CHELPG, + Merz-Kollman, and RESP) have been compared and critically + evaluated. It is shown that charges strongly depend on how and + where the potential points are selected. Two alternative methods + are suggested to avoid the arbitrariness in the point-selection + schemes and van der Waals exclusion radii: CHELP-BOW, which also + estimates the charges from the electrostatic potential, but with + potential points that are Boltzmann-weighted after their + occurrence in actual simulations using the energy function of the + program in which the charges will be used, and CHELMO, which + estimates the charges directly from the electrostatic multipole + moments. Different criteria for the quality of the charges are + discussed.}, } @article{spiegelberg, - title = {\mkbibquote{Intention} und \mkbibquote{Intentionalit{\"a}t} in der Scholastik, bei Brentano und Husserl}, - shorttitle = {Intention und Intentionalit{\"a}t}, - author = {Spiegelberg, Herbert}, - volume = {29}, - pages = {189--216}, - journaltitle = {Studia Philosophica}, - date = {1969}, - langid = {german}, - sorttitle = {Intention und Intentionalitat in der Scholastik, bei Brentano und Husserl}, - indexsorttitle = {Intention und Intentionalitat in der Scholastik, bei Brentano und Husserl}, - annotation = {An \texttt{article} entry. Note the \texttt{sorttitle} and \texttt{indexsorttitle} fields and the markup of the quotes in the database file}, + title = {\mkbibquote{Intention} und \mkbibquote{Intentionalit{\"a}t} in der + Scholastik, bei Brentano und Husserl}, + shorttitle = {Intention und Intentionalit{\"a}t}, + author = {Spiegelberg, Herbert}, + volume = {29}, + pages = {189--216}, + journaltitle = {Studia Philosophica}, + date = {1969}, + langid = {german}, + sorttitle = {Intention und Intentionalitat in der Scholastik, bei Brentano + und Husserl}, + indexsorttitle = {Intention und Intentionalitat in der Scholastik, bei + Brentano und Husserl}, + annotation = {An \texttt{article} entry. Note the \texttt{sorttitle} and + \texttt{indexsorttitle} fields and the markup of the quotes in + the database file}, } @article{springer, - title = {Mediaeval Pilgrim Routes from {Scandinavia} to {Rome}}, - shorttitle = {Mediaeval Pilgrim Routes}, - author = {Springer, Otto}, - volume = {12}, - pages = {92--122}, - journaltitle = {Mediaeval Studies}, - date = {1950}, - langid = {english}, - langidopts = {variant=british}, - annotation = {A plain \texttt{article} entry}, + title = {Mediaeval Pilgrim Routes from {Scandinavia} to {Rome}}, + shorttitle = {Mediaeval Pilgrim Routes}, + author = {Springer, Otto}, + volume = {12}, + pages = {92--122}, + journaltitle = {Mediaeval Studies}, + date = {1950}, + langid = {english}, + langidopts = {variant=british}, + annotation = {A plain \texttt{article} entry}, } @article{weinberg, - title = {A Model of Leptons}, - author = {Weinberg, Steven}, - volume = {19}, - pages = {1264--1266}, - journaltitle = {Phys.~Rev.~Lett.}, - date = {1967}, + title = {A Model of Leptons}, + author = {Weinberg, Steven}, + volume = {19}, + pages = {1264--1266}, + journaltitle = {Phys.~Rev.~Lett.}, + date = {1967}, } @string{anch-ie = {Angew.~Chem. Int.~Ed.}} -@string{cup = {Cambridge University Press}} +@string{cup = {Cambridge University Press}} -@string{dtv = {Deutscher Taschenbuch-Verlag}} +@string{dtv = {Deutscher Taschenbuch-Verlag}} -@string{hup = {Harvard University Press}} +@string{hup = {Harvard University Press}} -@string{jams = {J.~Amer. Math. Soc.}} +@string{jams = {J.~Amer. Math. Soc.}} -@string{jchph = {J.~Chem. Phys.}} +@string{jchph = {J.~Chem. Phys.}} -@string{jomch = {J.~Organomet. Chem.}} +@string{jomch = {J.~Organomet. Chem.}} -@string{pup = {Princeton University Press}} +@string{pup = {Princeton University Press}} @incollection{westfahl:space, - title = {The True Frontier}, - author = {Westfahl, Gary}, - pages = {55--65}, - subtitle = {Confronting and Avoiding the Realities of Space in {American} Science Fiction Films}, - crossref = {westfahl:frontier}, - langid = {english}, - langidopts = {variant=american}, - indextitle = {True Frontier, The}, - annotation = {A cross-referenced article from a \texttt{collection}. This is an \texttt{incollection} entry with a \texttt{crossref} field. Note the \texttt{subtitle} and \texttt{indextitle} fields}, + title = {The True Frontier}, + author = {Westfahl, Gary}, + pages = {55--65}, + subtitle = {Confronting and Avoiding the Realities of Space in {American} + Science Fiction Films}, + crossref = {westfahl:frontier}, + langid = {english}, + langidopts = {variant=american}, + indextitle = {True Frontier, The}, + annotation = {A cross-referenced article from a \texttt{collection}. This is + an \texttt{incollection} entry with a \texttt{crossref} field. + Note the \texttt{subtitle} and \texttt{indextitle} fields}, } @article{yoon, - title = {Palladium pincer complexes with reduced bond angle strain: efficient catalysts for the {Heck} reaction}, - author = {Yoon, Myeong S. and Ryu, Dowook and Kim, Jeongryul and Ahn, Kyo Han}, - volume = {25}, - number = {10}, - pages = {2409--2411}, - journaltitle = {Organometallics}, - date = {2006}, - indextitle = {Palladium pincer complexes}, + title = {Palladium pincer complexes with reduced bond angle strain: + efficient catalysts for the {Heck} reaction}, + author = {Yoon, Myeong S. and Ryu, Dowook and Kim, Jeongryul and Ahn, Kyo + Han}, + volume = {25}, + number = {10}, + pages = {2409--2411}, + journaltitle = {Organometallics}, + date = {2006}, + indextitle = {Palladium pincer complexes}, } |
