mirror of
https://github.com/ryanoasis/nerd-fonts.git
synced 2024-12-13 17:18:37 +02:00
3b93c99637
[why] Normally the release zip files have a flat directory structure, i.e. all files are in the base directory and there are no subdirs. The existing subdirectory structure is removed on zip creation via `archive-fonts.sh`. If the patch results have two fonts with identical name these flat archives can not be generated. The `archive-fonts.sh` reports: Could not create archive with the path junked (-j option) - likely same font names for different paths, zip status: $zipStatus Retrying with full path But now the problem is only delayed. When the font file has the name name the Family and SubFamily are most likely also the same for both font files. If we install both the user (and the system) can not really distinguish the font files anymore. This turned up with [1] when doing a `brew style *nerd-font*` that complains in fact about duplicate fonts to install. At that point we had the additional problem that the subdir-path had been missing in the cask files. So I'm not sure if it would work from a Cask standpoint (i.e. font files are installed in subdirs). Anyhow, this will fail when the user wants to select the font files, because normally this is done on a Family-name basis. And identical file name usually means identical Family-SubFamily. Note that this ONLY happens with GohuFont, which has these subdirs: 11/complete 14/complete uni-11/complete uni-14/complete The font has embedded bitmaps, but only one size. The "11" ones have 11px bitmap fonts and the "14" ones 14px bitmaps. The "uni-" variant has much more glyphs. Otherwise the differences are slim. From the font creation date the "uni-" ones are newer. [how] Each font filename added to a cask is memorized. When the next fontfile is to be added to the cask it is checked if we already have that filename installed. Duplicates are then skipped. If we have a deep archive, the fonts are added to the cask with full relative path. In case of Gohu that means the 11/complete variant is added (because all files are alphabetically sorted before adding). By chance this is the same variant that has historically been in the Cask, so no change here. Fixes: https://github.com/ryanoasis/nerd-fonts/pull/1008#issuecomment-1351170552 https://github.com/Homebrew/homebrew-cask-fonts/pull/6758#issuecomment-1350791208 Signed-off-by: Fini Jastrow <ulf.fini.jastrow@desy.de>
256 lines
8.3 KiB
Bash
Executable File
256 lines
8.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Nerd Fonts Version: 2.3.0-RC
|
|
# Script Version: 2.2.0
|
|
#
|
|
# Iterates over all [*] archived fonts
|
|
# to generate ruby cask files for homebrew-fonts (https://github.com/caskroom/homebrew-fonts)
|
|
# * Only adds non-Windows versions of the fonts
|
|
# * Needs the zip archives in archives/ (i.e. run `./archive-fonts.sh` first)
|
|
#
|
|
# 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.
|
|
#
|
|
# [1] Accepts one parameter, a pattern which fonts to examine, if not given defaults
|
|
# 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
|
|
|
|
# set -x
|
|
set -e
|
|
|
|
version="2.3.0-RC"
|
|
homepage="https://github.com/ryanoasis/nerd-fonts"
|
|
downloadarchive="https://github.com/ryanoasis/nerd-fonts/releases/download/v#{version}/"
|
|
LINE_PREFIX="# [Nerd Fonts] "
|
|
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
|
|
|
|
cd ${archivedir} || {
|
|
echo >&2 "$LINE_PREFIX Could not find archives directory"
|
|
exit 1
|
|
}
|
|
|
|
function clear_file {
|
|
local outputfile=$1
|
|
# clear output file (needed for multiple runs or updates):
|
|
true > "$outputfile" 2> /dev/null
|
|
}
|
|
|
|
function write_header {
|
|
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"
|
|
}
|
|
|
|
# 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
|
|
if [[ "${fn}" == *Nerd* ]]; then
|
|
echo "${fn}"
|
|
return
|
|
fi
|
|
idx=$((${idx} + 1))
|
|
done
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
# 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
|
|
}
|
|
|
|
function write_body {
|
|
local unpatchedname=$1
|
|
local outputfile=$2
|
|
shift; shift;
|
|
local fonts=("$@")
|
|
|
|
if [ "${fonts[0]}" ]; then
|
|
local longest=-1
|
|
# Find longest filename for pretty printing
|
|
for i in "${!fonts[@]}"; do
|
|
local basename=$(basename "${fonts[$i]}")
|
|
if [ ${#basename} -gt $longest ]; then
|
|
longest=${#basename}
|
|
fi
|
|
done
|
|
# Find familyname of non Mono variant (well, rather shortest because we can contain multiple families)
|
|
local familyname=$(find_nerdish_family "${fonts[0]}")
|
|
for i in "${!fonts[@]}"; do
|
|
local fn=$(find_nerdish_family "${fonts[$i]}")
|
|
familyname=$(find_common_stem "${fn}" "${familyname}")
|
|
done
|
|
if [ -z "${familyname}" ]; then
|
|
echo >&2 "${LINE_PREFIX} Can not determine family name"
|
|
exit 2
|
|
fi
|
|
# Family names differ in front of "Nerd Font" (stem is short)
|
|
if [[ "${familyname}" != *Nerd* ]]; then
|
|
familyname="${familyname} Nerd Font families"
|
|
fi
|
|
familyname="$(tr [:lower:] [:upper:] <<< ${familyname:0:1})${familyname:1}"
|
|
# Process font files
|
|
local all_individual_fonts=( )
|
|
local warned=0
|
|
for i in "${!fonts[@]}"; do
|
|
local individualfont=$(basename "${fonts[$i]}")
|
|
local individualdir=$(dirname "${fonts[$i]}")
|
|
|
|
if [ $(dirname "${individualdir}") = "." ]; then
|
|
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
|
|
|
|
if [ "$i" == 0 ]; then
|
|
{
|
|
printf " name \"%s (%s)\"\\n" "$familyname" "$unpatchedname"
|
|
printf " desc \"Developer targeted fonts with a high number of glyphs\"\\n"
|
|
printf " homepage \"%s\"" "$homepage"
|
|
printf "\\n\\n"
|
|
printf " livecheck do\\n"
|
|
printf " url :url\\n"
|
|
printf " strategy :github_latest\\n"
|
|
printf " end\\n\\n"
|
|
} >> "$outputfile"
|
|
fi
|
|
|
|
# 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.
|
|
$(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}/"
|
|
|
|
done
|
|
else
|
|
echo "$LINE_PREFIX Did not find TTF or OTF"
|
|
fi
|
|
}
|
|
|
|
function write_footer {
|
|
local outputfile=$1
|
|
|
|
{
|
|
printf "end\\n"
|
|
} >> "$outputfile"
|
|
}
|
|
|
|
pattern="$1.*"
|
|
if [ "$pattern" = "" ]; then
|
|
pattern=".*"
|
|
fi
|
|
|
|
find . -maxdepth 1 -mindepth 1 -type f -iregex "\./$pattern" -regex ".*\.zip" | sort |
|
|
while read -r filename; do
|
|
|
|
dirname=$(dirname "$filename")
|
|
basename=$(basename "$filename" .zip)
|
|
if [ ! -f "../archives/${basename}.zip" ]; then
|
|
echo "${LINE_PREFIX} No archive for: ${basename}, skipping..."
|
|
continue
|
|
fi
|
|
sha256sum=$(sha256sum "../archives/${basename}.zip" | head -c 64)
|
|
searchdir=$filename
|
|
|
|
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)
|
|
if [ -z "$originalname" ]; then
|
|
echo "${LINE_PREFIX} Can not find ${basename} in fonts.json, skipping..."
|
|
continue
|
|
fi
|
|
|
|
rm -Rf "${basename}"
|
|
echo "$LINE_PREFIX Unpacking $basename"
|
|
unzip -q "${basename}" -d "${basename}"
|
|
searchdir=${basename}
|
|
|
|
FONTS=()
|
|
while IFS= read -d $'\0' -r file; do
|
|
FONTS=("${FONTS[@]}" "$file")
|
|
done < <(find "$searchdir" -type f -iwholename '*complete*' \( -iname '*.[o,t]tf' ! -wholename '*Windows Compatible*' \) -print0 | sort -z)
|
|
|
|
outputdir=$PWD/../casks
|
|
|
|
echo "$LINE_PREFIX Generating cask for: $basename"
|
|
|
|
[[ -d "$outputdir" ]] || mkdir -p "$outputdir"
|
|
|
|
caskname="font-${caskbasename}-nerd-font"
|
|
to="$outputdir/${caskname}.rb"
|
|
|
|
clear_file "$to"
|
|
write_header "$to" "$caskname"
|
|
write_body "$originalname" "$to" "${FONTS[@]}"
|
|
write_footer "$to"
|
|
|
|
rm -Rf "${basename}"
|
|
|
|
echo "## Created casks: $(realpath ${to})"
|
|
done
|