Class: Fontisan::Cli

Inherits:
Thor
  • Object
show all
Defined in:
lib/fontisan/cli.rb

Overview

Command-line interface for Fontisan.

This class provides the Thor-based CLI with commands for extracting font information and listing tables. It supports multiple output formats (text, YAML, JSON) and various options for controlling output behavior.

Examples:

Run the info command

Fontisan::Cli.start(['info', 'font.ttf'])

Instance Method Summary collapse

Instance Method Details

#convert(font_file) ⇒ Object

Convert a font to a different format.

Supported conversions:

  • Same format (ttf→ttf, otf→otf): Copy/optimize

  • TTF ↔ OTF: Outline format conversion (foundation)

  • Future: WOFF2 compression, SVG export

Subroutine Optimization (–optimize): When converting TTF→OTF, you can enable automatic CFF subroutine generation to reduce file size. This analyzes repeated byte patterns across glyphs and creates shared subroutines, typically saving 30-50% in CFF table size.

Examples:

Convert TTF to OTF

fontisan convert font.ttf --to otf --output font.otf

Convert with optimization

fontisan convert font.ttf --to otf --output font.otf --optimize --verbose

Convert with custom optimization parameters

fontisan convert font.ttf --to otf --output font.otf --optimize \
  --min-pattern-length 15 --max-subroutines 10000

Copy/optimize TTF

fontisan convert font.ttf --to ttf --output optimized.ttf

Parameters:

  • font_file (String)

    Path to the font file



237
238
239
240
241
242
# File 'lib/fontisan/cli.rb', line 237

def convert(font_file)
  command = Commands::ConvertCommand.new(font_file, options)
  command.run
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#dump_table(font_file, table_tag) ⇒ Object

Dump raw binary table data to stdout.

Parameters:

  • font_file (String)

    Path to the font file

  • table_tag (String)

    Four-character table tag (e.g., ‘name’, ‘head’)



299
300
301
302
303
304
305
306
307
308
# File 'lib/fontisan/cli.rb', line 299

def dump_table(font_file, table_tag)
  command = Commands::DumpTableCommand.new(font_file, table_tag, options)
  raw_data = command.run

  # Write binary data directly to stdout
  $stdout.binmode
  $stdout.write(raw_data)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#export(font_file) ⇒ Object



332
333
334
335
336
337
338
339
340
341
# File 'lib/fontisan/cli.rb', line 332

def export(font_file)
  command = Commands::ExportCommand.new(
    font_file,
    output: options[:output],
    format: options[:format].to_sym,
    tables: options[:tables],
    binary_format: options[:binary_format].to_sym,
  )
  exit command.run
end

#features(font_file) ⇒ Object

List OpenType features available for scripts. If no script is specified, shows features for all scripts.

Parameters:

  • font_file (String)

    Path to the font file



141
142
143
144
145
146
147
# File 'lib/fontisan/cli.rb', line 141

def features(font_file)
  command = Commands::FeaturesCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#glyphs(font_file) ⇒ Object

List glyph names from the font file.

Parameters:

  • font_file (String)

    Path to the font file



77
78
79
80
81
82
83
# File 'lib/fontisan/cli.rb', line 77

def glyphs(font_file)
  command = Commands::GlyphsCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#info(font_file) ⇒ Object

Extract and display comprehensive font metadata.

Parameters:

  • font_file (String)

    Path to the font file



32
33
34
35
36
37
38
# File 'lib/fontisan/cli.rb', line 32

def info(font_file)
  command = Commands::InfoCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#instance(font_file) ⇒ Object

Generate static font instance from variable font.

You can specify axis coordinates using –wght, –wdth, etc., or use a predefined named instance with –named-instance. Use –list-instances to see available named instances.

Examples:

Generate bold instance

fontisan instance variable.ttf --wght=700 --output=bold.ttf

Use named instance

fontisan instance variable.ttf --named-instance="Bold" --output=bold.ttf

Instance with format conversion

fontisan instance variable.ttf --wght=700 --to=woff2 --output=bold.woff2

List available instances

fontisan instance variable.ttf --list-instances

Parameters:

  • font_file (String)

    Path to the variable font file



287
288
289
290
291
292
# File 'lib/fontisan/cli.rb', line 287

def instance(font_file)
  command = Commands::InstanceCommand.new
  command.execute(font_file, options)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#ls(file) ⇒ Object

List contents of font files with auto-detection.

For collections (TTC/OTC): Lists all fonts in the collection For individual fonts (TTF/OTF): Shows quick font summary

Examples:

List fonts in collection

fontisan ls fonts.ttc

Show font summary

fontisan ls font.ttf

Parameters:

  • file (String)

    Path to the font or collection file



53
54
55
56
57
58
59
# File 'lib/fontisan/cli.rb', line 53

def ls(file)
  command = Commands::LsCommand.new(file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#optical_size(font_file) ⇒ Object

Display optical size information from the font file.

Parameters:

  • font_file (String)

    Path to the font file



113
114
115
116
117
118
119
# File 'lib/fontisan/cli.rb', line 113

def optical_size(font_file)
  command = Commands::OpticalSizeCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#pack(*font_files) ⇒ Object

Create a TTC (TrueType Collection) or OTC (OpenType Collection) from multiple font files.

This command combines multiple fonts into a single collection file with shared table deduplication to save space. It supports both TTC and OTC formats.

Examples:

Pack fonts into TTC

fontisan pack font1.ttf font2.ttf font3.ttf --output family.ttc

Pack into OTC with analysis

fontisan pack Regular.otf Bold.otf Italic.otf --output family.otc --analyze

Pack without optimization

fontisan pack font1.ttf font2.ttf --output collection.ttc --no-optimize

Parameters:

  • font_files (Array<String>)

    Paths to input font files (minimum 2 required)



426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/fontisan/cli.rb', line 426

def pack(*font_files)
  command = Commands::PackCommand.new(font_files, options)
  result = command.run

  unless options[:quiet]
    puts "Collection created successfully:"
    puts "  Output: #{result[:output]}"
    puts "  Format: #{result[:format].upcase}"
    puts "  Fonts: #{result[:num_fonts]}"
    puts "  Size: #{format_size(result[:output_size])}"
    if result[:space_savings].positive?
      puts "  Space saved: #{format_size(result[:space_savings])}"
      puts "  Sharing: #{result[:sharing_percentage]}%"
    end
  end
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#scripts(font_file) ⇒ Object

List all scripts supported by the font from GSUB and GPOS tables.

Parameters:

  • font_file (String)

    Path to the font file



125
126
127
128
129
130
131
# File 'lib/fontisan/cli.rb', line 125

def scripts(font_file)
  command = Commands::ScriptsCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#subset(font_file) ⇒ Object

Subset a font to specific glyphs.

You must specify one of –text, –glyphs, or –unicode to define which glyphs to include in the subset.

Parameters:

  • font_file (String)

    Path to the font file



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/fontisan/cli.rb', line 179

def subset(font_file)
  command = Commands::SubsetCommand.new(font_file, options)
  result = command.run

  unless options[:quiet]
    puts "Subset font created:"
    puts "  Input: #{result[:input]}"
    puts "  Output: #{result[:output]}"
    puts "  Original glyphs: #{result[:original_glyphs]}"
    puts "  Subset glyphs: #{result[:subset_glyphs]}"
    puts "  Profile: #{result[:profile]}"
    puts "  Size: #{format_size(result[:size])}"
  end
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#tables(font_file) ⇒ Object

List all OpenType tables in the font file.

Parameters:

  • font_file (String)

    Path to the font file



65
66
67
68
69
70
71
# File 'lib/fontisan/cli.rb', line 65

def tables(font_file)
  command = Commands::TablesCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#unicode(font_file) ⇒ Object

List Unicode to glyph index mappings from the font file.

Parameters:

  • font_file (String)

    Path to the font file



89
90
91
92
93
94
95
# File 'lib/fontisan/cli.rb', line 89

def unicode(font_file)
  command = Commands::UnicodeCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#unpack(font_file) ⇒ Object

Extract individual fonts from a TTC (TrueType Collection) or OTC (OpenType Collection) file.

This command unpacks fonts from collection files, optionally converting them to different formats during extraction.

Examples:

Extract all fonts to directory

fontisan unpack family.ttc --output-dir extracted/

Extract specific font by index

fontisan unpack family.ttc --output-dir extracted/ --font-index 0

Extract with format conversion

fontisan unpack family.ttc --output-dir extracted/ --format woff2

Extract with custom prefix

fontisan unpack family.ttc --output-dir extracted/ --prefix "NotoSans"

Parameters:

  • font_file (String)

    Path to the TTC/OTC collection file



380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# File 'lib/fontisan/cli.rb', line 380

def unpack(font_file)
  command = Commands::UnpackCommand.new(font_file, options)
  result = command.run

  unless options[:quiet]
    puts "Collection unpacked successfully:"
    puts "  Input: #{result[:collection]}"
    puts "  Output directory: #{result[:output_dir]}"
    puts "  Fonts extracted: #{result[:fonts_extracted]}/#{result[:num_fonts]}"
    result[:extracted_files].each do |file|
      size = File.size(file)
      puts "  - #{File.basename(file)} (#{format_size(size)})"
    end
  end
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#validate(font_file) ⇒ Object



313
314
315
316
# File 'lib/fontisan/cli.rb', line 313

def validate(font_file)
  command = Commands::ValidateCommand.new(font_file, verbose: options[:verbose])
  exit command.run
end

#variable(font_file) ⇒ Object

Display variable font variation axes and instances.

Parameters:

  • font_file (String)

    Path to the font file



101
102
103
104
105
106
107
# File 'lib/fontisan/cli.rb', line 101

def variable(font_file)
  command = Commands::VariableCommand.new(font_file, options)
  result = command.run
  output_result(result)
rescue Errno::ENOENT, Error => e
  handle_error(e)
end

#versionObject

Display the Fontisan version.



345
346
347
# File 'lib/fontisan/cli.rb', line 345

def version
  puts "Fontisan version #{Fontisan::VERSION}"
end