Skip to content

Instantly share code, notes, and snippets.

@Syzygies
Last active August 30, 2022 05:27
Show Gist options
  • Save Syzygies/226253bc38743ef474ee67cbf584cb2b to your computer and use it in GitHub Desktop.
Save Syzygies/226253bc38743ef474ee67cbf584cb2b to your computer and use it in GitHub Desktop.
Script for merging fonts to create lighter ()[]{} brackets for Lisp
FONT_SOURCE = '/Volumes/All/Sources/@ Fonts/Fonts/JetBrains Mono/JetBrainsMono-2.242'
FONT_OUTDIR = '/Volumes/All/Sources/@ Fonts/Fonts/JetBrains Mono/JetBrainsLisp'
FONT_TTXDIR = "#{FONT_OUTDIR}/ttx"
FONT_KIND = 'ttf'
FONT_NAME1 = 'JetBrainsMono'
FONT_NAME2 = 'JetBrains Mono'
OUTPUT_NAME1 = 'JetBrainsLisp'
OUTPUT_NAME2 = 'JetBrains Lisp'
GLYPHS = [ 'parenleft', 'parenright', 'braceleft', 'braceright', 'bracketleft', 'bracketright' ]
TASKS = [
%w{ Light Thin },
%w{ LightItalic ThinItalic },
%w{ Regular Thin },
%w{ Italic ThinItalic },
%w{ SemiBold ExtraLight },
%w{ SemiBoldItalic ExtraLightItalic },
%w{ Bold Light },
%w{ BoldItalic LightItalic },
]
FONT_SOURCE = '/Volumes/All/Sources/@ Fonts/Fonts/JetBrains Mono/JetBrainsMono-2.242'
FONT_OUTDIR = '/Volumes/All/Sources/@ Fonts/Fonts/JetBrains Mono/JetBrainsLisp'
FONT_TTXDIR = "#{FONT_OUTDIR}/ttx"
FONT_KIND = 'ttf'
FONT_NAME1 = 'JetBrainsMonoNL'
FONT_NAME2 = 'JetBrains Mono NL'
OUTPUT_NAME1 = 'JetBrainsLispNL'
OUTPUT_NAME2 = 'JetBrains Lisp NL'
GLYPHS = [ 'parenleft', 'parenright', 'braceleft', 'braceright', 'bracketleft', 'bracketright' ]
TASKS = [
%w{ Light Thin },
%w{ LightItalic ThinItalic },
%w{ Regular Thin },
%w{ Italic ThinItalic },
%w{ SemiBold ExtraLight },
%w{ SemiBoldItalic ExtraLightItalic },
%w{ Bold Light },
%w{ BoldItalic LightItalic },
]
#!/usr/bin/env ruby
# lisp-brackets.rb
# combine fonts, inserting ()[]{} from second font and renaming output
# relies on ttx command from Python fonttools 4.37.1
# https://pypi.org/project/fonttools/
# Some people, when confronted with an XML problem, think "I know, I'll use Nokogiri."
# Now they have two problems.
require_relative 'JetBrainsMono'
# require_relative 'JetBrainsMonoNL'
# require_relative 'SourceCodePro'
# make output directories as needed
system "mkdir -p '#{FONT_OUTDIR}' '#{FONT_TTXDIR}'"
TAG = { 'ttf' => 'TTGlyph', 'otf' => 'CharString' }[FONT_KIND]
TASKS.each do |task|
# create both xml files and read into memory
out = task[0]
one, two = task.map do |font|
puts
file = "#{FONT_NAME1}-#{font}"
src = "#{FONT_SOURCE}/#{file}.#{FONT_KIND}"
ttx = "#{FONT_TTXDIR}/#{file}.ttx"
if File.exists? ttx
puts ttx
else
system "ttx -d '#{FONT_TTXDIR}' -f '#{src}'"
end
File.read("#{FONT_TTXDIR}/#{file}.ttx")
end
# change names for output xml
one.sub! /<name>.*?<.name>/m do |name|
name.gsub! /<namerecord.*?<.namerecord>/m do |record|
if not record =~ /Copyright/
record.sub! /#{FONT_NAME1}/, OUTPUT_NAME1
record.sub! /#{FONT_NAME2}/, OUTPUT_NAME2
end
record
end
end
# determine glyphs to copy
tag = { 'ttf' => 'TTGlyph', 'otf' => 'CharString' }[FONT_KIND]
item_pat = /<#{TAG} name="([^"]+)"/
glyph_pat = /#{GLYPHS.join '|'}/
items = one.scan(item_pat).flatten.select {|v| v =~ glyph_pat}
# copy glyphs from two to one
puts
items.each do |glyph|
puts glyph
pat = /<#{TAG} name="#{glyph}".*?<.#{TAG}>/m
if one.match(pat) and m2 = two.match(pat)
one.sub! pat, m2[0]
end
end
# write output xml and convert back to font
puts
font = "#{FONT_TTXDIR}/#{OUTPUT_NAME1}-#{out}.ttx"
File.write font, one
system "ttx -d '#{FONT_OUTDIR}' -f '#{font}'"
end
FONT_SOURCE = '/Volumes/All/Sources/@ Fonts/Fonts/Adobe Source Code Pro/SourceCodePro_FontsOnly-1.013/OTF'
FONT_OUTDIR = '/Volumes/All/Sources/@ Fonts/Fonts/Adobe Source Code Pro/SourceCodeProLisp'
FONT_TTXDIR = "#{FONT_OUTDIR}/ttx"
FONT_KIND = 'otf'
FONT_NAME1 = 'SourceCodePro'
FONT_NAME2 = 'Source Code Pro'
OUTPUT_NAME1 = 'SourceCodeProLisp'
OUTPUT_NAME2 = 'Source Code Pro Lisp'
GLYPHS = [ 'parenleft', 'parenright', 'braceleft', 'braceright', 'bracketleft', 'bracketright' ]
TASKS = [
%w{ Regular ExtraLight },
]
@Syzygies
Copy link
Author

Matrix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment