diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..389159a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+# Created by https://www.toptal.com/developers/gitignore/api/rust
+# Edit at https://www.toptal.com/developers/gitignore?templates=rust
+
+### Rust ###
+# Generated by Cargo
+# will have compiled files and executables
+debug/
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+# MSVC Windows builds of rustc generate these, which store debugging information
+*.pdb
+
+# End of https://www.toptal.com/developers/gitignore/api/rust
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..ec6841e
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "doi"
+version = "0.1.0"
+edition = "2021"
+rust-version = "1.65.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "4.2.5", features = ["derive"] }
+either = "1.8.1"
+itertools = "0.10.5"
+nom-bibtex = "0.4.0"
+nutype = { version = "0.2.0", features = ["regex"] }
+once_cell = "1.17.1"
+regex = "1.8.1"
+reqwest = { version = "0.11", features = ["blocking"] }
+url = "2.3.1"
diff --git a/README.md b/README.md
index 4ae355c..9d24388 100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,53 @@
[](https://zenodo.org/badge/latestdoi/67431697)
-# doi2bib and friends
-
-This repository provides scripts for converting from either [Digital Object Identifier (DOI)](https://www.doi.org) or [Uniform Resource Locator (URL)](https://en.wikipedia.org/wiki/URL) to [BibTeX](http://www.bibtex.org), or from DOI to plain text.
-
-## doi2bib
+TODO: support storing to the clipboard automatically.
+TODO: add the surname of the first author automatically if not given (if only the year is shown as id when retrieved)
-Convert [Digital Object Identifier (DOI)](https://www.doi.org) to
-[BibTeX](http://www.bibtex.org) using
-[crosscite.org](https://citation.crosscite.org/).
-DOIs are received and the corresponding BibTeX entries are output.
+# Bibliography in your command-line
-Inspired by and
-.
+This repository provides scripts for converting from either [Digital Object Identifier (DOI)](https://www.doi.org) or [Uniform Resource Locator (URL)](https://en.wikipedia.org/wiki/URL) to [BibTeX](http://www.bibtex.org), or from DOI to plain text.
+
+## `doi2bib`
-**October 16, 2017**: seems not to be working
-any more.
+Convert [Digital Object Identifier (DOI)](https://www.doi.org) to [BibTeX](http://www.bibtex.org) using [crosscite.org](https://citation.crosscite.org/).
+DOIs are received and the corresponding BibTeX entries are output.
+(Inspired by and .)
-## doi2text
+## `doi2text`
-Convert [Digital Object Identifier (DOI)](https://www.doi.org) to plain text
-using [crosscite.org](https://citation.crosscite.org/). DOIs are received and
-the corresponding text entries are output. In theory, all the styles
-available at can be used.
+Convert [Digital Object Identifier (DOI)](https://www.doi.org) to plain text using [crosscite.org](https://citation.crosscite.org/).
+DOIs are received and the corresponding text entries are output. In theory, all the styles available at can be used.
-## url2bib
+## `url2bib`
-Convert [Uniform Resource Locator (URL)](https://en.wikipedia.org/wiki/URL) to
-[BibTeX](http://www.bibtex.org) using pure
-[Bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell)).
+Convert [Uniform Resource Locator (URL)](https://en.wikipedia.org/wiki/URL) to [BibTeX](http://www.bibtex.org) using pure [Bash]().
URLs are received and the corresponding BibTeX entries are output.
+(This is made to be used exactly as one would use `doi2bib`.)
-(This is made to be used exactly as one would use doi2bib.)
+This requires `gawk` (`sudo apt install gawk`).
+
+## Dependencies
+
+`doi2bib` requires [curl](https://curl.haxx.se/):
+
+ $ sudo apt install curl
+
+You will also need `make` to install:
+
+ $ sudo apt install make
## Installation
After downloading the tarball and using `cd` to go where the files are, simply do a `sudo make install` and everything will be installed.
+By default, it will install in `/usr/local/bin/`.
## Usage
- $ doi2bib 10.1021/acs.jpcc.8b06244 10.1021/acscatal.9b00210
+ $ doi2bib 10.1021/acs.jpcc.8b06244 10.1021/acscatal.9b00210
@article{Schneider_2018,
title={How Do Secondary Phosphine Oxides Interact with Silver Nanoclusters? Insights from Computation},
volume={122},
@@ -74,7 +78,7 @@ After downloading the tarball and using `cd` to go where the files are, simply d
pages={3792–3799}
}
- $ url2bib google.com http://schneiderfelipe.xyz/ https://github.com/schneiderfelipe/doi2bib
+ $ url2bib google.com https://schneiderfelipe.github.io/ https://github.com/schneiderfelipe/doi
@misc{google,
title = {Google},
howpublished = {\url{google.com}},
@@ -83,12 +87,16 @@ After downloading the tarball and using `cd` to go where the files are, simply d
@misc{felipe-s-s-schneider,
title = {Felipe S. S. Schneider},
- howpublished = {\url{http://schneiderfelipe.xyz/}},
+ howpublished = {\url{https://schneiderfelipe.github.io/}},
note = {Accessed: 2020-01-27}
}
- @misc{github-schneiderfelipe-doi2bib-convert-dois-and-urls-to-bibtex,
- title = {GitHub - schneiderfelipe/doi2bib: Convert DOIs and URLs to BibTeX},
- howpublished = {\url{https://github.com/schneiderfelipe/doi2bib}},
+ @misc{github-schneiderfelipe-doi-convert-dois-and-urls-to-bibtex,
+ title = {GitHub - schneiderfelipe/doi: Convert DOIs and URLs to BibTeX},
+ howpublished = {\url{https://github.com/schneiderfelipe/doi}},
note = {Accessed: 2020-01-27}
}
+
+## Citing doi2bib
+
+If you use doi2bib in your research, please cite it.
diff --git a/cast.svg b/cast.svg
index eb16f27..c7a2c26 100644
--- a/cast.svg
+++ b/cast.svg
@@ -1 +1,15057 @@
-
\ No newline at end of file
+➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagos➜~➜~doi2bibhttps://doi.org/10.1021/acs.jpcc.8b06244@article{Schneider_2018,title={HowDoSecondaryPhosphineOxidesInteractwithSilverNanoclusters?InsightsfromComputation},volume={122},ISSN={1932-7455},url={http://dx.doi.org/10.1021/acs.jpcc.8b06244},DOI={10.1021/acs.jpcc.8b06244},number={37},journal={TheJournalofPhysicalChemistryC},publisher={AmericanChemicalSociety(ACS)},author={Schneider,FelipeS.S.andSegala,MaximilianoandCaramori,GiovanniF.anddaSilva,EderHenriqueandParreira,RenatoL.T.andSchrekker,HenriS.andvanLeeuwen,PietW.N.M.},year={2018},month={Aug},pages={21449–21461}}➜~doi2bib10.1021/acs.jpcc.8b06244➜~doi2text10.1021/acs.jpcc.8b06244Schneider,FelipeS.S.,MaximilianoSegala,GiovanniF.Caramori,EderHenriquedaSilva,RenatoL.T.Parreira,HenriS.Schrekker,ePietW.N.M.vanLeeuwen.2018.“HowDoSecondaryPhosphineOxidesInteractwithSilverNanoclusters?InsightsfromComputation”.TheJournalofPhysicalChemistryC122(37)(agosto27):21449–21461.doi:10.1021/acs.jpcc.8b06244.http://dx.doi.org/10.1021/acs.jpcc.8b06244.➜~doi2text-l10.1021/acs.jpcc.8b06244➜~doi2text-lde-DE10.1021/acs.jpcc.8b06244daSilva,RenatoL.T.Parreira,HenriS.Schrekker,undPietW.N.M.vanLeeuwen.2018.„HowDoSecondaryPhosphineOxidesInteractwithSilverNanoclusters?InsightsfromComputation“.TheJournalofPhysicalChemistryC122(37)(August27):21449–21461.doi:10.1021/acs.jpcc.8b06244.http://dx.doi.org/10.1021/acs.jpcc.8b06244.➜~doi2text-l10.1021/acs.jpcc.8b06244➜~doi2text-le10.1021/acs.jpcc.8b06244➜~doi2text-len10.1021/acs.jpcc.8b06244➜~doi2text-len-10.1021/acs.jpcc.8b06244➜~doi2text-len-G10.1021/acs.jpcc.8b06244➜~doi2text-len-GB10.1021/acs.jpcc.8b06244➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#a➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#al➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#all➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allc➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allch➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchi➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchic➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchica➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicag➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicago➜~doi2bib➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagost➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagosty➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostyl➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostyle➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostyleb➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostyleby➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebyd➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebyde➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebydef➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebydefa➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebydefau➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebydefaul➜~doi2text-len-GB10.1021/acs.jpcc.8b06244#allchicagostylebydefaultdaSilva,RenatoL.T.Parreira,HenriS.Schrekker,andPietW.N.M.vanLeeuwen.2018.‘HowDoSecondaryPhosphineOxidesInteractwithSilverNanoclusters?InsightsfromComputation’.TheJournalofPhysicalChemistryC122(37)(Augus➜~doi2text-s10.1021/acs.jpcc.8b06244➜~doi2text-sharvard310.1021/acs.jpcc.8b06244Schneider,F.S.S.etal.,2018.HowDoSecondaryPhosphineOxidesInteractwithSilverNanoclusters?InsightsfromComputation.TheJournalofPhysicalChemistryC,122(37),p.21449–21461.Availableat:http://dx.doi.org/10.1021/acs.jpcc.8b06244.➜~doi2text-samerican-chemical-society10.1021/acs.jpcc.8b06244(1)Schneider,F.S.S.;Segala,M.;Caramori,G.F.;daSilva,E.H.;Parreira,R.L.T.;Schrekker,H.S.;vanLeeuwen,P.W.N.M.TheJournalofPhysicalChemistryC2018,122,21449–21461.➜~doi2text-samerican-chemical-society10.1021/acs.jpcc.8b0624410.1103/PhysRev.140.A113310.1021/la203078wRev.140.A113310.1021/la203078w#Rev.140.A113310.1021/la203078w#asRev.140.A113310.1021/la203078w#asmanyRev.140.A113310.1021/la203078w#asmanyasRev.140.A113310.1021/la203078w#asmanyasyouRev.140.A113310.1021/la203078w#asmanyasyouwant(1)Kohn,W.;Sham,L.J.PhysicalReview1965,140,A1133–A1138.(1)Cabaleiro-Lago,C.;Szczepankiewicz,O.;Linse,S.Langmuir2012,28,1852–1857.➜~url2bib➜~url2bibhttps://github.com/schneiderfelipe/doi@misc{github-schneiderfelipe-doi-easily-convert-digital-object-identifier-doi-and-uniform-resource-locator-url-to-bibtex,title={GitHub-schneiderfelipe/doi:EasilyconvertDigitalObjectIdentifier(DOI)andUniformResourceLocator(URL)toBibTeX.},howpublished={\url{https://github.com/schneiderfelipe/doi}},note={Accessed:2020-09-22}➜~#➜~#have➜~#havefun➜~#havefun:)➜~➜~d➜~do➜~doi➜~doi2➜~doi2b➜~doi2bi➜~doi2bibhttps://doi.org/10.1021/acs.jpcc.8b06244➜~doi2bibhttps://doi.org10.1021/acs.jpcc.8b06244➜~doi2bibhttps://doi.or10.1021/acs.jpcc.8b06244➜~doi2bibhttps://doi.o10.1021/acs.jpcc.8b06244➜~doi2bibhttps://doi.10.1021/acs.jpcc.8b06244➜~doi2bibhttps://doi10.1021/acs.jpcc.8b06244➜~doi2bibhttps://do10.1021/acs.jpcc.8b06244➜~doi2bibhttps://d10.1021/acs.jpcc.8b06244➜~doi2bibhttps://10.1021/acs.jpcc.8b06244➜~doi2bibhttps:/10.1021/acs.jpcc.8b06244➜~doi2bibhttps:10.1021/acs.jpcc.8b06244➜~doi2bibhttps10.1021/acs.jpcc.8b06244➜~doi2bibhttp10.1021/acs.jpcc.8b06244➜~doi2bibhtt10.1021/acs.jpcc.8b06244➜~doi2bibht10.1021/acs.jpcc.8b06244➜~doi2bibh10.1021/acs.jpcc.8b06244➜~doi2bib10.1021/acs.jpcc.8b06244➜~doi2bi10.1021/acs.jpcc.8b06244➜~doi2b10.1021/acs.jpcc.8b06244➜~doi210.1021/acs.jpcc.8b06244➜~doi2t10.1021/acs.jpcc.8b06244➜~doi2te10.1021/acs.jpcc.8b06244➜~doi2tex10.1021/acs.jpcc.8b06244➜~doi2text10.1021/acs.jpcc.8b06244➜~doi2text-10.1021/acs.jpcc.8b06244➜~doi2text-l10.1021/acs.jpcc.8b06244➜~doi2text-ld10.1021/acs.jpcc.8b06244➜~doi2text-lde10.1021/acs.jpcc.8b06244➜~doi2text-lde-10.1021/acs.jpcc.8b06244➜~doi2text-lde-D10.1021/acs.jpcc.8b06244➜~doi2text-lde-DE10.1021/acs.jpcc.8b06244➜~doi2text-le-DE10.1021/acs.jpcc.8b06244➜~doi2text-l-DE10.1021/acs.jpcc.8b06244➜~doi2text-lDE10.1021/acs.jpcc.8b06244➜~doi2text-lE10.1021/acs.jpcc.8b06244➜~doi2text-10.1021/acs.jpcc.8b06244➜~doi2text-s10.1021/acs.jpcc.8b06244➜~doi2text-sh10.1021/acs.jpcc.8b06244➜~doi2text-sha10.1021/acs.jpcc.8b06244➜~doi2text-shar10.1021/acs.jpcc.8b06244➜~doi2text-sharv10.1021/acs.jpcc.8b06244➜~doi2text-sharva10.1021/acs.jpcc.8b06244➜~doi2text-sharvar10.1021/acs.jpcc.8b06244➜~doi2text-sharvard10.1021/acs.jpcc.8b06244➜~doi2text-sarvard310.1021/acs.jpcc.8b06244➜~doi2text-srvard310.1021/acs.jpcc.8b06244➜~doi2text-svard310.1021/acs.jpcc.8b06244➜~doi2text-sard310.1021/acs.jpcc.8b06244➜~doi2text-srd310.1021/acs.jpcc.8b06244➜~doi2text-sd310.1021/acs.jpcc.8b06244➜~doi2text-s310.1021/acs.jpcc.8b06244➜~doi2text-sa10.1021/acs.jpcc.8b06244➜~doi2text-sam10.1021/acs.jpcc.8b06244➜~doi2text-same10.1021/acs.jpcc.8b06244➜~doi2text-samer10.1021/acs.jpcc.8b06244➜~doi2text-sameri10.1021/acs.jpcc.8b06244➜~doi2text-sameric10.1021/acs.jpcc.8b06244➜~doi2text-samerica10.1021/acs.jpcc.8b06244➜~doi2text-samerican10.1021/acs.jpcc.8b06244➜~doi2text-samerican-10.1021/acs.jpcc.8b06244➜~doi2text-samerican-c10.1021/acs.jpcc.8b06244➜~doi2text-samerican-ch10.1021/acs.jpcc.8b06244➜~doi2text-samerican-che10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chem10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemi10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemic10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemica10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-s10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-so10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-soc10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-soci10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-socie10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-societ10.1021/acs.jpcc.8b06244➜~doi2text-samerican-chemical-society10.1021/acs.jpcc.8b0624410.1103/PhysRev.140.A1133Rev.140.A1133Rev.140.A113310.1021/la203078wRev.140.A113310.1021/la203078w#aRev.140.A113310.1021/la203078w#asmRev.140.A113310.1021/la203078w#asmaRev.140.A113310.1021/la203078w#asmanRev.140.A113310.1021/la203078w#asmanyaRev.140.A113310.1021/la203078w#asmanyasyRev.140.A113310.1021/la203078w#asmanyasyoRev.140.A113310.1021/la203078w#asmanyasyouwRev.140.A113310.1021/la203078w#asmanyasyouwaRev.140.A113310.1021/la203078w#asmanyasyouwan➜~u➜~ur➜~url➜~url2➜~url2b➜~url2bi➜~url2bibhttps://github.com/schneiderfelipe/doi➜~#h➜~#ha➜~#hav➜~#havef➜~#havefu➜~#havefun:
diff --git a/src/bibmagic.py b/src/bibmagic.py
new file mode 100644
index 0000000..7935507
--- /dev/null
+++ b/src/bibmagic.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import sys
+import bibtexparser as btp
+from bibtexparser.bparser import BibTexParser
+from bibtexparser.customization import homogenize_latex_encoding
+
+with open(sys.argv[1]) as bib_file:
+ parser = BibTexParser()
+ # parser.customization = homogenize_latex_encoding
+ bib_db = btp.load(bib_file, parser=parser)
+
+if len(sys.argv) > 2:
+ with open(sys.argv[2], 'w') as bib_file:
+ btp.dump(bib_db, bib_file)
+else:
+ print(btp.dumps(bib_db))
diff --git a/src/bin/doi2bib.rs b/src/bin/doi2bib.rs
new file mode 100644
index 0000000..45e57a3
--- /dev/null
+++ b/src/bin/doi2bib.rs
@@ -0,0 +1,63 @@
+use std::process;
+use std::str::FromStr;
+
+use clap::Parser;
+use doi::Doi;
+use either::Either;
+use itertools::Itertools;
+use itertools::Position;
+use nom_bibtex::Bibliography;
+use nom_bibtex::Bibtex;
+use reqwest::blocking::Client;
+use reqwest::blocking::Response;
+use reqwest::header;
+use reqwest::Url;
+
+/// Retrieve BibTeX data for a given DOI.
+#[derive(Clone, Debug, Parser)]
+#[command(author, version, about, arg_required_else_help(true))]
+struct Cli {
+ /// DOI to retrieve BibTeX data for.
+ #[arg(value_parser(Doi::from_str))]
+ doi: Vec,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ for doi in cli.doi {
+ match Client::new()
+ .get(Url::from(&doi))
+ .header(header::ACCEPT, "text/bibliography; style=bibtex")
+ .send()
+ .and_then(Response::text)
+ .map_err(Either::Left)
+ .and_then(|text| Bibtex::parse(&text).map_err(Either::Right))
+ {
+ Ok(bibtex) => {
+ bibtex.bibliographies().iter().for_each(|biblio| {
+ print(biblio);
+ });
+ }
+ Err(e) => {
+ eprintln!("Error retrieving DOI {doi}: {e}");
+ process::exit(1);
+ }
+ }
+ }
+}
+
+fn print(biblio: &Bibliography) {
+ println!("@{}{{{},", biblio.entry_type(), biblio.citation_key());
+ biblio.tags().iter().with_position().for_each(|item| {
+ match item {
+ Position::First((key, value)) | Position::Middle((key, value)) => {
+ println!(" {key:9} = {{{value}}},");
+ }
+ Position::Last((key, value)) | Position::Only((key, value)) => {
+ println!(" {key:9} = {{{value}}}");
+ }
+ }
+ });
+ println!("}}\n");
+}
diff --git a/src/bin/doi2text.rs b/src/bin/doi2text.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/src/bin/doi2text.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/bin/url2bib.rs b/src/bin/url2bib.rs
new file mode 100644
index 0000000..ca6320d
--- /dev/null
+++ b/src/bin/url2bib.rs
@@ -0,0 +1,62 @@
+use std::process;
+use std::str::FromStr;
+
+use clap::Parser;
+use itertools::Itertools;
+use itertools::Position;
+use nom_bibtex::Bibliography;
+use reqwest::blocking::Client;
+use reqwest::blocking::Response;
+use reqwest::Url;
+
+/// Retrieve BibTeX data for a given URL.
+#[derive(Clone, Debug, Parser)]
+#[command(author, version, about, arg_required_else_help(true))]
+struct Cli {
+ /// URL to retrieve BibTeX data for.
+ #[arg(value_parser(Url::from_str))]
+ url: Vec,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ for url in cli.url {
+ match Client::new()
+ .get(url.as_str())
+ .send()
+ .and_then(Response::text)
+ {
+ Ok(html) => {
+ let title: String = todo!("Hello world!");
+ let slug: String = todo!("hello-world");
+ let today: String = todo!("%Y-%m-%d");
+ let biblio = Bibliography::new("misc".into(), slug, vec![
+ ("title".into(), title),
+ ("howpublished".into(), format!(r"\url{{{}}}", url)),
+ ("note".into(), format!("Accessed: {}", today)),
+ ]);
+ print(&biblio);
+ }
+ Err(e) => {
+ eprintln!("Error retrieving URL {url}: {e}");
+ process::exit(1);
+ }
+ }
+ }
+}
+
+fn print(biblio: &Bibliography) {
+ println!("@{}{{{},", biblio.entry_type(), biblio.citation_key());
+ biblio.tags().iter().with_position().for_each(|item| {
+ match item {
+ Position::First((key, value)) | Position::Middle((key, value)) => {
+ println!(" {key:9} = {{{value}}},");
+ }
+ Position::Last((key, value)) | Position::Only((key, value)) => {
+ println!(" {key:9} = {{{value}}}");
+ }
+ }
+ });
+ println!("}}\n");
+}
diff --git a/src/doi2bib b/src/doi2bib
index 5e04bf2..ab5ee4d 100755
--- a/src/doi2bib
+++ b/src/doi2bib
@@ -39,16 +39,16 @@
#?
#? License:
#?
-#? doi2bib
+#? doi2bib
#? is licensed under the MIT License.
while getopts ":hv" opt "$@"; do
case $opt in
- h) # help
+ h) # help
grep "^#?" "$0" | cut -c 4-
exit 0
;;
- v) # version
+ v) # version
grep "^#? doi2bib" "$0" | cut -c 4-
exit 0
;;
@@ -64,7 +64,7 @@ while getopts ":hv" opt "$@"; do
done
# recover $@
-shift $((OPTIND-1))
+shift $((OPTIND - 1))
# we consider everything after the command a list of DOIs.
for doi in "$@"; do
@@ -72,10 +72,13 @@ for doi in "$@"; do
doi=${doi//+/%2B}
http_headers="Accept: text/bibliography; style=bibtex"
+ echo "$http_headers"
+ echo
+
# we retrieve the data from https://doi.org/
- curl -s -LH "$http_headers" "https://doi.org/${doi}" | \
- sed -e $'s/^ *//' \
- -e $'s/}, /},\\\n /g' \
- -e $'s/, /,\\\n /1' \
- -e $'s/}}$/}\\\n}\\\n/'
+ curl -LH "$http_headers" "https://doi.org/${doi}" \
+ | sed -e $'s/^ *//' \
+ -e $'s/}, /},\\\n /g' \
+ -e $'s/, /,\\\n /1' \
+ -e $'s/}}$/}\\\n}\\\n/'
done
diff --git a/src/doi2text b/src/doi2text
index a7624ab..019762d 100755
--- a/src/doi2text
+++ b/src/doi2text
@@ -34,7 +34,7 @@
#? -v show version
#? -s set ciation style from the ones given in
#? (this is
-#? "chicago-author-date" by default, see examples below)
+#? "american-chemical-society" by default, see examples below)
#? -S list all available citation styles and quit
#? -l set locale from the ones given in
#? , e.g. "pt-BR"
@@ -52,41 +52,42 @@
#?
#? License:
#?
-#? doi2text and doi2bib
+#? doi2text and doi2bib
#? are licensed under the MIT License.
+style="american-chemical-society"
+
locale=$(locale | grep LANGUAGE | cut -d= -f2 | cut -d: -f1 | tr '_' '-')
-style="chicago-author-date"
if [ ! $locale ]; then
locale="en-US"
fi
while getopts ":hvs:Sl:L" opt "$@"; do
case $opt in
- h) # help
+ h) # help
grep "^#?" "$0" | cut -c 4-
exit 0
;;
- v) # version
+ v) # version
grep "^#? doi2text" "$0" | cut -c 4-
exit 0
;;
- s) # style
+ s) # style
style="${OPTARG}"
;;
- S) # list all styles
- curl -s -X GET \
- https://api.github.com/repos/citation-style-language/styles/contents/\?ref\=master | \
- sed -e '/"name":.*\.csl"/{s/\s*"name": "//;s/\.csl",\s*//;p};d'
+ S) # list all styles
+ curl -X GET \
+ https://api.github.com/repos/citation-style-language/styles/contents/\?ref\=master \
+ | sed -e '/"name":.*\.csl"/{s/\s*"name": "//;s/\.csl",\s*//;p};d'
exit 0
;;
- l) # locale
+ l) # locale
locale="${OPTARG}"
;;
- L) # list all styles
- curl -s -X GET \
- https://api.github.com/repos/citation-style-language/locales/contents/\?ref\=master | \
- sed -e '/"name":.*\.xml"/{s/\s*"name": "//;s/\.xml",\s*//;s/locales-//;p};d'
+ L) # list all styles
+ curl -X GET \
+ https://api.github.com/repos/citation-style-language/locales/contents/\?ref\=master \
+ | sed -e '/"name":.*\.xml"/{s/\s*"name": "//;s/\.xml",\s*//;s/locales-//;p};d'
exit 0
;;
\?)
@@ -101,7 +102,7 @@ while getopts ":hvs:Sl:L" opt "$@"; do
done
# recover $@
-shift $((OPTIND-1))
+shift $((OPTIND - 1))
# we consider everything after the command a list of DOIs.
for doi in "$@"; do
@@ -109,6 +110,9 @@ for doi in "$@"; do
doi=${doi//+/%2B}
http_headers="Accept: text/x-bibliography; style=${style}; locale=${locale}"
+ echo "$http_headers"
+ echo
+
# we retrieve the data from https://doi.org/
- curl -s -LH "$http_headers" "https://doi.org/${doi}"
+ curl -LH "$http_headers" "https://doi.org/${doi}"
done
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..e04dc58
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,73 @@
+//! A strongly-typed library for working
+//! with
+//! [Digital object identifiers](https://en.wikipedia.org/wiki/Digital_object_identifier)
+//! (DOIs).
+
+use nutype::nutype;
+use once_cell::sync::Lazy;
+use regex::Regex;
+use regex::RegexBuilder;
+
+/// Regex for
+/// [Digital object identifier](https://en.wikipedia.org/wiki/Digital_object_identifier)
+/// (DOI)
+/// validation.
+///
+/// It is taken from
+/// ,
+/// which has been
+/// [recommended by CrossRef](https://www.crossref.org/blog/dois-and-matching-regular-expressions/).
+static REGEX: Lazy = Lazy::new(|| {
+ RegexBuilder::new(r"^10.\d{4,9}/[-._;()/:A-Z0-9]+$")
+ .case_insensitive(true)
+ .build()
+ .expect("should be valid")
+});
+
+/// A
+/// [Digital object identifier](https://en.wikipedia.org/wiki/Digital_object_identifier)
+/// (DOI).
+#[nutype(
+ sanitize(trim, lowercase, with = sanitize_doi)
+ validate(not_empty, regex = REGEX)
+)]
+#[derive(*)]
+#[derive(Display)]
+pub struct Doi(String);
+
+use url::Url;
+
+/// Prefix
+/// [URL](https://en.wikipedia.org/wiki/URL)
+/// for retrieving information about
+/// [Digital object identifiers](https://en.wikipedia.org/wiki/Digital_object_identifier)
+/// (DOIs).
+static URL: Lazy = Lazy::new(|| Url::parse("https://doi.org/").expect("should be parseable"));
+
+/// Sanitize a
+/// [Digital object identifier](https://en.wikipedia.org/wiki/Digital_object_identifier)
+/// (DOI).
+#[inline]
+#[allow(clippy::needless_pass_by_value)]
+fn sanitize_doi(doi: String) -> String {
+ [URL.as_str(), "doi:"]
+ .into_iter()
+ .fold(doi.as_str(), |doi, prefix| {
+ doi.strip_prefix(prefix).unwrap_or(doi)
+ })
+ .into()
+}
+
+impl From for Url {
+ #[inline]
+ fn from(doi: Doi) -> Self {
+ Self::from(&doi)
+ }
+}
+
+impl From<&Doi> for Url {
+ #[inline]
+ fn from(doi: &Doi) -> Self {
+ URL.join(doi.as_ref()).expect("should be joinable")
+ }
+}
diff --git a/src/url2bib b/src/url2bib
index 820e5a6..440db8f 100755
--- a/src/url2bib
+++ b/src/url2bib
@@ -33,22 +33,22 @@
#?
#? Examples:
#?
-#? $ url2bib https://github.com/schneiderfelipe/doi2bib # write to stdout
-#? $ url2bib https://github.com/schneiderfelipe/doi2bib >> citations.bib # append to file
-#? $ url2bib https://github.com/schneiderfelipe/doi2bib https://en.wikipedia.org/wiki/Brazilin # get many URLs
+#? $ url2bib https://github.com/schneiderfelipe/doi # write to stdout
+#? $ url2bib https://github.com/schneiderfelipe/doi >> citations.bib # append to file
+#? $ url2bib https://github.com/schneiderfelipe/doi https://en.wikipedia.org/wiki/Brazilin # get many URLs
#?
#? License:
#?
-#? url2bib and doi2bib
+#? url2bib and doi2bib
#? are licensed under the MIT License.
while getopts ":hv" opt "$@"; do
case $opt in
- h) # help
+ h) # help
grep "^#?" "$0" | cut -c 4-
exit 0
;;
- v) # version
+ v) # version
grep "^#? url2bib" "$0" | cut -c 4-
exit 0
;;
@@ -64,7 +64,7 @@ while getopts ":hv" opt "$@"; do
done
# recover $@
-shift $((OPTIND-1))
+shift $((OPTIND - 1))
# we consider everything after the command a list of URLs.
for url in "$@"; do
@@ -72,14 +72,14 @@ for url in "$@"; do
url=${url//+/%2B}
# https://unix.stackexchange.com/a/103253/211802
- title=$(wget -qO- "${url}" | \
- gawk -v IGNORECASE=1 -v RS=']*>/,"");print;exit}')
+ title=$(wget -qO- "${url}" \
+ | gawk -v IGNORECASE=1 -v RS=']*>/,"");print;exit}')
# https://gist.github.com/oneohthree/f528c7ae1e701ad990e6
- slug=$(echo "${title}" | iconv -t ascii//TRANSLIT | \
- sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | tr "[:upper:]" "[:lower:]")
+ slug=$(echo "${title}" | iconv -t ascii//TRANSLIT \
+ | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | tr "[:upper:]" "[:lower:]")
- cat <