2018-07-09 16:20:40 +02:00
|
|
|
#!/usr/bin/env bash
|
2023-11-26 19:49:56 +02:00
|
|
|
# Nerd Fonts Version: 3.1.1
|
2024-03-27 09:30:25 +02:00
|
|
|
# Script Version: 2.2.3
|
2022-11-30 00:37:27 +02:00
|
|
|
#
|
|
|
|
# Iterates over all [*] archived fonts
|
2024-03-27 09:30:25 +02:00
|
|
|
# to generate ruby cask files for homebrew-fonts (https://github.com/Homebrew/homebrew-cask-fonts)
|
2022-11-27 13:25:10 +02:00
|
|
|
# * Only adds non-Windows versions of the fonts
|
|
|
|
# * Needs the zip archives in archives/ (i.e. run `./archive-fonts.sh` first)
|
|
|
|
#
|
2022-11-30 00:37:27 +02:00
|
|
|
# Uses the current release version (including drafts) of the repo.
|
|
|
|
# You can specify a different version with the --setversion parameter.
|
|
|
|
# A leading 'v' from the version is removed.
|
|
|
|
# Must be the first parameter.
|
|
|
|
#
|
2022-11-27 13:25:10 +02:00
|
|
|
# [1] Accepts one parameter, a pattern which fonts to examine, if not given defaults
|
2022-11-30 00:37:27 +02:00
|
|
|
# to "*" which is all fonts.
|
|
|
|
#
|
|
|
|
# Example runs
|
|
|
|
# generate-casks.sh Hasklig
|
|
|
|
# generate-casks.sh --setversion 2.2.0
|
|
|
|
# generate-casks.sh Hasklig
|
|
|
|
# generate-casks.sh --setversion 2.2.0 Hasklig
|
2016-11-06 05:09:12 +02:00
|
|
|
|
2022-11-30 00:37:27 +02:00
|
|
|
# set -x
|
2022-11-25 15:12:47 +02:00
|
|
|
set -e
|
2016-11-06 05:09:12 +02:00
|
|
|
|
2023-11-26 19:49:56 +02:00
|
|
|
version="3.1.1"
|
2016-11-06 05:09:12 +02:00
|
|
|
homepage="https://github.com/ryanoasis/nerd-fonts"
|
2016-11-13 19:22:10 +02:00
|
|
|
downloadarchive="https://github.com/ryanoasis/nerd-fonts/releases/download/v#{version}/"
|
2017-05-14 00:02:53 +02:00
|
|
|
LINE_PREFIX="# [Nerd Fonts] "
|
2022-11-30 00:37:27 +02:00
|
|
|
scripts_root_dir="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
archivedir=$(realpath "${scripts_root_dir}/../../archives")
|
|
|
|
|
|
|
|
if [ $# -ge 1 ]; then
|
|
|
|
if [ "$1" = "--setversion" ]; then
|
|
|
|
if [ $# -lt 2 ]; then
|
|
|
|
echo >&2 "$LINE_PREFIX Missing argument for --setversion"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
version=$2
|
|
|
|
shift; shift
|
|
|
|
if [ "${version:0:1}" = "v" ]; then
|
|
|
|
version="${version:1}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2016-11-06 05:09:12 +02:00
|
|
|
|
2023-06-01 10:49:26 +02:00
|
|
|
cd "${archivedir}" || {
|
2022-11-30 00:37:27 +02:00
|
|
|
echo >&2 "$LINE_PREFIX Could not find archives directory"
|
2022-11-25 13:52:23 +02:00
|
|
|
exit 1
|
2016-11-06 05:09:12 +02:00
|
|
|
}
|
|
|
|
|
2016-12-03 05:56:52 +02:00
|
|
|
function clear_file {
|
2022-11-25 13:52:23 +02:00
|
|
|
local outputfile=$1
|
|
|
|
# clear output file (needed for multiple runs or updates):
|
|
|
|
true > "$outputfile" 2> /dev/null
|
2016-12-03 05:56:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function write_header {
|
2022-11-25 13:52:23 +02:00
|
|
|
local outputfile=$1
|
|
|
|
local caskname=$2
|
|
|
|
|
|
|
|
{
|
|
|
|
printf "cask \"%s\" do\\n" "$caskname"
|
|
|
|
printf " version \"%s\"\\n" "$version"
|
|
|
|
printf " sha256 \"%s\"\\n\\n" "$sha256sum"
|
|
|
|
printf " url \"%s%s.zip\"\\n" "$downloadarchive" "$basename"
|
|
|
|
} >> "$outputfile"
|
2016-12-03 05:56:52 +02:00
|
|
|
}
|
2016-11-06 05:09:12 +02:00
|
|
|
|
2022-11-27 13:07:29 +02:00
|
|
|
# Query all Family names of a font individually and return the first
|
|
|
|
# we found that has "Nerd" in it. We need this because some fonts have
|
|
|
|
# broken Family names.
|
|
|
|
function find_nerdish_family {
|
|
|
|
local fontfile=$1
|
|
|
|
local idx=0
|
|
|
|
while :; do
|
|
|
|
local fn=$(fc-query --format="%{family[${idx}]}" "${fontfile}")
|
|
|
|
if [ -z "$fn" ]; then
|
|
|
|
return
|
|
|
|
fi
|
2023-11-21 17:25:41 +02:00
|
|
|
if [[ "${fn}" == *Nerd* ]] || [[ "${fn}" == *NF* ]]; then
|
2022-11-27 13:07:29 +02:00
|
|
|
echo "${fn}"
|
|
|
|
return
|
|
|
|
fi
|
2023-06-01 10:49:26 +02:00
|
|
|
idx=$((idx + 1))
|
2022-11-27 13:07:29 +02:00
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2022-11-29 12:50:19 +02:00
|
|
|
# Return the longest common starting part of two strings
|
|
|
|
# This is the stem, the basic base name of the fonts
|
|
|
|
function find_common_stem {
|
|
|
|
local first=$1
|
|
|
|
local second=$2
|
|
|
|
for i in $(seq ${#first} -1 1); do
|
|
|
|
if [ "${first:0:$i}" == "${second:0:$i}" ]; then
|
|
|
|
echo "${first:0:$i}"
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2022-12-14 18:47:37 +02:00
|
|
|
# Check if an element already exists in an array
|
|
|
|
function contains {
|
|
|
|
local what=$1
|
|
|
|
shift
|
|
|
|
for e; do
|
|
|
|
if [ "${e}" = "${what}" ]; then
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2016-12-03 05:56:52 +02:00
|
|
|
function write_body {
|
2022-11-25 17:47:12 +02:00
|
|
|
local unpatchedname=$1
|
|
|
|
local outputfile=$2
|
|
|
|
shift; shift;
|
2022-11-25 13:52:23 +02:00
|
|
|
local fonts=("$@")
|
|
|
|
|
|
|
|
if [ "${fonts[0]}" ]; then
|
2022-12-14 17:30:02 +02:00
|
|
|
local longest=-1
|
2022-11-25 16:02:21 +02:00
|
|
|
# Find longest filename for pretty printing
|
|
|
|
for i in "${!fonts[@]}"; do
|
2022-12-14 17:30:02 +02:00
|
|
|
local basename=$(basename "${fonts[$i]}")
|
2023-06-01 10:49:26 +02:00
|
|
|
if [ ${#basename} -gt "$longest" ]; then
|
2022-11-25 16:02:21 +02:00
|
|
|
longest=${#basename}
|
|
|
|
fi
|
|
|
|
done
|
2022-11-27 13:07:29 +02:00
|
|
|
# Find familyname of non Mono variant (well, rather shortest because we can contain multiple families)
|
2022-12-14 17:30:02 +02:00
|
|
|
local familyname=$(find_nerdish_family "${fonts[0]}")
|
2022-11-27 11:22:09 +02:00
|
|
|
for i in "${!fonts[@]}"; do
|
2022-12-14 17:30:02 +02:00
|
|
|
local fn=$(find_nerdish_family "${fonts[$i]}")
|
2022-11-29 23:52:43 +02:00
|
|
|
familyname=$(find_common_stem "${fn}" "${familyname}")
|
2022-11-27 11:22:09 +02:00
|
|
|
done
|
2022-11-27 13:07:29 +02:00
|
|
|
if [ -z "${familyname}" ]; then
|
|
|
|
echo >&2 "${LINE_PREFIX} Can not determine family name"
|
|
|
|
exit 2
|
|
|
|
fi
|
2022-11-29 23:52:43 +02:00
|
|
|
# Family names differ in front of "Nerd Font" (stem is short)
|
2022-11-29 12:50:19 +02:00
|
|
|
if [[ "${familyname}" != *Nerd* ]]; then
|
|
|
|
familyname="${familyname} Nerd Font families"
|
|
|
|
fi
|
2023-06-01 10:49:26 +02:00
|
|
|
familyname="$(tr "[:lower:]" "[:upper:]" <<< "${familyname:0:1}")${familyname:1}"
|
2022-11-25 16:02:21 +02:00
|
|
|
# Process font files
|
2022-12-14 18:47:37 +02:00
|
|
|
local all_individual_fonts=( )
|
|
|
|
local warned=0
|
2022-11-25 13:52:23 +02:00
|
|
|
for i in "${!fonts[@]}"; do
|
2022-12-14 17:30:02 +02:00
|
|
|
local individualfont=$(basename "${fonts[$i]}")
|
|
|
|
local individualdir=$(dirname "${fonts[$i]}")
|
2022-11-25 13:52:23 +02:00
|
|
|
|
2023-06-01 10:49:26 +02:00
|
|
|
if [ "$(dirname "${individualdir}")" = "." ]; then
|
2022-12-14 18:47:37 +02:00
|
|
|
individualdir=""
|
|
|
|
else
|
|
|
|
if [ ${warned} -eq 0 ]; then
|
|
|
|
echo "$LINE_PREFIX WARNING: Non-flat directory structure in archive! We might have problems..."
|
|
|
|
warned=1
|
|
|
|
fi
|
|
|
|
# Remove leftmost directory (on Linux), the base directory of the zip file
|
|
|
|
individualdir=$(sed -E 's!/+!/!;s!^([^/]*/)|(/[^/]+/?)|([^/]*$)!!' <<< "${individualdir}")/
|
|
|
|
fi
|
2022-11-25 13:52:23 +02:00
|
|
|
|
|
|
|
if [ "$i" == 0 ]; then
|
|
|
|
{
|
2022-11-25 17:47:12 +02:00
|
|
|
printf " name \"%s (%s)\"\\n" "$familyname" "$unpatchedname"
|
2022-11-25 15:12:47 +02:00
|
|
|
printf " desc \"Developer targeted fonts with a high number of glyphs\"\\n"
|
2022-11-25 13:52:23 +02:00
|
|
|
printf " homepage \"%s\"" "$homepage"
|
|
|
|
printf "\\n\\n"
|
2022-11-25 15:12:47 +02:00
|
|
|
printf " livecheck do\\n"
|
|
|
|
printf " url :url\\n"
|
|
|
|
printf " strategy :github_latest\\n"
|
|
|
|
printf " end\\n\\n"
|
2022-11-25 13:52:23 +02:00
|
|
|
} >> "$outputfile"
|
|
|
|
fi
|
|
|
|
|
2022-12-14 18:47:37 +02:00
|
|
|
# When we have a 'deep' directory structure there can be multiple files with the same name
|
|
|
|
# (in different subdirectories). We can not install two files with the same name, that does
|
|
|
|
# not make sense. Someone has to choose which alternative is wanted.
|
|
|
|
# Here we just take the first one.
|
|
|
|
# This is only occuring at the moment with GohuFont.
|
2023-06-01 10:49:26 +02:00
|
|
|
# shellcheck disable=SC2091 # Evaluate on array
|
2022-12-14 18:47:37 +02:00
|
|
|
$(contains "$individualfont" "${all_individual_fonts[@]}") && {
|
|
|
|
printf " SKIPPING: %-${longest}s %s\\n" "${individualfont}" "${individualdir}/"
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
all_individual_fonts+=("$individualfont")
|
|
|
|
|
|
|
|
printf " font \"%s\"\\n" "${individualdir}${individualfont}" >> "${outputfile}"
|
|
|
|
printf " %-${longest}s %s\\n" "${individualfont}" "${individualdir}/"
|
2022-11-25 13:52:23 +02:00
|
|
|
|
|
|
|
done
|
|
|
|
else
|
|
|
|
echo "$LINE_PREFIX Did not find TTF or OTF"
|
|
|
|
fi
|
2016-12-03 05:56:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function write_footer {
|
2022-11-25 13:52:23 +02:00
|
|
|
local outputfile=$1
|
2016-11-06 05:09:12 +02:00
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
{
|
2023-05-13 08:58:09 +02:00
|
|
|
printf "\\n # No zap stanza required\\n"
|
2022-11-25 13:52:23 +02:00
|
|
|
printf "end\\n"
|
|
|
|
} >> "$outputfile"
|
2016-12-03 05:56:52 +02:00
|
|
|
}
|
|
|
|
|
2022-11-30 00:37:27 +02:00
|
|
|
pattern="$1.*"
|
2022-08-25 08:39:08 +02:00
|
|
|
if [ "$pattern" = "" ]; then
|
2022-11-25 13:52:23 +02:00
|
|
|
pattern=".*"
|
2022-08-25 08:39:08 +02:00
|
|
|
fi
|
|
|
|
|
2023-04-27 21:38:34 +02:00
|
|
|
find . -maxdepth 1 -mindepth 1 -type f -iregex "\./$pattern" -regex ".*\.zip" | LC_ALL=C sort |
|
2022-11-25 13:52:23 +02:00
|
|
|
while read -r filename; do
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2022-11-30 00:37:27 +02:00
|
|
|
basename=$(basename "$filename" .zip)
|
2022-11-25 15:12:47 +02:00
|
|
|
if [ ! -f "../archives/${basename}.zip" ]; then
|
|
|
|
echo "${LINE_PREFIX} No archive for: ${basename}, skipping..."
|
|
|
|
continue
|
|
|
|
fi
|
2022-11-25 13:52:23 +02:00
|
|
|
sha256sum=$(sha256sum "../archives/${basename}.zip" | head -c 64)
|
|
|
|
searchdir=$filename
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2023-06-01 10:49:26 +02:00
|
|
|
originalname=$(jq -r ".fonts[] | select(.folderName == \"${basename}\") | .unpatchedName" "${scripts_root_dir}/lib/fonts.json" | head -n 1)
|
|
|
|
caskbasename=$(jq -r ".fonts[] | select(.folderName == \"${basename}\") | .caskName" "${scripts_root_dir}/lib/fonts.json" | head -n 1)
|
2022-11-25 17:47:12 +02:00
|
|
|
if [ -z "$originalname" ]; then
|
|
|
|
echo "${LINE_PREFIX} Can not find ${basename} in fonts.json, skipping..."
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
2022-11-30 00:37:27 +02:00
|
|
|
rm -Rf "${basename}"
|
|
|
|
echo "$LINE_PREFIX Unpacking $basename"
|
|
|
|
unzip -q "${basename}" -d "${basename}"
|
|
|
|
searchdir=${basename}
|
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
FONTS=()
|
|
|
|
while IFS= read -d $'\0' -r file; do
|
|
|
|
FONTS=("${FONTS[@]}" "$file")
|
2023-05-01 11:10:01 +02:00
|
|
|
done < <(find "$searchdir" -type f -iname '*.[ot]tf' -print0 | LC_ALL=C sort -z)
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
outputdir=$PWD/../casks
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
echo "$LINE_PREFIX Generating cask for: $basename"
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
[[ -d "$outputdir" ]] || mkdir -p "$outputdir"
|
2016-12-03 05:56:52 +02:00
|
|
|
|
casks: Hardcode cask names in fonts.json
[why]
We want to replace the existing casks. But they do not have a consistent
way to name the casks. Sometimes blanks are preserved (as dashes):
"unpatchedName": "DejaVu Sans Mono",
"patchedName": "DejaVuSansMono",
"caskName": "dejavu-sans-mono",
The above looks like cask-name == unpatched-name.
Here they introduce blanks out of thin air (the original name does not
have blanks):
"unpatchedName": "DaddyTimeMono",
"patchedName": "DaddyTimeMono",
"caskName": "daddy-time-mono",
Here they add something to the name??!:
"unpatchedName": "Gohu",
"patchedName": "Gohu",
"caskName": "gohufont",
Here the cask-name follows the RFN renaming:
"unpatchedName": "Hasklig",
"patchedName": "Hasklug",
"caskName": "hasklug",
Here they do not follow the RFN renaming:
"unpatchedName": "Liberation",
"patchedName": "LiterationMono",
"caskName": "liberation",
And there are a lot more ... strangenesses.
I guess the casks have been created by different people following
different ideas.
[how]
All these inconsistencies makes setting up rules how to determine the
cask name from the other names very complicated and brittle.
If we want to preserve the existing cask names the simplest and most
stable approach is to explicitely specify them in the fonts.json
database:
Introduce a new data field "caskName", like shown above.
Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
2022-11-26 19:00:17 +02:00
|
|
|
caskname="font-${caskbasename}-nerd-font"
|
2022-11-25 13:52:23 +02:00
|
|
|
to="$outputdir/${caskname}.rb"
|
2016-12-03 05:56:52 +02:00
|
|
|
|
2022-11-25 13:52:23 +02:00
|
|
|
clear_file "$to"
|
|
|
|
write_header "$to" "$caskname"
|
2022-11-25 17:47:12 +02:00
|
|
|
write_body "$originalname" "$to" "${FONTS[@]}"
|
2022-11-25 13:52:23 +02:00
|
|
|
write_footer "$to"
|
2022-08-30 10:18:42 +02:00
|
|
|
|
2022-11-30 00:37:27 +02:00
|
|
|
rm -Rf "${basename}"
|
|
|
|
|
2023-06-01 10:49:26 +02:00
|
|
|
echo "## Created casks: $(realpath "${to}")"
|
2016-11-06 05:09:12 +02:00
|
|
|
done
|