Initial commit
This commit is contained in:
437
bin/BBlog
Executable file
437
bin/BBlog
Executable file
@ -0,0 +1,437 @@
|
||||
#!/bin/bash
|
||||
|
||||
## Copyright Ian Jauslin 2015-2017
|
||||
##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License");
|
||||
## you may not use this file except in compliance with the License.
|
||||
## You may obtain a copy of the License at
|
||||
##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0
|
||||
##
|
||||
## Unless required by applicable law or agreed to in writing, software
|
||||
## distributed under the License is distributed on an "AS IS" BASIS,
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
## See the License for the specific language governing permissions and
|
||||
## limitations under the License.
|
||||
|
||||
# directory containing the engine files
|
||||
enginedir=/usr/share/BBlog/engines
|
||||
enginedir=/home/ian/Programs/BBlog2/engines
|
||||
|
||||
# version
|
||||
version=2.1
|
||||
|
||||
function print_config {
|
||||
echo "engine: $engine"
|
||||
echo "db: $db"
|
||||
echo "conf: $conf"
|
||||
echo "aux: $aux"
|
||||
echo "format: $format"
|
||||
echo "outbib: $outbib"
|
||||
echo "order: $order"
|
||||
echo "aux_cmd: $aux_cmd"
|
||||
echo "ref_map: $ref_map"
|
||||
}
|
||||
|
||||
# defaults
|
||||
function set_defaults {
|
||||
engine="sqlite"
|
||||
db=""
|
||||
conf=""
|
||||
aux='*.aux'
|
||||
format='\bibitem[%citeref%]{%token%}%n%%author% - {\it %title%}, %journal%, %year%.%n%'
|
||||
outbib=''
|
||||
order="alphabetical"
|
||||
aux_cmd='\\citation{'
|
||||
ref_map=''
|
||||
}
|
||||
|
||||
# read cli args
|
||||
function read_cli {
|
||||
|
||||
flag=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
"-e" )
|
||||
flag="engine" ;;
|
||||
"-d" )
|
||||
flag="db" ;;
|
||||
"-c" )
|
||||
flag="conf" ;;
|
||||
"-a" )
|
||||
flag="aux" ;;
|
||||
"-f" )
|
||||
flag="format" ;;
|
||||
"-b" )
|
||||
flag="outbib" ;;
|
||||
"-o" )
|
||||
flag="order" ;;
|
||||
"-A" )
|
||||
flag="aux_cmd" ;;
|
||||
"-F" )
|
||||
flag="filter" ;;
|
||||
"-r" )
|
||||
flag="ref_map" ;;
|
||||
# version
|
||||
"-v" )
|
||||
echo "$version"; exit ;;
|
||||
* )
|
||||
if [ -n "$flag" ]; then
|
||||
# treat filters differently
|
||||
if [ "$flag" != 'filter' ]; then
|
||||
eval "$flag='$arg'"
|
||||
# flag the variable as set
|
||||
eval "set_$flag=1"
|
||||
else
|
||||
field="${arg%%:*}"
|
||||
value="${arg#*:}"
|
||||
eval "filter_$field='$value'"
|
||||
eval "set_filter_$field=1"
|
||||
fi
|
||||
flag=""
|
||||
fi
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# read config file
|
||||
function read_config {
|
||||
extra_entries_index=0
|
||||
|
||||
if [ -n "$conf" ]; then
|
||||
[ -f "$conf" ] || { echo "error: $conf: no such file" 1>&2 ; exit -1 ; }
|
||||
while read -r confline; do
|
||||
flag=""
|
||||
field="${confline%%:*}"
|
||||
value="${confline#*:}"
|
||||
# remove spaces
|
||||
field=$(echo "$field" | sed -r 's/ *$//')
|
||||
value=$(echo "$value" | sed -r 's/^ *//')
|
||||
case "$field" in
|
||||
"engine" )
|
||||
flag="engine" ;;
|
||||
"database" )
|
||||
flag="db" ;;
|
||||
"aux" )
|
||||
flag="aux" ;;
|
||||
"format" )
|
||||
flag="format" ;;
|
||||
"out_file" )
|
||||
flag="outbib" ;;
|
||||
"order" )
|
||||
flag="order" ;;
|
||||
"aux_cmd" )
|
||||
flag="aux_cmd" ;;
|
||||
"ref_map" )
|
||||
flag="ref_map" ;;
|
||||
"filter" )
|
||||
# set flag to the specific filter
|
||||
flag="filter_${value%%:*}"
|
||||
# reset value
|
||||
value="${value#*:}" ;;
|
||||
"extra" )
|
||||
extra[$extra_entries_index]="$value"
|
||||
extra_entries_index=$((extra_entries_index+1)) ;;
|
||||
esac
|
||||
|
||||
if [ -n "$flag" ]; then
|
||||
# check it was not set on the command line
|
||||
eval "[ -n \"\$set_$flag\" -a \"\$set_$flag\" = 1 ] || $flag='$value'"
|
||||
fi
|
||||
done <"$conf"
|
||||
|
||||
# sort extra entries
|
||||
if [ "$extra_entries_index" -gt 0 -a "$order" = "alphabetical" ]; then
|
||||
IFS=$'\n' extra=($(echo "${extra[*]}" | sort -k 1,1 -t :))
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# check the configuration
|
||||
function check_config {
|
||||
# check whether the engine exists
|
||||
[ -e "$enginedir/$engine.sh" ] || { echo "error: engine $engine not found in $enginedir" 1>&2; exit -1 ; }
|
||||
|
||||
# check the database and aux file
|
||||
for file in "$db" "$aux"; do
|
||||
[[ "$file" =~ '*' || -e "$file" ]] || { echo "error: $file: no such file" 1>&2 ; exit -1 ; }
|
||||
done
|
||||
|
||||
# check the $order variable
|
||||
[ "$order" != "alphabetical" -a "$order" != "appearance" ] && { echo "error: order should be one of 'alphabetical' or 'appearance' (read $order)" 1>&2 ; exit -1 ; }
|
||||
|
||||
# check for ref_map
|
||||
[ -n "$ref_map" ] && [ ! -e "$ref_map" ] && { echo "error: $ref_map: no such file" 1>&2 ; exit -1 ; }
|
||||
}
|
||||
|
||||
function replace_format {
|
||||
out="$1"
|
||||
|
||||
# replace newlines
|
||||
out="${out//\%n\%/\\n}"
|
||||
|
||||
# if the ref of the entry has been mapped, fetch the old citeref
|
||||
if [ -n "$ref_map" ]; then
|
||||
citeref=$(inverse_map_citeref "$citeref")
|
||||
fi
|
||||
|
||||
# first search for conditionals
|
||||
# while '|' is still in $out
|
||||
while : ; do
|
||||
# find next '|'
|
||||
tmp=${out#*|}
|
||||
# save text before '|'
|
||||
pre=${out%%|*}
|
||||
# check whether it was found
|
||||
[ "$tmp" = "$out" ] && break
|
||||
# find next '|'
|
||||
command=${tmp%%|*}
|
||||
# save text after '|'
|
||||
post=${tmp#*|}
|
||||
# check whether it was found
|
||||
[ "$command" = "$tmp" ] && { echo "error: '|'s do not match in '$1'" 1>&2 ; exit -1 ; }
|
||||
|
||||
# extract field
|
||||
field="${command%%\?*}"
|
||||
repl="${command##*\?}"
|
||||
|
||||
# check whether field is empty
|
||||
val=$(eval "echo \$$field")
|
||||
if [ -n "$val" ]; then
|
||||
out="$pre$repl$post"
|
||||
else
|
||||
out="$pre$post"
|
||||
fi
|
||||
done
|
||||
|
||||
# replace '%'
|
||||
# while '%' is still in $out
|
||||
while : ; do
|
||||
# find next '%'
|
||||
tmp=${out#*%}
|
||||
# check whether it was found
|
||||
[ "$tmp" = "$out" ] && break
|
||||
# find next '%'
|
||||
command=${tmp%%%*}
|
||||
# check whether it was found
|
||||
[ "$command" = "$tmp" ] && { echo "error: '%'s do not match in '$1'" 1>&2 ; exit -1 ; }
|
||||
|
||||
# the field entry may be followed by a filter
|
||||
field="${command%:*}"
|
||||
# filter
|
||||
filter="${command##*:}"
|
||||
|
||||
# apply filter
|
||||
if [ -n "$filter" ]; then
|
||||
sed_cmd=$(eval "echo \$filter_$filter")
|
||||
replacement=$(eval "echo \$$field" | sed -r "$sed_cmd" )
|
||||
else
|
||||
replacement=$(eval "echo \$$field")
|
||||
fi
|
||||
|
||||
out="${out//\%$command\%/$replacement}"
|
||||
done
|
||||
|
||||
# finish replacing newlines
|
||||
out="${out//\\n/%}"
|
||||
out=$(echo "$out" | tr "%" "\n")
|
||||
echo "$out"
|
||||
}
|
||||
|
||||
function escape_string {
|
||||
str="$1"
|
||||
str="${str//\\/\\\\}"
|
||||
str="${str//\`/\\\`}"
|
||||
str="${str//\"/\\\"}"
|
||||
str="${str//\$/\\\$}"
|
||||
echo "$str"
|
||||
}
|
||||
|
||||
# replace a citeref according to a ref_map
|
||||
function map_citeref {
|
||||
# check whether a ref_map was specified
|
||||
[ -z "$ref_map" ] && { echo "$1" ; return 0 ; }
|
||||
|
||||
oldref="$1"
|
||||
newref=$(echo "$oldref" | sed -r -f "$ref_map")
|
||||
echo "$newref"
|
||||
}
|
||||
|
||||
# find the pre-image of a citeref through the ref_map
|
||||
function inverse_map_citeref {
|
||||
# check whether a ref_map was specified
|
||||
[ -z "$ref_map" ] && { echo "$1" ; return 0 ; }
|
||||
|
||||
newref="$1"
|
||||
|
||||
foundref=0
|
||||
# sift through aux file
|
||||
grep -h "$aux_cmd" $aux | while read -r ref; do
|
||||
eval "ref=\${ref#$aux_cmd}"
|
||||
ref="${ref%\}}"
|
||||
# replace the ref via the ref_map
|
||||
possibleref=$(map_citeref "$ref")
|
||||
# check whether the ref is the right one
|
||||
if [ "$possibleref" = "$newref" ]; then
|
||||
echo "$ref"
|
||||
foundref=1
|
||||
return 1
|
||||
fi
|
||||
done && echo "$foundref$newref"
|
||||
}
|
||||
|
||||
# format entries
|
||||
function format_BBlog_entries {
|
||||
# keep track of tokens to avoid repetitions
|
||||
token_list=""
|
||||
|
||||
has_there_been_a_nonempty_line_so_far=0
|
||||
|
||||
while read -r line; do
|
||||
# if line has 0 size, then new entry
|
||||
if [ -z "$line" ]; then
|
||||
# skip if it is the first line
|
||||
if [ $has_there_been_a_nonempty_line_so_far = 1 ]; then
|
||||
# check whether an extra entry precedes it
|
||||
# alphabetical order
|
||||
if [ "$order" = "alphabetical" ]; then
|
||||
old_token="$token"
|
||||
old_citeref="$citeref"
|
||||
while [[ ${#extra} -gt 0 && "${extra[0]%%:*}" < "$prauth$year" ]]; do
|
||||
reftokval="${extra[0]#*:}"
|
||||
citeref="${reftokval%%:*}"
|
||||
tokval="${reftokval#*:}"
|
||||
token="${tokval%%:*}"
|
||||
value="${tokval#*:}"
|
||||
# check whether token is unique
|
||||
token=$(replace_repeated_token "$token" "$token_list")
|
||||
# add token to list
|
||||
token_list="$token_list;$token"
|
||||
|
||||
replace_format "$value"
|
||||
|
||||
IFS=$'\n' extra=($(echo "${extra[*]:1}"))
|
||||
done
|
||||
token="$old_token"
|
||||
citeref="$old_citeref"
|
||||
|
||||
# check whether token is unique
|
||||
token=$(replace_repeated_token "$token" "$token_list")
|
||||
# add token to list
|
||||
token_list="$token_list;$token"
|
||||
|
||||
replace_format "$format"
|
||||
|
||||
# appearance order
|
||||
else
|
||||
foundit=0
|
||||
if [ ${#extra} -gt 0 ]; then
|
||||
for entry in "${extra[@]}"; do
|
||||
ref="${entry#*:}"
|
||||
ref="${ref%%:*}"
|
||||
if [ "$ref" = "$citeref" ]; then
|
||||
old_token="$token"
|
||||
old_citeref="$citeref"
|
||||
|
||||
citeref="$ref"
|
||||
token="${entry#*:*:}"
|
||||
value="${token#*:}"
|
||||
token="${token%%:*}"
|
||||
# check whether token is unique
|
||||
token=$(replace_repeated_token "$token" "$token_list")
|
||||
# add token to list
|
||||
token_list="$token_list;$token"
|
||||
|
||||
replace_format "$value"
|
||||
|
||||
token="$old_token"
|
||||
citeref="$old_citeref"
|
||||
foundit=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ $foundit = 0 ]; then
|
||||
# check whether token is unique
|
||||
token=$(replace_repeated_token "$token" "$token_list")
|
||||
# add token to list
|
||||
token_list="$token_list;$token"
|
||||
|
||||
replace_format "$format"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
has_there_been_a_nonempty_line_so_far=0
|
||||
else
|
||||
eval "$line"
|
||||
has_there_been_a_nonempty_line_so_far=1
|
||||
fi
|
||||
done
|
||||
|
||||
# add remaining extra entries (only for alphabetical order)
|
||||
if [ "$order" = "alphabetical" ]; then
|
||||
while [ ${#extra} -gt 0 ]; do
|
||||
reftokval="${extra[0]#*:}"
|
||||
citeref="${reftokval%%:*}"
|
||||
tokval="${reftokval#*:}"
|
||||
token="${tokval%%:*}"
|
||||
value="${tokval#*:}"
|
||||
# check whether token is unique
|
||||
token=$(replace_repeated_token "$token" "$token_list")
|
||||
# add token to list
|
||||
token_list="$token_list;$token"
|
||||
|
||||
replace_format "$value"
|
||||
IFS=$'\n' extra=($(echo "${extra[*]:1}"))
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# replace a token that already exists
|
||||
function replace_repeated_token {
|
||||
token="$1"
|
||||
list="$2"
|
||||
|
||||
out="$token"
|
||||
i=0
|
||||
while $(echo "$token_list;" | grep -q ";$out;"); do
|
||||
i=$((i+1))
|
||||
out="$token"$(alpha_number $i)
|
||||
done
|
||||
|
||||
echo "$out"
|
||||
}
|
||||
|
||||
# convert an integer to base 26
|
||||
function alpha_number {
|
||||
num="$1"
|
||||
rem="$num"
|
||||
out=""
|
||||
letters=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
|
||||
while [ "$rem" -gt 0 ]; do
|
||||
digit=$((rem-26*(rem/26)))
|
||||
out="${letters[$digit]}$out"
|
||||
rem=$(((rem-digit)/26))
|
||||
done
|
||||
|
||||
echo "$out"
|
||||
}
|
||||
|
||||
|
||||
set_defaults
|
||||
read_cli "$@"
|
||||
read_config
|
||||
check_config
|
||||
source "$enginedir/$engine.sh"
|
||||
|
||||
# check whether to order by alphabetical order or appearance
|
||||
[ "$order" = "alphabetical" ] && fetch_cmd=fetch_BBlog_entries_alpha || fetch_cmd=fetch_BBlog_entries_appearance
|
||||
|
||||
# fetch entries
|
||||
if [ -n "$outbib" ]; then
|
||||
"$fetch_cmd" | format_BBlog_entries > "$outbib"
|
||||
else
|
||||
"$fetch_cmd" | format_BBlog_entries
|
||||
fi
|
||||
|
Reference in New Issue
Block a user