├── README.md ├── dmenubib ├── dmenubib-menu ├── dmenubib-open ├── dmenubib-pdfmeta ├── dmenubib-refer └── dmenubib-search /README.md: -------------------------------------------------------------------------------- 1 | # Dmenubib 2 | 3 | A simple bibliography manager using dmenu 4 | 5 | - Minimal (*only require **POSIX compliant shell** and coreutils*) 6 | - Automatically **rename** and **update metadata** for your pdf files. 7 | 8 | ## Dependency 9 | 10 | - `dmenu`, `exiftool`, `pdftotext` 11 | - `grep`, `awk`, `sed`, `eval`, `tail`, `curl` 12 | - `printf`, `echo`, `xclip / xsel` 13 | 14 | ## Installation 15 | 16 | Move all the files to `$PATH`. 17 | 18 | ## Usage 19 | 20 | Need to set two environment variables: 21 | 22 | - `$BIB` for `.bib` file 23 | - `$BIB_PDF_PATH` for directory to store pdf files. 24 | 25 | ### `SER` to Search BibTeX on Internet: 26 | 27 | Two ways to search: `Text` or `PDF`. 28 | 29 | `Text`: 30 | 31 | - Type doi and directly generate bibtex 32 | - Type text related to paper to search on [Crossref](https://search.crossref.org/), and copy doi to generate bibtex. 33 | - If you cannot find doi in crossref, copy any text other than doi, and then `dmenubib` will search on [Google scholar](https://scholar.google.com/). Copy bibtex to store it in `$BIB`. 34 | 35 | `PDF`: 36 | 37 | - Choose pdf file in `$BIB_PDF_PATH`. 38 | - If the metadata contain doi, then generate bibtex. 39 | - If the metadata contain title or can extract some text, then search on [Crossref](https://search.crossref.org/), and copy doi to generate bibtex. 40 | - If you cannot find doi in crossref, copy any text other than doi, and then `dmenubib` will search on [Google scholar](https://scholar.google.com/). Copy bibtex to store it in `$BIB`. 41 | 42 | ### `REF` to Get BibTeX label for reference 43 | 44 | Choose the criterion to search in `$BIB`. Copy the label of chosen bibtex to clipboard. 45 | 46 | ### `OPN` to open corresponding pdf file 47 | 48 | Choose the criterion to search in `$BIB`. Open the corresponding pdf in `$BIB_PDF_PATH`. 49 | 50 | ### `PDF` to Manually Rename and encode metadata into pdf 51 | 52 | Choose pdf files, and choose which bibtex entry to generate metadata. 53 | 54 | PDF will be renamed as bibtex label, and attached with Title, Author, and doi metadata. 55 | 56 | ### `AUO` to Automatically rename and encode metadata into pdf 57 | 58 | Automatically go through all pdf files in `$BIB_PDF_PATH`, check whether correctly named. `Dmenubib` will generate a list of unmatched pdf files, and allow manual rename and encode metadata using `PDF` function. 59 | 60 | **Caveat: `AUO` update pdf based on pdf filename. So if you update your bibtex and want to update metadata, use `PDF` instead.** 61 | 62 | ## `NTE` to write notes for each reference 63 | 64 | Store the notes for each paper as markdown file in `$BIB_PDF_PATH/Notes`. 65 | 66 | Each `.md` file is named after the bibtex label in `$BIB`. 67 | 68 | -------------------------------------------------------------------------------- /dmenubib: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BIB="$BIB" 4 | BIB_PDF_PATH="$BIB_PDF_PATH" 5 | BIB_NOTE_PATH="$BIB_PDF_PATH/Notes" 6 | BIB_GENERIC_FONT=Monospace-15 7 | BIB_NOTIF_FONT=Monospace-25 8 | BIB_GENERIC_COLOR=#005577 9 | BIB_SER="SER - Search BibTeX on Internet" 10 | BIB_REF="REF - Get BibTeX label for reference" 11 | BIB_OPN="OPN - Open corresponding pdf file based on BibTeX" 12 | BIB_PDF="PDF - Manually Rename and encode metadata into pdf" 13 | BIB_AUO="AUO - Automatically rename and encode metadata into pdf" 14 | BIB_NTE="NTE - Write markdown notes on references" 15 | BIBACTLIST="$(printf '%s\n' "$BIB_SER" "$BIB_REF" "$BIB_OPN" "$BIB_PDF" "$BIB_AUO" "$BIB_NTE")" 16 | nl=' 17 | ' 18 | act="placeholder" 19 | doi_regex='(https://doi.org/)?10\.[0-9]{4}[0-9.]*/[^[:space:]]*' 20 | 21 | [ ! -d "$BIB_NOTE_PATH" ] && mkdir "$BIB_NOTE_PATH" 22 | 23 | . dmenubib-menu 24 | . dmenubib-search 25 | . dmenubib-refer 26 | . dmenubib-pdfmeta 27 | . dmenubib-open 28 | 29 | CheckDeps () { 30 | depcount=0 31 | for CurDep in "$@"; do 32 | if ! command -v "$CurDep" 1> /dev/null 2>&1; then 33 | printf '%s\n' "ERROR: Dependency $CurDep not met." 1>&2 34 | depcount=$((depcount+1)) 35 | fi 36 | done 37 | unset CurDep 38 | } 39 | 40 | CheckDeps grep awk dmenu exiftool sed eval pdftotext printf tail curl echo 41 | 42 | [ "$depcount" -gt 0 ] && exit 1 43 | 44 | BIB_Action () { 45 | while [ -n "$act" ]; do 46 | act="$(printf '%s\n' "$BIBACTLIST" | yprompt "Actions: " "$BIB_GENERIC_COLOR")" 47 | case "$act" in 48 | "$BIB_SER") BIB_SER ;; 49 | "$BIB_REF") BIB_REF ;; 50 | "$BIB_OPN") BIB_OPN ;; 51 | "$BIB_PDF") BIB_PDF ;; 52 | "$BIB_AUO") BIB_AUO ;; 53 | "$BIB_NTE") BIB_NTE ;; 54 | esac 55 | done 56 | } 57 | 58 | BIB_SER () { 59 | CheckBIB 60 | criteria="$(printf '%s\n' "Text" "PDF" | yprompt "Searching criteria: " "$BIB_GENERIC_COLOR")" 61 | case "$criteria" in 62 | "Text") input="$(xprompt "Type text to search: " "$BIB_GENERIC_COLOR")" && [ -n "$input" ] && CheckArg "$input" ;; 63 | "PDF") MainMenu && [ -n "$CHOICE" ] && CheckArg "$CHOICE" ;; 64 | esac 65 | ScanBIB 66 | unset doi info 67 | } 68 | 69 | BIB_REF () { 70 | CheckBIB 71 | SearchBIB 72 | RefBIB 73 | } 74 | 75 | BIB_OPN () { 76 | CheckBIB 77 | open="$(printf '%s\n' "PDF" "$BIB_PDF_PATH" "$BIB" | yprompt "Open: " "$BIB_GENERIC_COLOR")" 78 | case "$open" in 79 | "PDF") SearchBIB && OpenBIB ;; 80 | "$BIB_PDF_PATH") [ -n "$TERMINAL" ] && cd "$BIB_PDF_PATH" && $TERMINAL || ${BIB_OPENER:-xdg-open} "$BIB_PDF_PATH" ;; 81 | "$BIB") [ -n "$TERMINAL" ] && $TERMINAL -e "${EDITOR:-vi}" "$BIB" || ${BIB_OPENER:-xdg-open} "$BIB" ;; 82 | esac 83 | } 84 | 85 | BIB_NTE () { 86 | CheckBIB 87 | SearchBIB 88 | NoteBIB 89 | } 90 | 91 | BIB_PDF () { 92 | CheckBIB 93 | MainMenu 94 | [ -n "$CHOICE" ] && 95 | SearchBIB && 96 | [ -n "$cite" ] && 97 | MetaGen && 98 | MetaPDFBind "$CHOICE" 99 | } 100 | 101 | BIB_AUO () { 102 | CheckBIB 103 | MetaAutoGen 104 | MetaFixGen 105 | } 106 | 107 | BIB_Action 108 | -------------------------------------------------------------------------------- /dmenubib-menu: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## PROMPT FUNCTIONS 4 | yprompt () { # Usage yprompt [MSG] [BG_COLOR] 5 | dmenu -f -fn "$BIB_GENERIC_FONT" -i -sb "$2" -l 10 -p "$1" 6 | } 7 | 8 | xprompt () { # Usage xprompt [MSG] [BG_COLOR] 9 | dmenu -f -fn "$BIB_GENERIC_FONT" -i -sb "$2" -p "$1" <&- 10 | } 11 | 12 | NotiPrompt () { # Usage NotiPrompt [MSG] 13 | dmenu -f -fn "$BIB_NOTIF_FONT" -sb "#d79921" -sf "#1d2021" -nf "#000000" -nb "#000000" -p "$1" <&- 14 | } 15 | 16 | AskPrompt () { # Usage: AskPrompt [MSG] && ... 17 | [ "$(printf "No\\nYes" | dmenu -f -fn "$BIB_NOTIF_FONT" -i -p "$1" -sb "#d79921" -sf "#1d2021" -nf gray -nb "#000000")" = "Yes" ] 18 | } 19 | 20 | 21 | ## MENUFUNCTIONS 22 | 23 | MenuFile () { # Generate file 24 | IFS="$nl" 25 | FILEs=$( 26 | for file in "$BIB_PDF_PATH"/*; do 27 | [ -f "$file" ] && printf '%s\n' "$file" 28 | done 29 | ) 30 | unset IFS 31 | } 32 | 33 | MenuDotFile () { # Generate dorfile 34 | IFS="$nl" 35 | DOTFILEs=$( 36 | for file in "$BIB_PDF_PATH"/.*; do 37 | [ -f "$file" ] && printf '%s\n' "$file" 38 | done 39 | ) 40 | unset IFS 41 | } 42 | 43 | Menu () { # Generate default menu 44 | MenuFile 45 | MenuDotFile 46 | } 47 | 48 | MainMenu () { # Usage: MainMenu 49 | Menu && list=$(printf '%s\n' "$FILEs" "$DOTFILEs") 50 | CHOICE=$(printf '%s\n' "$list" | sed "/^$/ d" | yprompt "Select PDF files: " "$BIB_GENERIC_COLOR") 51 | } 52 | -------------------------------------------------------------------------------- /dmenubib-open: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PDFOpen () { 4 | [ -n "$ref" ] && ${BIB_OPENER:-xdg-open} "$BIB_PDF_PATH/$ref.pdf" || NotiPrompt "$cite.pdf does not exist" 5 | } 6 | 7 | OpenBIB () { 8 | # Usage: OpenBIB 9 | # Input: $criterion 10 | # Output: Open pdf files 11 | case "$criterion" in 12 | "title") 13 | bibtexgen "/$cite/" 14 | PDFOpen 15 | ;; 16 | "authoryear") 17 | cite_author="${cite%% --- *}" 18 | cite_year="${cite##* --- }" 19 | bibtexgen "/$cite_author/ && /$cite_year/" 20 | PDFOpen 21 | ;; 22 | "mixed") 23 | cite_title="${cite##* --- }" 24 | bibtexgen "/$cite_title/" 25 | PDFOpen 26 | ;; 27 | esac 28 | } 29 | 30 | # NoteOpen () { 31 | # note="$BIB_NOTE_PATH/$ref.md" 32 | # [ ! -f "$note" ] && 33 | # title="$(printf '%s' "$bibtex" | grep -i "title.*" | sed "s/^.*title \?= \?{\?//g; s/}\?,\?$//g")" && 34 | # author="$(printf '%s' "$bibtex" | grep -i "author.*" | sed "s/^.*author \?= \?{\?//g; s/}\?,\?$//g")" && 35 | # printf '%s\n\n' "# $title" "Author: $author" > "$note" 36 | # mimetype=$(xdg-mime query filetype "$note") 37 | # appdesktop=$(xdg-mime query default "$mimetype") 38 | # grep -q "Terminal=false" < "$(find "$XDGDIR1" "$XDGDIR2" -name "$appdesktop" | tail -n 1)" && 39 | # ${BIB_OPENER:-xdg-open} "$note" || 40 | # $TERMINAL -e "${BIB_OPENER:-xdg-open}" "$note" 41 | # } 42 | 43 | NoteOpen () { 44 | note="$BIB_NOTE_PATH/$ref/$ref.tex" 45 | [ ! -f "$note" ] && 46 | title="$(printf '%s' "$bibtex" | grep -i "title.*" | sed "s/^.*title \?= \?{\?//g; s/}\?,\?$//g")" && 47 | author="$(printf '%s' "$bibtex" | grep -i "author.*" | sed "s/^.*author \?= \?{\?//g; s/}\?,\?$//g")" && 48 | mkdir -p "$BIB_NOTE_PATH/$ref/" && 49 | printf '%s\n' \ 50 | '\documentclass[a4paper]{article}' \ 51 | '\usepackage[utf8]{inputenc}' \ 52 | '\usepackage[T1]{fontenc}' \ 53 | '\usepackage{textcomp}' \ 54 | '\usepackage{amsmath, amssymb, amsthm}' \ 55 | '\usepackage{import}' \ 56 | '\usepackage{pdfpages}' \ 57 | '\usepackage{transparent}' \ 58 | '\usepackage{xcolor}' \ 59 | '\newcommand{\inkfig}[2][1]{%' \ 60 | ' \def\svgwidth{#1\columnwidth}' \ 61 | ' \import{./figures/}{#2.pdf_tex}' \ 62 | '}' \ 63 | '\pdfsuppresswarningpagegroup=1' \ 64 | "\\title{Hui-Jun Chen's Note on \"$title\"}" \ 65 | "\\author{Author(s): $author}" \ 66 | '\date{\today}' \ 67 | '\begin{document}' \ 68 | '\maketitle' \ 69 | '' \ 70 | '' \ 71 | '' \ 72 | '\end{document}' > "$note" 73 | mimetype=$(file --mime-type -b "$note" 2>/dev/null) 74 | case "$mimetype" in 75 | text/*|*x-empty*|*json*) 76 | case "$TERMINAL" in 77 | "") ${BIB_OPENER:-xdg-open} "$note" ;; 78 | *) $TERMINAL -e "${EDITOR:-vi}" "$note" ;; 79 | esac 80 | ;; 81 | *) ${BIB_OPENER:-xdg-open} "$note" ;; 82 | esac 83 | } 84 | 85 | NoteBIB () { 86 | # Usage: NoteBIB 87 | # Input: $criterion 88 | # Output: Open Note file 89 | case "$criterion" in 90 | "title") 91 | bibtexgen "/$cite/" 92 | [ -n "$ref" ] && NoteOpen 93 | ;; 94 | "authoryear") 95 | cite_author="${cite%% --- *}" 96 | cite_year="${cite##* --- }" 97 | bibtexgen "/$cite_author/ && /$cite_year/" 98 | [ -n "$ref" ] && NoteOpen 99 | ;; 100 | "mixed") 101 | cite_title="${cite##* --- }" 102 | bibtexgen "/$cite_title/" 103 | [ -n "$ref" ] && NoteOpen 104 | ;; 105 | esac 106 | } 107 | -------------------------------------------------------------------------------- /dmenubib-pdfmeta: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | bibtexgen () { 4 | # Usage: bibtexgen [PATTERN] 5 | # Input: $bibfile 6 | # Output: $bibtex && $ref 7 | file="$(cat -u "$bibfile" | sed 's/\\//g')" 8 | bibtex="$(printf '%s' "$file" | awk -v RS='@' "$1")" 9 | ref="$(printf '%s' "$bibtex" | head -n 1 | sed "s/.*{//g; s/,$//g")" 10 | } 11 | 12 | bib2list () { 13 | # Usage: bib2list 14 | # Input: $bibtex 15 | # Output: $reflist -> [VARs] 16 | reflist="$(printf '%s' "$bibtex" | 17 | sed " 18 | 1 d 19 | $ d 20 | s/^[ \t@]*//g 21 | s/}\?,\?$/\"/g 22 | s/ \?= \?{\?/=\"/g 23 | ")" 24 | eval "$reflist" 25 | } 26 | 27 | MetaGen () { 28 | # Usage: MetaGen 29 | # Input: criterion 30 | # Output: $reflist 31 | case "$criterion" in 32 | "title") 33 | bibtexgen "/$cite/" 34 | bib2list 35 | ;; 36 | "authoryear") 37 | cite_author="${cite%% --- *}" 38 | cite_year="${cite##* --- }" 39 | bibtexgen "/$cite_author/ && /$cite_year/" 40 | bib2list 41 | ;; 42 | "mixed") 43 | cite_title="${cite##* --- }" 44 | bibtexgen "/$cite_title/" 45 | bib2list 46 | ;; 47 | esac 48 | } 49 | 50 | MetaAutoGen () { 51 | # Usage: MetaAutoGen 52 | # Input: pdfs in "$BIB_PDF_PATH" 53 | # Output: pdf metadata && $faillist 54 | Menu && list="$(printf '%s\n' "$FILEs" "$DOTFILEs")" 55 | IFS="$nl" 56 | for pdf in $list; do 57 | unset IFS 58 | TMP="${pdf##*/}"; basename="${TMP%.*}" 59 | if [ "$(head -n 1 "$pdf" | cut -c 1-4)" = "%PDF" ] && 60 | [ -z "$(grep "@" "$bibfile" | grep "$basename")" ]; then 61 | title="$(exiftool "$pdf" | grep -i "Title")"; title="${title##*: }" 62 | if [ -n "$title" ] && bibtexgen "/$title/" && [ -n "$ref" ]; then 63 | bib2list 64 | MetaPDFBind "$pdf" 65 | else 66 | faillist="$(printf '%s\n' "$faillist" "$pdf")" 67 | fi 68 | else 69 | continue 70 | fi 71 | done 72 | } 73 | 74 | MetaFixGen () { 75 | # Usage: MetaFixGen 76 | # Input: $faillist 77 | # Output: pdf metadata 78 | IFS="$nl" 79 | while [ -n "$faillist" ]; do 80 | CHOICE=$(printf '%s\n' "$faillist" | sed "/^$/ d" | yprompt "Select PDF files: " "$BIB_GENERIC_COLOR") 81 | if [ -n "$CHOICE" ]; then 82 | SearchBIB 83 | MetaGen 84 | if [ -n "$ref" ]; then 85 | MetaPDFBind "$CHOICE" 86 | faillist="$(printf '%s\n' "${faillist#*"$CHOICE"}" "${faillist%%"$CHOICE"*}")" 87 | else 88 | break 89 | fi 90 | else 91 | break 92 | fi 93 | done 94 | unset IFS 95 | NotiPrompt "Metadata for references updated." 96 | } 97 | 98 | MetaPDFBind () { 99 | # Usage: MetaPDFBind 100 | # Input: $ref, $title, $author, $doi 101 | # Output: metadata -> pdf 102 | IFS="$nl" 103 | if exiftool -Title="$title" -Author="$author" -doi="$doi" -filename="$ref.pdf" "$1" -overwrite_original; then 104 | unset IFS 105 | NotiPrompt "$ref Added" 106 | unset ref title author doi 107 | fi 108 | } 109 | -------------------------------------------------------------------------------- /dmenubib-refer: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | colbind () { 4 | # Usage: colbind "[VAR1]" "[VAR2]" 5 | # Input: "$1" "$2" 6 | # Output: "$1" --- "$2" 7 | awk -v awk_lpart="$1" -v awk_rpart="$2" 'BEGIN{ 8 | split(awk_lpart,lp,/#/) 9 | split(awk_rpart,rp,/#/) 10 | for (i=1; i in lp; i++) { 11 | print lp[i],"--- " rp[i] 12 | } 13 | }' 14 | } 15 | 16 | clipcopy () { 17 | # Usage: clipcopy [CONTENT] 18 | # Input: "$1" 19 | # Output: Copy to clipboard 20 | [ -n "$1" ] && command -v xclip && printf '%s' "$1" | xclip -selection clipboard 21 | [ -n "$1" ] && command -v xsel && printf '%s' "$1" | xsel --clipboard 22 | } 23 | 24 | SearchBIB () { 25 | # Usage: SearchBIB 26 | # Input: Dmenu choice 27 | # Output: $cite 28 | criterion="$(printf '%s\n' "title" "authoryear" "mixed" | yprompt "Choose selection criterion: " "$BIB_GENERIC_COLOR")" 29 | title="$(cat -u "$BIB" | grep -i "title.*" | sed "s/^.*title \?= \?{\?//g; s/}\?,\?$//g" | tr '\n' '#')" 30 | title="${title%#}" 31 | author="$(cat -u "$BIB" | grep -i "author.*" | sed "s/^.*author \?= \?{\?//g; s/}\?,\?$//g" | tr '\n' '#')" 32 | author="${author%#}" 33 | year="$(cat -u "$BIB" | grep -i "year.*" | sed "s/^.*year \?= \?{\?//g; s/}\?,\?$//g" | tr '\n' '#')" 34 | year="${year%#}" 35 | case "$criterion" in 36 | "title") 37 | cite="$(printf '%s' "$title" | tr '#' '\n' | yprompt "Selct reference title: " "$BIB_GENERIC_COLOR")" 38 | ;; 39 | "authoryear") 40 | cite="$(colbind "$author" "$year" | yprompt "Select author and year: " "$BIB_GENERIC_COLOR")" 41 | ;; 42 | "mixed") 43 | cite="$( 44 | TMP="$(colbind "$author" "$year" | tr '\n' '#')" 45 | colbind "$TMP" "$title" | yprompt "Select author, year and title: " "$BIB_GENERIC_COLOR" 46 | unset TMP 47 | )" 48 | ;; 49 | esac 50 | } 51 | 52 | RefBIB () { 53 | # Usage: RefBIB 54 | # Input: $criterion 55 | # Output: $ref to clipboard 56 | case "$criterion" in 57 | "title") 58 | bibtexgen "/$cite/" 59 | [ -n "$ref" ] && clipcopy "$ref" && NotiPrompt "$ref copied to clipboard" 60 | ;; 61 | "authoryear") 62 | cite_author="${cite%% --- *}" 63 | cite_year="${cite##* --- }" 64 | bibtexgen "/$cite_author/ && /$cite_year/" 65 | [ -n "$ref" ] && clipcopy "$ref" && NotiPrompt "$ref copied to clipboard" 66 | ;; 67 | "mixed") 68 | cite_title="${cite##* --- }" 69 | bibtexgen "/$cite_title/" 70 | [ -n "$ref" ] && clipcopy "$ref" && NotiPrompt "$ref copied to clipboard" 71 | ;; 72 | esac 73 | } 74 | 75 | CheckBIB () { 76 | # Usage: CheckBIB 77 | # Input: $BIB 78 | # Output: $bibfile 79 | [ -n "$BIB" ] && bibfile="$BIB" || NotiPrompt "Need to set environment variable '$BIB'" 80 | } 81 | -------------------------------------------------------------------------------- /dmenubib-search: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CheckArg () { 4 | # Usage: CheckArg "[Arg]" 5 | # Input: $1 6 | # Output: $doi / $info 7 | doi_regex='(https://doi.org/)?10\.[0-9]{4}[0-9.]*/[^[:space:]]*' 8 | if echo "$1" | grep -E -q "$doi_regex"; then 9 | doi="$1" 10 | pdf="false" 11 | elif [ "$(dd if="$1" count=4 bs=1)" = "%PDF" ]; then 12 | pdf="$1" 13 | doi="$(exiftool "$1" | grep -E "$doi_regex")" && doi="${doi##* : }" 14 | [ -z "$doi" ] && { info="$(exiftool "$1" | grep "^Title")"; info="${info##* : }"; } 15 | [ -z "$info" ] && info="$(pdftotext "$1" 2>/dev/null - | head -n 1)" 16 | [ -z "$info" ] && NotiPrompt "Cannot identify doi, title or any content from pdf file." && exit 1 17 | else 18 | info="$1" 19 | pdf="false" 20 | fi 21 | } 22 | 23 | OpenDoi () { 24 | # Usage: OpenDoi 25 | # Input: $doi 26 | # Output: open browser 27 | [ "$pdf" = "false" ] && [ -n "$doi" ] && AskPrompt "Download corresponding pdf files?" && xdg-open "https://doi.org/$doi" 28 | } 29 | 30 | ScanBIB () { 31 | # Usage: ScanBIB 32 | # Input: $doi / $info 33 | # Output: $bibtex >> $bibfile 34 | if [ -n "$doi" ]; then 35 | if grep "doi \?= \?{*" "$bibfile" | grep "$doi"; then 36 | NotiPrompt "Reference already added." 37 | else 38 | BibGen 39 | fi 40 | elif [ -n "$info" ]; then 41 | if grep "title \?= \?{*" "$bibfile" | grep "$info"; then 42 | NotiPrompt "Reference already added." 43 | else 44 | DoiMenu 45 | if [ -n "$doi" ]; then 46 | BibGen 47 | OpenDoi 48 | else 49 | BibYak 50 | fi 51 | fi 52 | fi 53 | } 54 | 55 | waitclip () { 56 | # Usage: waitclip "[CMD]" 57 | # Input: "[CMD]" 58 | # Output: $clip 59 | count=1 60 | countlimit=3600 61 | while [ -z "$clip" ] && [ $count -le $countlimit ]; do 62 | clip="$(printf '%s' "$1" | ${SHELL:-"/bin/sh"})" 63 | sleep 1 64 | count=$((count+1)) 65 | done 66 | } 67 | 68 | clipdoi () { 69 | # Usage: clipdoi 70 | # Input: $clip 71 | # OUtput: $doi 72 | echo "$clip" | grep -E -q "$doi_regex" && { doi="$clip"; doi="${doi##*doi.org/}"; } || doi="" 73 | } 74 | 75 | DoiMenu () { 76 | # Usage: DoiMenu 77 | # Input: $info 78 | # Output: search content on dmenu 79 | url="$(printf '%s' "$info" | tr ' ' '+')" 80 | html="$(curl -s "https://search.crossref.org/?q=$url")" 81 | TMP="${html##*
/@/g; 87 | s/<[^>]*>//g 88 | /^$/ d 89 | " | 90 | awk 'BEGIN { 91 | RS="@"; 92 | } 93 | { 94 | n=split($0, sp, /\n/) 95 | title = sp[2] 96 | category = sp[3] 97 | for (i=1; i in sp; i++) { 98 | if (match(sp[i], /^[0-9][0-9][0-9][0-9]$/)) 99 | year = sp[i] 100 | else if (match(sp[i], /Authors:.*/)) 101 | author = sp[i] 102 | else if (match(sp[i-1], /^in$/)) 103 | journal = sp[i] 104 | else if (match(sp[i], /(https:\/\/)?10\.[0-9][0-9][0-9][0-9][0-9.]*\/[^[:space:]]*/)) 105 | doi = sp[i] 106 | } 107 | if (length(journal) == 0) 108 | print title, "- " category, "- " year, "- " author, "- " doi 109 | else 110 | print title, "- " category, "- " journal, "- " year, "- " author, "- " doi 111 | }' | 112 | sed "1 d; /^$/ d; s/^ //g; s/ $//g" | yprompt "Choose correct citation" "$BIB_GENERIC_COLOR" 113 | )" 114 | [ -n "$research" ] && doi="$(printf '%s' "${research##*doi.org/}")" 115 | } 116 | 117 | DoiGen () { 118 | # Usage: DoiGen 119 | # Input: $info 120 | # Output: $doi 121 | doi_regex='(https://doi.org/)?10\.[0-9]{4}[0-9.]*/[^[:space:]]*' 122 | if [ -n "$info" ] && command -v xclip; then 123 | printf '%s' "" | xclip -selection clipboard # Clear clipboard 124 | NotiPrompt "Copy DOI. If paper not found, copy anything that is not DOI to trigger next stage." 125 | ${BIB_OPENER:-xdg-open} "https://search.crossref.org/?q=$info" & 126 | waitclip "xclip -o -selection clipboard" 127 | clipdoi 128 | elif [ -n "$info" ] && command -v xsel; then 129 | xsel -bc # Clear clipboard 130 | ${BIB_OPENER:-xdg-open} "https://search.crossref.org/?q=$info" & 131 | waitclip "xsel -o --clipboard" 132 | clipdoi 133 | elif [ -n "$info" ]; then 134 | NotiPrompt "Need to install xclip or xsel as dependency" && exit 1 135 | else 136 | exit 0 137 | fi 138 | } 139 | 140 | 141 | bibnl () { 142 | # Add \n at end of file 143 | [ "$(tail -c 1 "$bibfile")" != "$nl" ] && printf '%s\n' "" >> "$bibfile" 144 | } 145 | 146 | BibGen () { 147 | # Usage: BibGen 148 | # Input: $doi 149 | # Output: $bibtex >> $bibfile 150 | [ -n "$doi" ] && 151 | bibtex="$(curl -s "http://api.crossref.org/works/$doi/transform/application/x-bibtex")" && 152 | ! grep "$info" "$bibfile" && 153 | printf '%s\n' "$bibtex" >> "$bibfile" && 154 | NotiPrompt "Reference added to $bibfile" && 155 | bibnl || 156 | NotiPrompt "Reference already added" 157 | } 158 | 159 | clipbib () { 160 | # Usage: clipbib 161 | # Input: $info 162 | # Output: $bibtex >> $bibfile 163 | bibtex="$clip" 164 | bibtex_regex='^@[a-z]*{.*,' 165 | title="$(printf '%s' "$bibtex" | grep "title")"; title="${title##*\{}"; title="${title%%\}*}" 166 | if echo "$bibtex" | grep -E -q "$bibtex_regex"; then 167 | if ! grep "$title" "$bibfile"; then 168 | printf '%s\n' "$bibtex" >> "$bibfile" && NotiPrompt "Reference added to $bibfile" && bibnl 169 | else 170 | NotiPrompt "Reference already added" 171 | fi 172 | else 173 | NotiPrompt "Not copying bibtex" 174 | fi 175 | } 176 | 177 | BibYak () { 178 | # Usage: BibYak 179 | # Input: $clip 180 | # Output: $bibtex >> $bibfile 181 | clip="" 182 | NotiPrompt "Copy BibTeX. If paper not found, copy anything that is not BibTeX to stop." 183 | if [ -n "$info" ] && command -v xclip; then 184 | printf '%s' "" | xclip -selection clipboard # Clear clipboard 185 | ${BIB_OPENER:-xdg-open} "https://scholar.google.com/scholar?&q=$info" & 186 | waitclip "xclip -o -selection clipboard" 187 | clipbib 188 | elif [ -n "$info" ] && command -v xsel; then 189 | xsel -bc # Clear clipboard 190 | ${BIB_OPENER:-xdg-open} "https://scholar.google.com/scholar?&q=$info" & 191 | waitclip "xsel -o --clipboard" 192 | bibtex="$clip" 193 | clipbib 194 | fi 195 | } 196 | --------------------------------------------------------------------------------