1#!/usr/bin/env bash
2# Nerd Fonts Version: 2.1.0
3# Script Version: 1.1.1
4
5  # used for debugging
6  #set -x
7
8# for executing script to rebuild JUST the readmes:
9# ./gotta-patch-em-all-font-patcher\!.sh "" info
10
11LINE_PREFIX="# [Nerd Fonts] "
12
13# Check for Fontforge
14type fontforge >/dev/null 2>&1 || {
15  echo >&2 "$LINE_PREFIX FontForge must be installed before running this script."
16  echo >&2 "# Please see installation instructions at"
17  echo >&2 "# http://designwithfontforge.com/en-US/Installing_Fontforge.html"
18  exit 1
19}
20
21res1=$(date +%s)
22parent_dir="${PWD}/../../"
23# Set source and target directories
24source_fonts_dir="${PWD}/../../src/unpatched-fonts"
25like_pattern=''
26complete_variations_per_family=4
27font_typefaces_count=0
28font_families_count=0
29complete_variation_count=0
30total_variation_count=0
31total_count=0
32last_parent_dir=""
33unpatched_parent_dir="bin/scripts/../../src/unpatched-fonts"
34patched_parent_dir="patched-fonts"
35max_parallel_process=64
36
37if [ $# -eq 1 ]
38  then
39    like_pattern=$1
40    echo "$LINE_PREFIX Parameter given, limiting search and patch to pattern '$like_pattern' given"
41fi
42
43# simple second param option to allow to regenerate font info without re-patching
44if [ $# -eq 2 ]
45  then
46    info_only=$2
47    echo "$LINE_PREFIX 'Info Only' Parameter given, only generating font info (not patching)"
48fi
49
50# correct way to output find results into an array (when files have space chars, etc)
51# source: https://stackoverflow.com/questions/8213328/bash-script-find-output-to-array
52source_fonts=()
53 while IFS= read -d $'\0' -r file ; do
54     source_fonts=("${source_fonts[@]}" "$file")
55 done < <(find "$source_fonts_dir" -iname "$like_pattern*.[o,t]tf" -type f -print0)
56
57# print total number of source fonts found
58echo "$LINE_PREFIX Total source fonts found: ${#source_fonts[*]}"
59
60
61function patch_font {
62  local f=$1; shift
63  local i=$1; shift
64  #echo $i
65  #echo $f
66  # take everything before the last slash (/) to start building the full path
67  local patched_font_dir="${f%/*}/"
68  # find replace unpatched parent dir with patched parent dir:
69  local patched_font_dir="${patched_font_dir/$unpatched_parent_dir/$patched_parent_dir}"
70
71  [[ -d "$patched_font_dir" ]] || mkdir -p "$patched_font_dir"
72
73  config_parent_dir=$( cd "$( dirname "$f" )" && cd ".." && pwd)
74  config_dir=$( cd "$( dirname "$f" )" && pwd)
75
76  # source the font config file if exists:
77  if [ -f "$config_dir/config.cfg" ]
78  then
79    # shellcheck source=/dev/null
80    source "$config_dir/config.cfg"
81  elif [ -f "$config_parent_dir/config.cfg" ]
82  then
83    # shellcheck source=/dev/null
84    source "$config_parent_dir/config.cfg"
85  fi
86
87  if [ -f "$config_parent_dir/config.json" ]
88  then
89    # load font configuration file and remove ligatures (for mono fonts):
90    font_config="--removeligatures --configfile $config_parent_dir/config.json"
91  else
92    font_config=""
93  fi
94
95  if [ "$post_process" ]
96  then
97    post_process="--postprocess=$post_process"
98  else
99    post_process=""
100  fi
101
102  # shellcheck disable=SC2154
103  # we know the '$config_has_powerline' is from the sourced file
104  if [ "$config_has_powerline" ]
105  then
106    powerline=""
107    combinations=$(printf "./font-patcher ${f##*/} %s\\n" {' --use-single-width-glyphs',}{' --windows',}{' --fontawesome',}{' --octicons',}{' --fontlinux',}{' --pomicons',}{' --powerlineextra',}{' --fontawesomeextension',}{' --powersymbols',}{' --weather',}{' --material',})
108  else
109    powerline="--powerline"
110    combinations=$(printf "./font-patcher ${f##*/} %s\\n" {' --powerline',}{' --use-single-width-glyphs',}{' --windows',}{' --fontawesome',}{' --octicons',}{' --fontlinux',}{' --pomicons',}{' --powerlineextra',}{' --fontawesomeextension',}{' --powersymbols',}{' --weather',}{' --material',})
111  fi
112
113  cd "$parent_dir" || {
114    echo >&2 "# Could not find project parent directory"
115    exit 1
116  }
117
118  fontforge -quiet -script ./font-patcher "$f" -q $powerline $post_process --complete --no-progressbars --outputdir "${patched_font_dir}complete/" 2>/dev/null
119  fontforge -quiet -script ./font-patcher "$f" -q -s ${font_config} $powerline $post_process --complete --no-progressbars --outputdir "${patched_font_dir}complete/" 2>/dev/null
120  fontforge -quiet -script ./font-patcher "$f" -q -w $powerline $post_process --complete --no-progressbars --outputdir "${patched_font_dir}complete/" 2>/dev/null
121  fontforge -quiet -script ./font-patcher "$f" -q -s ${font_config} -w $powerline $post_process --complete --no-progressbars --outputdir "${patched_font_dir}complete/" 2>/dev/null
122  # wait for this group of background processes to finish to avoid forking too many processes
123  # that can add up quickly with the number of combinations
124  #wait
125
126}
127
128function generate_info {
129  local f=$1; shift
130  local i=$1; shift
131  #echo $i
132  #echo $f
133  # take everything before the last slash (/) to start building the full path
134  local patched_font_dir="${f%/*}/"
135  # find replace unpatched parent dir with patched parent dir:
136  local patched_font_dir="${patched_font_dir/$unpatched_parent_dir/$patched_parent_dir}"
137
138  [[ -d "$patched_font_dir" ]] || mkdir -p "$patched_font_dir"
139
140  config_parent_dir=$( cd "$( dirname "$f" )" && cd ".." && pwd)
141  config_dir=$( cd "$( dirname "$f" )" && pwd)
142  config_parent_dir_name=$(basename "$config_parent_dir")
143  is_unpatched_fonts_root=0
144
145  if [ "$config_parent_dir_name" == "unpatched-fonts" ]
146  then
147    is_unpatched_fonts_root=1
148    font_typefaces_count=$((font_typefaces_count+1))
149  fi
150
151  # source the font config file if exists:
152  if [ -f "$config_dir/config.cfg" ]
153  then
154    # shellcheck source=/dev/null
155    source "$config_dir/config.cfg"
156  elif [ -f "$config_parent_dir/config.cfg" ]
157  then
158    # shellcheck source=/dev/null
159    source "$config_parent_dir/config.cfg"
160  fi
161
162  if [ "$config_has_powerline" ]
163  then
164    powerline=""
165    combinations=$(printf "./font-patcher ${f##*/} %s\\n" {' --use-single-width-glyphs',}{' --windows',}{' --fontawesome',}{' --octicons',}{' --fontlinux',}{' --pomicons',}{' --powerlineextra',}{' --fontawesomeextension',}{' --powersymbols',}{' --weather',}{' --material',})
166  else
167    powerline="--powerline"
168    combinations=$(printf "./font-patcher ${f##*/} %s\\n" {' --powerline',}{' --use-single-width-glyphs',}{' --windows',}{' --fontawesome',}{' --octicons',}{' --fontlinux',}{' --pomicons',}{' --powerlineextra',}{' --fontawesomeextension',}{' --powersymbols',}{' --weather',}{' --material',})
169  fi
170
171  font_families_count=$((font_families_count+1))
172  complete_variation_count=$((complete_variation_count+complete_variations_per_family))
173  combination_count=$(printf "%s" "$combinations" | wc -l)
174
175  # generate the readmes:
176
177  # if first time with this font then re-build parent dir readme, else skip:
178  if [[ $config_parent_dir != "$last_parent_dir" ]] && [ $is_unpatched_fonts_root == "0" ];
179  then
180    echo "$LINE_PREFIX Re-generate parent directory readme"
181    generate_readme "$patched_font_dir.." 0
182  fi
183
184  generate_readme "$patched_font_dir" 1
185
186  last_parent_dir=$config_parent_dir
187
188  total_variation_count=$((total_variation_count+combination_count))
189  total_count=$((total_count+complete_variations_per_family+combination_count))
190
191}
192
193# Re-generate all the readmes
194# $1 = fontdir path
195function generate_readme {
196  local patched_font_dir=$1
197  local generate_combinations=$2
198  local combinations_filename="$patched_font_dir/readme.md"
199  local font_info="$patched_font_dir/font-info.md"
200
201  # clear output file (needed for multiple runs or updates):
202  true > "$combinations_filename"
203
204  if [ -f "$font_info" ];
205  then
206    cat "$patched_font_dir/font-info.md" >> "$combinations_filename"
207  else
208    echo "$LINE_PREFIX Could not append font-info.md (file not found). Was standardize script run? It should be executed first"
209    echo "# looked for: $font_info"
210  fi
211
212  cat "$parent_dir/src/readme-per-directory-variations.md" >> "$combinations_filename"
213
214  if [ "$generate_combinations" == 1 ];
215  then
216    echo "$LINE_PREFIX Adding 'Possible Combinations' section"
217    # add to the file
218    {
219      printf "\`\`\`sh"
220      printf "\\n# %s Possible Combinations:\\n" "$combination_count"
221      printf "\\n"
222      printf "%s" "$combinations"
223      printf "\\n"
224      printf "\`\`\`"
225    } >> "$combinations_filename"
226  fi
227}
228
229if [ ! "$info_only" ]
230then
231  # Iterate through source fonts
232  for i in "${!source_fonts[@]}"
233  do
234    patch_font "${source_fonts[$i]}" "$i" 2>/dev/null &
235
236    # un-comment to test this script (patch 1 font)
237    #break
238
239    # wait for this set of bg commands to finish: dont do too many at once!
240    # if we spawn a background process for each set of fonts it will
241    # end up using too many system resources
242    # however we want to run a certain number in parallel to decrease
243    # the amount of time patching all the fonts will take
244    # for now set a 'wait' for each X set of processes:
245    if [[ $((i % max_parallel_process)) == 0 ]];
246    then
247      echo "$LINE_PREFIX Complete Variation Count after max parallel process is  $complete_variation_count"
248      wait
249    fi
250  done
251  # wait for all bg commands to finish
252  wait
253fi
254
255# update information in separate iteration (to avoid issues with bg processes and the counts):
256# Iterate through source fonts
257for i in "${!source_fonts[@]}"
258do
259  # only output after last slash (/):
260  path=${source_fonts[$i]}
261  font_file=${path##*/}
262  echo "$LINE_PREFIX Generating info for '$font_file'"
263  generate_info "$path" "$i" 2>/dev/null
264done
265
266font_typefaces_count=$(find "${PWD}/../../${patched_parent_dir}/"* -maxdepth 0 -type d | wc -l)
267
268res2=$(date +%s)
269dt=$(echo "$res2 - $res1" | bc)
270dd=$(echo "$dt/86400" | bc)
271dt2=$(echo "$dt-86400*$dd" | bc)
272dh=$(echo "$dt2/3600" | bc)
273dt3=$(echo "$dt2-3600*$dh" | bc)
274dm=$(echo "$dt3/60" | bc)
275ds=$(echo "$dt3-60*$dm" | bc)
276
277printf "$LINE_PREFIX Total runtime: %d:%02d:%02d:%02d\\n" "$dd" "$dh" "$dm" "$ds"
278
279printf "# All fonts patched to sub-directories in \\t\\t\\t'%s'\\n" "$patched_parent_dir"
280printf "# The total number of font typefaces patched was \\t\\t'%s'\\n" "$font_typefaces_count"
281printf "# The total number of font families patched was \\t\\t'%s'\\n" "$font_families_count"
282printf "# The total number of 'complete' patched fonts created was \\t'%s'\\n" "$complete_variation_count"
283printf "# The total number of 'variation' patched fonts created was \\t'%s'\\n" "$total_variation_count"
284printf "# The total number of patched fonts created was \\t\\t'%s'\\n" "$total_count"
285