1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
|
WEBVTT captioned by sachac
NOTE Introduction
00:00:02.679 --> 00:00:06.782
Welcome to Watering My Digital Plant with Emacs Timers,
00:00:07.503 --> 00:00:11.384
a talk by Christopher Howard for Emacs Conference 2024.
00:00:11.385 --> 00:00:16.989
The goal of this talk is to give
00:00:17.010 --> 00:00:19.431
a brief introduction to Emacs timers
00:00:20.892 --> 00:00:23.334
using the illustration of how I created
00:00:23.394 --> 00:00:25.676
a bot for the Astrobotany service.
NOTE What is Astrobotany?
00:00:28.823 --> 00:00:30.004
What is Astrobotany?
00:00:30.924 --> 00:00:32.384
Let me jump to the home page.
00:00:38.649 --> 00:00:42.411
Astrobotany is a botany game or a simulation
00:00:42.611 --> 00:00:45.072
that is played using the Gemini protocol
00:00:45.893 --> 00:00:47.234
and gemtext documents.
NOTE What is Gemini?
00:00:48.914 --> 00:00:49.615
What is Gemini?
00:00:50.700 --> 00:00:53.563
The Gemini protocol is a small web protocol,
00:00:54.263 --> 00:00:57.246
similar to the HyperText Transfer Protocol,
00:00:58.047 --> 00:01:00.109
but with differing goals of simplicity,
00:01:00.789 --> 00:01:03.712
non-extensibility, and protecting privacy.
00:01:05.453 --> 00:01:09.057
Gemtext is a simple hyperlinking document format,
00:01:09.557 --> 00:01:14.242
the analog of the HyperText Markup Language, or HTML.
00:01:16.095 --> 00:01:17.075
Much more could be said
00:01:17.135 --> 00:01:18.516
about the design and goals
00:01:18.576 --> 00:01:19.756
of the Gemini project,
00:01:20.236 --> 00:01:22.096
but that is not the focus of this talk.
NOTE How do you play Astrobotany?
00:01:25.337 --> 00:01:27.057
And how do you play Astrobotany?
00:01:28.418 --> 00:01:30.518
First, you need to get a Gemini client
00:01:31.138 --> 00:01:32.838
or what you might call a browser.
00:01:34.079 --> 00:01:35.599
Many clients are available,
00:01:36.259 --> 00:01:39.860
but I am using Elpher, a Gemini client for Emacs.
00:01:41.340 --> 00:01:43.161
Once you have your client running,
00:01:43.801 --> 00:01:46.361
navigate to the home page for Astrobotany,
00:01:46.782 --> 00:01:48.842
which is shown in this window.
00:01:50.783 --> 00:01:53.023
You'll see the URL for the home page
00:01:53.103 --> 00:01:54.704
displayed at the top of the window.
00:01:57.865 --> 00:01:59.625
On your first visit to Astrobotany,
00:02:00.406 --> 00:02:02.586
you will need to create a client certificate,
00:02:03.426 --> 00:02:05.507
which will be used instead of a password.
00:02:06.067 --> 00:02:07.548
Your Gemini client will help you
00:02:07.588 --> 00:02:08.768
to create the certificate.
00:02:12.102 --> 00:02:16.306
Then you will go to the Visit Your Plant page
00:02:22.472 --> 00:02:24.553
in order to view your plant,
00:02:28.297 --> 00:02:32.781
to water it, and to collect things from it,
00:02:33.141 --> 00:02:37.928
including money. So here you see
00:02:37.968 --> 00:02:39.429
the plant that I'm currently growing
00:02:40.229 --> 00:02:41.910
in glorious ASCII graphics.
00:02:43.070 --> 00:02:46.691
There's also a color version available from this page.
00:02:56.895 --> 00:02:57.935
Back at the home page,
00:02:59.536 --> 00:03:00.836
you can do other things
00:03:02.537 --> 00:03:05.358
like go to the item shop,
00:03:07.165 --> 00:03:10.247
to buy items like badges, fertilizer,
00:03:11.607 --> 00:03:13.348
or post on the message board.
00:03:15.849 --> 00:03:18.991
In Astrobotany, gardener bots are fully legal.
00:03:20.852 --> 00:03:23.153
And to do an action on your plant,
00:03:23.693 --> 00:03:24.814
like watering the plant,
00:03:25.454 --> 00:03:26.915
all your bot needs to do is
00:03:27.035 --> 00:03:30.917
to access the appropriate Gemini URL or page
00:03:31.537 --> 00:03:33.998
while presenting the appropriate certificate
00:03:34.419 --> 00:03:34.999
for your plant.
NOTE Timers
00:03:37.000 --> 00:03:39.862
And this brings us to Emacs timers.
00:03:42.904 --> 00:03:45.906
So the main function of interest to us
00:03:46.626 --> 00:03:49.288
is the run-at-time function.
00:04:00.714 --> 00:04:03.235
Here is the help documentation,
00:04:03.395 --> 00:04:07.036
which is available in any recent Emacs installation.
00:04:10.157 --> 00:04:13.277
As you see, the purpose of the function
00:04:13.498 --> 00:04:16.718
is to perform an action at a specific time
00:04:20.920 --> 00:04:25.801
to repeat it after a specific number of seconds.
00:04:29.770 --> 00:04:32.573
And so basically, all you have to do is
00:04:32.673 --> 00:04:35.795
pass in a function to run-at-time,
00:04:36.436 --> 00:04:39.058
telling Emacs how soon you want to run the function,
00:04:39.999 --> 00:04:41.541
and then how often you want to run the
00:04:41.581 --> 00:04:42.461
function after that.
00:04:44.403 --> 00:04:46.605
The function has a variety of options for
00:04:46.645 --> 00:04:48.887
specifying the time parameter,
00:04:49.347 --> 00:04:52.030
that is, how soon you want the function to run.
00:04:55.307 --> 00:04:57.428
For our application, in which we'll be
00:04:57.508 --> 00:04:58.409
running our functions
00:04:58.649 --> 00:05:01.030
once or twice a day at specific times,
00:05:03.152 --> 00:05:04.513
it is most useful to
00:05:04.553 --> 00:05:06.954
specify the number of seconds until the event.
00:05:08.515 --> 00:05:09.876
This does, however, require
00:05:10.436 --> 00:05:11.977
calculating the number of seconds
00:05:12.097 --> 00:05:15.399
until a specific time of day. I will
00:05:15.419 --> 00:05:16.800
provide code for this shortly.
00:05:18.860 --> 00:05:20.803
The run-at-time function does allow you to
00:05:20.864 --> 00:05:23.308
specify the time parameter as a string,
00:05:24.029 --> 00:05:25.672
representing the hours and minutes.
00:05:26.413 --> 00:05:32.149
For example, 05:40.
00:05:32.150 --> 00:05:34.051
However, there is an oddity in the
00:05:34.091 --> 00:05:35.392
design of run-at-time,
00:05:36.372 --> 00:05:41.395
such that if the specified time of day has
00:05:41.455 --> 00:05:42.216
already passed,
00:05:43.196 --> 00:05:44.877
then the timer will run immediately,
00:05:45.578 --> 00:05:46.638
rather than in the future,
00:05:46.958 --> 00:05:47.839
as you might expect.
00:05:49.280 --> 00:05:51.441
This can be problematic, for example,
00:05:51.661 --> 00:05:54.663
if run-at-time is being called from your init file,
00:05:55.583 --> 00:05:57.624
since the timer will run immediately
00:05:58.245 --> 00:06:00.426
every time you restart Emacs for any reason.
00:06:02.526 --> 00:06:04.691
I noticed recently that run-at-time
00:06:04.791 --> 00:06:07.217
also allows you to pass in a value
00:06:07.317 --> 00:06:17.657
from encode-time, which maybe does what we want,
00:06:18.378 --> 00:06:20.760
but I never bothered with testing that.
00:06:21.340 --> 00:06:23.041
Actually, I have a vague memory of
00:06:23.181 --> 00:06:25.743
once looking into it and it didn't seem to do what I
00:06:25.783 --> 00:06:29.286
wanted, but honestly I can't clearly remember,
00:06:29.946 --> 00:06:31.667
so you may want to look into that yourself.
00:06:32.728 --> 00:06:34.209
What I ended up using was just
00:06:34.309 --> 00:06:35.750
passing in a number of seconds.
NOTE The code
00:06:37.792 --> 00:06:39.413
So now we'll move over to the code.
00:06:46.764 --> 00:06:49.426
So I'll skip down here first
00:06:49.966 --> 00:06:52.447
to the code that I wrote for calculating the number of
00:06:52.527 --> 00:06:52.887
seconds.
00:06:54.408 --> 00:06:57.790
It's a function that calculates the number of seconds
00:06:58.050 --> 00:07:01.012
until a particular time of day in the future.
00:07:04.214 --> 00:07:09.277
You can see that you pass in the hour as a number from
00:07:09.278 --> 00:07:19.137
0 to 23 and the minutes as a number from 0 to 59. And
00:07:20.078 --> 00:07:22.539
here's the code, which will also be available later.
00:07:25.700 --> 00:07:29.202
I wrote another function, secs-until-weekly,
00:07:29.522 --> 00:07:32.464
which we do not need for this talk,
00:07:32.604 --> 00:07:34.685
but which is useful if you're running
00:07:34.745 --> 00:07:36.746
events which need to happen once per week.
00:07:39.264 --> 00:07:44.025
This function also requires a target hour
00:07:44.085 --> 00:07:48.926
and a target minute, but also requires passing in a
00:07:48.966 --> 00:08:00.548
target day. And while we're on the subject of timers
00:08:00.568 --> 00:08:02.588
specifically, I should mention that
00:08:02.648 --> 00:08:05.929
Emacs has a very useful function called list-timers.
00:08:07.577 --> 00:08:09.959
So if I call the interactive function list-timers,
00:08:11.560 --> 00:08:14.542
it will give me a list of all the timers
00:08:14.842 --> 00:08:15.542
currently running.
00:08:16.723 --> 00:08:19.625
This page shows not only which timers exist,
00:08:20.186 --> 00:08:22.807
but also how long it will be until they run again,
00:08:23.848 --> 00:08:26.750
along with the periodic repeat value that you
00:08:26.770 --> 00:08:27.390
specified.
00:08:29.992 --> 00:08:33.034
Furthermore, any timer can be canceled by moving point
00:08:33.514 --> 00:08:38.515
over the timer and running timer-list-cancel,
00:08:38.696 --> 00:08:42.556
which on my system is bound to the letter c by default.
00:08:43.537 --> 00:08:45.417
This is very helpful while you are developing
00:08:45.497 --> 00:08:46.537
some timer function.
00:08:48.438 --> 00:08:52.158
So I could cancel the timer that I already have running
00:08:53.779 --> 00:08:55.059
for shaking the plant,
00:08:57.420 --> 00:08:59.360
as well as the one for watering the plant.
00:09:02.842 --> 00:09:03.843
and back to the code.
NOTE Managing the plant
00:09:05.724 --> 00:09:08.566
So now we'll talk about the actual code for
00:09:08.646 --> 00:09:09.567
managing the plant.
00:09:14.210 --> 00:09:16.031
So you see I have a variable set up here
00:09:16.471 --> 00:09:19.353
that specifies where the certificate file,
00:09:20.994 --> 00:09:23.836
the public certificate file, as well as
00:09:23.936 --> 00:09:26.458
the secret key file is located.
00:09:27.918 --> 00:09:29.459
This is where it is in my system.
00:09:30.119 --> 00:09:33.181
Of course, depending on your specific Gemini client,
00:09:33.481 --> 00:09:36.722
it may be in a different space and will likely have a
00:09:36.762 --> 00:09:37.303
different name.
00:09:41.045 --> 00:09:43.486
And here is the code for watering the plant,
00:09:44.526 --> 00:09:45.967
which I can call interactively.
00:09:49.412 --> 00:09:52.334
And the core of it here is that it uses the
00:09:52.834 --> 00:09:57.937
gmni utility, a command line utility to
00:10:00.998 --> 00:10:06.982
call a particular URL while also loading up
00:10:07.702 --> 00:10:10.564
or presenting the required certificate.
00:10:12.505 --> 00:10:16.447
So in this case, you can see it is the URL that is
00:10:16.567 --> 00:10:18.088
required for watering the plant.
00:10:19.827 --> 00:10:24.952
This idea is very simple and the gmni client
00:10:26.353 --> 00:10:30.097
or gmni command line program
00:10:30.758 --> 00:10:31.999
makes this very simple to do.
00:10:34.554 --> 00:10:36.535
Here's another function for shaking the plant.
00:10:37.696 --> 00:10:40.758
Again it is almost identical except that we
00:10:40.958 --> 00:10:43.300
use a different URL,
00:10:44.180 --> 00:10:46.982
one for shaking the plant instead of watering it.
00:10:47.562 --> 00:10:49.183
And again we want to shake the plant
00:10:50.044 --> 00:10:51.745
in order to get money to fall off of it.
00:10:55.847 --> 00:10:59.290
You need to water your plant at least once per day or
00:11:00.791 --> 00:11:01.251
it'll die.
00:11:02.930 --> 00:11:09.953
I usually water mine twice and just in case something
00:11:10.013 --> 00:11:13.314
happens where Emacs was turned off because of
00:11:13.414 --> 00:11:15.035
power outage or something like that
00:11:15.595 --> 00:11:17.196
that I'm more likely to get it watered,
00:11:19.036 --> 00:11:21.957
and I shake it once per day because there isn't
00:11:23.398 --> 00:11:25.339
any purpose to shaking it more than that.
00:11:25.619 --> 00:11:27.240
If you try to shake it more than that,
00:11:27.420 --> 00:11:29.560
then money no more money will fall off,
00:11:30.321 --> 00:11:30.821
or not much.
00:11:37.242 --> 00:11:39.526
So you see down here, I have the code that
00:11:39.627 --> 00:11:41.209
actually calls run-at-time.
00:11:42.560 --> 00:11:45.141
I left here commented my original forms of this
00:11:45.661 --> 00:11:50.024
which used the just specify directly the time of day.
00:11:50.644 --> 00:11:52.225
As I mentioned the problem with that
00:11:53.505 --> 00:11:54.466
was that it would...
00:11:54.786 --> 00:11:57.187
these functions would also get called
00:11:59.208 --> 00:12:02.649
whenever I restarted Emacs for any
00:12:02.709 --> 00:12:04.250
reason and that was kind of annoying.
00:12:05.011 --> 00:12:07.352
So instead we have here the functions down here
00:12:07.452 --> 00:12:09.533
which uses secs-until-daily
00:12:10.913 --> 00:12:11.754
to water the plant
00:12:12.294 --> 00:12:14.756
and then secs-until-daily to shake the plant.
00:12:16.057 --> 00:12:20.821
You see, I've specified the plant to get watered
00:12:21.181 --> 00:12:26.025
at 4 in the morning and then the function is run again
00:12:26.125 --> 00:12:31.269
after that, every 43,200 seconds, which translates to
00:12:31.389 --> 00:12:32.270
every 12 hours,
00:12:33.711 --> 00:12:36.353
and then I shake the plants, shake the plant
00:12:38.760 --> 00:12:43.341
every morning at 4.15 a.m. and once every [24] hours.
00:12:45.742 --> 00:12:46.802
With a little bit more
00:12:46.902 --> 00:12:49.483
sophistication, a little bit more work on the code,
00:12:50.143 --> 00:12:53.964
I could actually have multiple plants be watering and
00:12:54.264 --> 00:12:57.985
shaking multiple plants with multiple certificates,
00:12:58.105 --> 00:12:59.885
but I never got around to that.
00:13:00.946 --> 00:13:02.246
Didn't seem worth the bother to me.
NOTE Conclusion
00:13:09.560 --> 00:13:12.964
So thank you for watching my video,
00:13:13.825 --> 00:13:16.227
Watering My Digital Plant with Emacs Timers.
00:13:16.628 --> 00:13:18.189
You'll see at the bottom of this page
00:13:19.491 --> 00:13:21.613
links to the code for this talk
00:13:22.354 --> 00:13:24.096
as well as other things that I mentioned
00:13:24.677 --> 00:13:27.819
like the source code for the
00:13:27.979 --> 00:13:30.100
Elpher Gemini client,
00:13:30.801 --> 00:13:33.282
the URL for the Astrobotany capsule,
00:13:34.203 --> 00:13:36.865
as well as a link to more information about
00:13:36.925 --> 00:13:41.407
Project Gemini and my own personal Gemini capsule
00:13:42.808 --> 00:13:45.129
that's being run off my own server at home.
00:13:46.790 --> 00:13:47.471
Thank you very much.
|