This only happens when pressing C-n inside a drawing in normal (not
maximized) mode.
The reason is complicated. First, the baseline:
* When pressing C-o:
run.keychord: starty is not nil
run.keychord: current drawing is nil
Drawing.keychord C-o: doesn't set current drawing
plan_draw (only happens in normal mode): clears starty in all lines
Drawing.update: all good ✓
* When pressing C-n:
run.keychord: starty is not nil
run.keychord: current drawing is nil
Drawing.keychord C-n: sets current drawing <===
plan_draw: clears starty in all lines
Drawing.update: BOOM
Ugh.
When is starty set? Drawing.draw. This is why I can clean it up with
abandon. But:
frame = events -> update -> draw
* plan_draw clears starty while processing events
* Drawing.update blows up in here <===
* Drawing.draw is about to set starty
So one possible interpretation here is that this is an unfortunate
interaction of two special-cases:
* draw should never mutate state, but it's just the most convenient
place to track starty
* keystrokes never set current drawing -- except rare operations like
naming and moving points
So the current prescription: any code called from within update needs to
protect against starty being nil.
Ugh X-(
All the Text functions assume the cursor is always on a text line. I was
violating that invariant.
* When scrolling up, I start the cursor at the top-most line below the
screen top.
* When scrolling down, I start the cursor at the top-most line below the
screen bottom.
I think it would feel slightly more natural for it to be the
bottom-most line above the screen bottom.
However, the Text functions maintain an invariant that the bottom-most
line in a buffer will be text. There's no such invariant for the
top-most line.
Earlier the ghost while drawing wouldn't quite match the final shape.
Now the math is identical in draw_pending_shape.
It's a little unfortunate that we have this duplication of formulae.
At least there are no other stray calls of App.mouse_x in
draw_pending_shape.
The drawing buttons are now absolutely positioned, which is a horrible
hack. But for just the source editor it seems good enough. The
alternative is to modify magic constants in all the tests :/
These are like versions in nativefs, but only support absolute paths.
I want to be thoughtful about the precise location at each call-site.
It's a little ugly that app.lua now has a dependency on file.lua. Or
source_file.lua for the source editor.
In the process, I'm getting rid of the search/ directory that cached
results and that I never ever used. This might pose an additional
migration issue: someone might need to `rm -rf` the `search/`
subdirectory in their notes.
Before:
- notes directory is saveDir/data by default
where saveDir = love.filesystem.getSaveDirectory()
- providing a commandline arg of x makes the notes directory saveDir/data.x
Now:
- there is no default directory; you get an error message instead
telling you what to do.
- the commandline arg is the (preferably absolute) path of the notes
directory you want to load
Unchanged: once you set the notes directory it gets remembered for
future runs.
Now the Readme is a lot simpler.
I tried to make migrating simpler, but this is complicated enough (see
Manual_tests.md)
Now pensieve.love always manages notes in the data/ subdirectory of the
save dir, and stores its settings in the 'config' file in the save dir.
And main.lua is now much more similar to upstream and most forks. I made
this edit using an external editor, just to keep the comparison with
lines.love in view.
Error_message is a special global. It's set when the app (Current_app = 'run')
encounters an error and switches to the source editor, and cleared when
switching from source editor back to the app.
Thanks to physfs and nativefs.lua
nativefs still introduces some inconsistencies with love.filesystem with
relative paths:
* love.fs.read: reads from save dir if it exists, falls back to source dir if not
* nativefs.read: reads from save dir if it exists, falls back to source dir if not ✓
* love.fs.write: always writes to save dir
* nativefs.write: always writes to source dir (since no restrictions)
* love.fs.newFile followed by file:open('r'): reads from save dir if it exists, source dir if not
* nativefs.newFile followed by file:open('r'): always reads from working dir
* love.fs.newFile followed by file:open('w'): always writes to save dir
* nativefs.newFile followed by file:open('w'): always writes to working dir
So avoid using relative paths with App primitives.