Oh, I have three other favorite tricks.
I call it first one "semi-global variables". All upvalues that are intended to
have scope of the entire file are collected near the top of the program
with no initializer. They tend to have fairly long, descriptive names,
not just 'x'.
I call the second one "local closures". All my functions that use upvalues
needed only by themselves sit inside a do..end block in which those upvalues
I call the third one "logical blocks". If half a page of code deserves a
comment describing what it does, one might as well put that comment
on the rest of a line starting with "do".
The result is that seeing 'local' at a place where I can't see the start of its
scope makes my eyes hurt.
I realize that these habits betray my Algol/Pascal programming past,
but at least they cost nothing.