Making App
Let’s improve CodeaUnit a bit. But first, what’s the deal with iOS shortcuts? An odd report on an odd morning.
It turns out that there’s a user guide for Shortcuts. Who knew Apple could document things for the iPhone and Pad? I’m the sort of person who reads user guides. I’ve even read the entire Procreate1 user guide, more than once, because they keep improving the product.
It says here that you can run a Shortcut from the Shortcuts app, your home screen, a widget, your Apple watch, another app’s share sheet, or via Siri. Maybe I can shout “Hey, Siri, Commit” and have her do it. I fear the HomePod would try to do it. I have so many Siri instances in this house that it’s scary. She seems mostly benign, but I’m surrounded.
The Shortcuts documentation does drag on, but I’ve managed to learn enough to create this one:
When I execute that shortcut, it copies that new function text to the clipboard and then opens Codea. It seems that you cannot auto-paste into an app. Perhaps that makes sense. So I’ll type command+V when we get there, and we’ll see the following:
I can also ask Siri to run the shortcut for me. I’m a newbie here in Shortcut Land, but I’m told that I can put a quick action button on my home screen as well. Or on my watch, but I don’t see that as useful here.
So this is potentially pretty useful. My idea with “new function” was to include a return statement, which Codea doesn’t insert, so as to avoid my common mistake of not having one. Some more useful shortcuts might help me create new CodeaUnit test functions, which I often copy and paste to my detriment.
Shortcuts can prompt for input, so it’s probably possible to customize what gets pasted.
I don’t think anyone will find it productive to watch me fumbling with my initial shortcuts, so I’ll do further learning offline, but if you have useful experience, or specific questions, please tweet me up.
CodeaUnit Enhancements
In the D2 (Dung) program, I’ve made some changes to CodeaUnit to make it relate better to the way I work with that program:
It prints total test time to the console. My tests were taking a long time to run, and I wanted a reminder.
When tests are green, it doesn’t display anything, it just lets the program run.
It has a more robust check for whether tests have failed:
if CodeaUnit and CodeaTestsVisible then
if Console:find("[1-9] Failed")
or Console:find("[1-9] Ignored")
or Console:find("[1-9][0-9] Failed")
or Console:find("[1-9][0-9] Ignored") then
showingTests = true
showCodeaUnitTests()
end
end
The code above is looking at the Ignored and Failed lines to see whether any of them are non-zero. There may be a better way to do that but that one works.
The showingTests
flag is used to stop the program from running until I touch the screen, in the event that the tests are not green:
if not showingTests then
background(0)
Runner:draw()
end
Frankly, as I look at all the related code, I find it odd:
function draw()
local showingTests = false
if CodeaUnit and CodeaTestsVisible then
if Console:find("[1-9] Failed")
or Console:find("[1-9] Ignored")
or Console:find("[1-9][0-9] Failed")
or Console:find("[1-9][0-9] Ignored") then
showingTests = true
showCodeaUnitTests()
end
end
if not showingTests then
background(0)
Runner:draw()
end
end
function touched(aTouch)
CodeaTestsVisible = false
if aTouch.state == BEGAN then
Bus:publish("touchBegan", nil, aTouch.pos, capture)
elseif TouchCaptured and aTouch.state == ENDED then
TouchCaptured:touchEnded(aTouch.pos, Runner.player)
TouchCaptured:setHighlight(false)
TouchCaptured = nil
end
end
I guess it’s OK, the CodeaTestsVisible
flag, going to false after a touch, leaves the showingTests
flag also false. It’s odd, though.
The Dung app has its own copy of CodeaUnit, rather than using a dependency on my “library” copy. I’d best look to see what I’ve done to it. It appears that all I’ve done is comment out some prints, so that it doesn’t display anything but errors. That sort of thing should be handled with control flags, and probably should be set via parameters.
CodeaUnit presently creates just one:
parameter.action("CodeaUnit Runner", function()
CodeaUnit.execute()
end)
That’s the button you press to run CodeaUnit. I think we could add another parameter or two, to control its behavior a bit. That’s trickier than one might really prefer.
CodeaUnit Setup
There are three Codea projects involved when we use CodeaUnit.
- The CodeaUnit “library”, containing the CodeaUnit class and a few utility functions;
- The “CUBase” project template, containing a starting test tab, a starting Main tab, and with a reference to the library above;
- Your actual project, which starts out containing the “CUBase” tabs and references CodeaUnit.
Over time, my use of CodeaUnit has varied, and it’s probably time to clean up the Main tab. Let’s start there. The starting Main:
-- CUBase
function setup()
if CodeaUnit then
codeaTestsVisible(true)
runCodeaUnitTests()
end
end
function draw()
if CodeaUnit then showCodeaUnitTests() end
end
-- ------ functions below here
function runCodeaUnitTests()
local det = CodeaUnit.detailed
CodeaUnit.detailed = false
Console = _.execute()
CodeaUnit.detailed = det
end
function showCodeaUnitTests()
if CodeaVisible then
background(40, 40, 50)
pushMatrix()
pushStyle()
fontSize(50)
textAlign(CENTER)
if not Console:find("0 Failed") then
stroke(255,0,0)
fill(255,0,0)
elseif not Console:find("0 Ignored") then
stroke(255,255,0)
fill(255,255,0)
else
fill(0,255,0,50)
end
text(Console, WIDTH/2, HEIGHT-100)
popStyle()
popMatrix()
end
end
function codeaTestsVisible(aBoolean)
CodeaVisible = aBoolean
end
Let’s make some decisions here. The “new” design will have some parameters that come up, in addition to the button that runs the tests. There will be no special functions in the CUbase Main tab, just the minimum necessary code to run the tests from setup and display the results.
So the first thing I have to do with my new sample program is to bring CodeaUnit into it, in a separate tab, so that I can edit it as needed. Then I’ll put it back into CodeaUnit, and save what we wind up with as the new CUbase. Or roughly that, anyway …
Behavior
I’ve built a boolean parameter “CodeaUnit_Detailed”, that suppresses print of all output except for errors. I’ve improved the code to show the summaries in green red, or yellow, depending on whether the tests pass, fail, or have an ignored test, respectively.
I like the trick I did in the Dung program, that lets the program own the screen if tests are green, and locks the screen to the CodeaUnit summary if they’re yellow or red, until the user touches the screen.
Let’s do that with another parameter “CodeaUnit_Lock”.
I’ve got the default main tab down to this now:
-- CUBase
function setup()
--CodeaUnit_Detailed = false
--CodeaUnit_Lock = false
if CodeaUnit then
_.execute()
end
end
function draw()
background(40)
if CodeaUnit and CodeaUnit_Lock then
_.showTests()
else
background(128)
stroke(0)
fill(0)
text("Your App Here", WIDTH/2,HEIGHT/2)
end
end
function touched()
CodeaUnit_Lock = false
end
The two comments are there as a reminder that you can init the two new parameters to your liking. I think, with any luck, this will serve as a decent base. I do rather suspect that if I save this CodeaUnit back to the one used as a dependency, that old programs may behave oddly. I wonder if that means I should make a new version for this one.
I do, naming it CodeaUnit2. Now I can create the new base.
It turns out that none of these projects are under version control. I’ll put the new CUBase and CodeaUnit2 into WorkingCopy. Done.
Now what about converting D2 to use the new CodeaUnit? Sure, let’s try. The changes are easy but even after I reformat the output a bit I don’t like this:
When there’s an error anywhere, the entire output turns red. I can’t really make out which lines have problems. I think in the next version we’ll improve that. But for now, let’s sum up.
Summary
We’ve managed to make a new version of CodeaUnit that works for new projects and for D2. Older projects would perhaps require a bit of conversion but they can be left pointed at the old one.
I think I like the two new parameters, one for abbreviated output, which I’m tempted to make the default, and the other to unlock the screen and let your app run. For that one, I’m not entirely sure it’s right. As it stands now, it will unconditionally lock the screen until you touch it, even if your tests are green. I may decide that I don’t like that. We’ll see.
Looking forward, I think what I’ll do is create utilities, like the CodeaStats project, and rig them up to be included as additional dependencies (perhaps just one dependency), providing additional buttons and widgets that you can press to get their results. These could evolve into a somewhat nicer experience making larger Codea projects. I’ll be evolving toward a Codea “Making App”.
And I’ll experiment further with Shortcuts, to see whether there’s something actually helpful to do there. They need to be useful enough to be worth doing whatever special operation one has to do to trigger them, but pressing the Siri button and saying “new function” isn’t what I’d call difficult.
Anyway, kind of an odd morning, but some useful results. I hope to see you next time!
-
Procreate is a simply marvelous drawing app for iPadOS. It costs less than $10 and is incredibly powerful, with layers, custom brushes, and more. If you draw, and want to draw on a tablet, check it out. I am not compensated in any way for touting their excellent product. ↩