linebender / norad

Rust crate for working with Unified Font Object files
Apache License 2.0
43 stars 12 forks source link

API to change UFOs in-place #210

Open madig opened 2 years ago

madig commented 2 years ago

Currently, every write erases the complete UFO directory and writes a fresh copy from memory.

It would be nice to be able to "commit a changeset" to a UFO where you only change what you marked for change. Add a glyph, modify another, delete a third, and then only those 3 changes hit the disk:

  1. Update contents.plist of the target layer with the addition and deletion and write it to disk,
  2. Write the added and modified glyph file to disk,
  3. Delete the third glyph file from disk.

I am imagining a ChangeSetBuilder where you could queue up these add/change/remove events. Maybe you wouldn't even need to read the entire UFO from disk but just apply the changes where needed? It could even have events for other things like lib, kerning, groups entries.

The primary use-case would be to avoid IO churn, accidentally changing the formatting of existing files (bleh) and maybe better supporting file watching tools?

cmyr commented 2 years ago

I do think it would be nice in theory if we could at least avoid writing out unchanged glyphs if they're already on disk, but as you mention this would also require us to track deleted glyphs, in addition to keeping track of whether anything changes.

In any case, I think we can treat this as a future optimization, since we would be able to implement this without breaking the public API.

madig commented 1 year ago

Harry had the idea of making this an external concern, i.e. if norad provides a granular way to specify which pieces of data to load and write (i.e. which glyphs), an external client could keep track of which data it cares about and simply instruct norad or provide some other way for norad to decide whether to write something or not, or even delete glyphs.

Hoolean commented 1 year ago

Expanding on this a little, we could get some way towards this if we added a save_requested_data() counterpart to load_requested_data(); even more so if it had a means to limit which glyphs and layers are saved and loaded :)

Hoolean commented 1 year ago

This would not replace change tracking within norad, as we could still add that later and build it on top of the external API for selectively-saving data