summaryrefslogtreecommitdiffstats
path: root/2023/info/parallel-after.md
blob: 2f390ff860a3d8e9f2d16d0a3b55bc2abc034d51 (plain) (blame)
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
<!-- Automatically generated by emacsconf-publish-after-page -->


<a name="parallel-mainVideo-transcript"></a>
# Transcript


[[!template new="1" text="""Introduction""" start="00:00:00.000" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Hi everyone!""" start="00:00:00.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Welcome to our talk on Parallel Text Replacement.""" start="00:00:01.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""My name is Lovro, and I'll be telling you about an""" start="00:00:04.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""interesting problem that my friend Valentino and I""" start="00:00:07.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""set out to solve one afternoon.""" start="00:00:09.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We will describe the problem, take a look at some""" start="00:00:11.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""of the existing work and then present our solution.""" start="00:00:13.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Afterwards, we will show some demos and conclude""" start="00:00:16.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""with a quick overview of the implementation.""" start="00:00:19.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Let's get straight into it!""" start="00:00:21.520" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Problem: Goal""" start="00:00:23.440" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Here is a problem that most of us have dealt with""" start="00:00:23.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""at some point.""" start="00:00:25.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Assume we have a piece of code such as the following.""" start="00:00:27.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We use a code example here, but in general what we're""" start="00:00:29.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""about to discuss can be applied to any piece of text.""" start="00:00:32.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""After a bit of thinking, we decide that the names of""" start="00:00:35.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the two variables, &quot;foo&quot; and &quot;bar&quot;, should actually be""" start="00:00:37.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""swapped.""" start="00:00:39.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""That is, &quot;foo&quot; should be replaced with &quot;bar&quot;, and &quot;bar&quot;""" start="00:00:40.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""should be replaced with &quot;foo&quot;.""" start="00:00:43.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The question is: what is a good way to achieve this?""" start="00:00:45.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We could perform the edits manually if the code is""" start="00:00:49.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""small enough, and we might even be done reasonably""" start="00:00:51.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""quickly.""" start="00:00:53.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""However, consider two things.""" start="00:00:54.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Imagine the usual case where there's just too much""" start="00:00:56.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""code to edit by hand.""" start="00:00:58.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We have no other option than to automate the task.""" start="00:01:00.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""More importantly though, we have a whole programmable""" start="00:01:03.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""text editor right at our fingertips.""" start="00:01:06.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We should object to doing things that the computer""" start="00:01:08.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""can do for us.""" start="00:01:10.280" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Problem: Naive Multi-pass""" start="00:01:12.360" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""So, one way to automate it is by using our old friend""" start="00:01:12.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""query-replace (M-%) multiple times in a sequence.""" start="00:01:15.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We first do a pass where we replace &quot;foo&quot; with &quot;bar&quot;,""" start="00:01:19.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""then we do another pass where we replace &quot;bar&quot; with &quot;foo&quot;.""" start="00:01:22.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""But that's clearly not right.""" start="00:01:25.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We all know that this naive multi-pass approach""" start="00:01:26.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""doesn't work because it results in interference""" start="00:01:29.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""between the two replacements.""" start="00:01:31.560" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Problem: Clever Multi-pass""" start="00:01:34.200" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Instead, we have to be a bit more clever.""" start="00:01:34.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We should first replace &quot;foo&quot; with a temporary string,""" start="00:01:36.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""in this case &quot;oof&quot;, that we will call a &quot;token&quot;.""" start="00:01:39.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""To avoid interference, we must be careful to ensure""" start="00:01:42.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""that the token does not contain whatever we're about""" start="00:01:45.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to replace next.""" start="00:01:48.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Then we do a second pass to replace &quot;bar&quot; with &quot;foo&quot;,""" start="00:01:49.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and finally a third pass to replace the token with &quot;bar&quot;.""" start="00:01:52.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This gives us the result we want.""" start="00:01:56.080" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Problem: Terminology""" start="00:01:57.720" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Putting the implementation aside for a moment, this style""" start="00:01:57.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""of text replacement, where we replace multiple sources""" start="00:02:01.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""with their targets, without running into interference""" start="00:02:05.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""issues between replacement pairs, is what we call""" start="00:02:09.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""a &quot;parallel replacement&quot;.""" start="00:02:11.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This is the essence of the problem we're trying to solve.""" start="00:02:12.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The examples with swapping that we've shown so far""" start="00:02:16.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""are really just one of the many use cases that are""" start="00:02:18.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""supported by a general parallel replacement utility.""" start="00:02:21.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""To avoid confusion, let us clarify that the word &quot;parallel&quot;""" start="00:02:25.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""is not in reference to hardware parallelization, but""" start="00:02:28.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""rather comes from analogy with the Lisp let operator,""" start="00:02:31.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""where the bindings of variables are performed in parallel,""" start="00:02:34.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""rather than sequentially as in let*.""" start="00:02:38.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Parallel in this context means that none of the bindings""" start="00:02:40.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""are in scope within any of the initial value forms.""" start="00:02:43.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""In other words, just like a let's initialization form""" start="00:02:46.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""cannot refer to any of the earlier bindings, a""" start="00:02:50.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replacement pair's source should not be able to replace""" start="00:02:53.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the previously substituted targets of any other pair.""" start="00:02:56.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This is what we mean by &quot;no interference&quot;.""" start="00:03:00.200" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Problem: Scaling Multi-pass""" start="00:03:04.440" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""However, manually invoking multiple carefully chosen""" start="00:03:04.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""query-replace commands gets old very quickly.""" start="00:03:08.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Say we scaled up the problem and wanted to perform n""" start="00:03:11.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""swaps instead of just two, e.g. to swap, or rather,""" start="00:03:14.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""rotate, &quot;foo&quot; to &quot;bar&quot;, &quot;bar&quot; to &quot;baz&quot;, &quot;baz&quot; to &quot;quux&quot;""" start="00:03:18.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and &quot;quux&quot; to &quot;foo&quot;.""" start="00:03:22.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We would first have to perform n - 1 additional""" start="00:03:23.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replacements to introduce the necessary tokens,""" start="00:03:26.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""effectively doubling the number of steps.""" start="00:03:29.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Even if we tried to automate this, think about what""" start="00:03:32.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""tokens the code would have to generate if we had no""" start="00:03:34.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""prior knowledge of the replacement pairs given by the""" start="00:03:37.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""user.""" start="00:03:40.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We would have to program defensively and use long""" start="00:03:41.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""randomly-generated strings that, one, hopefully do""" start="00:03:44.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""not interfere with any of the replacement pairs,""" start="00:03:47.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and two, might slow down the search if they're overly long.""" start="00:03:50.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Can we do better?""" start="00:03:53.480" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Solution: Single-pass""" start="00:03:55.920" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Yes we can!""" start="00:03:55.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We can actually perform just a single pass.""" start="00:03:56.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The trick is to alternate between the replacement""" start="00:03:59.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""pairs, replacing whichever source occurs the earliest,""" start="00:04:02.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and making sure to continue scanning after the end""" start="00:04:06.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""of the substituted target in order to avoid interference.""" start="00:04:08.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This interleaving of replacements is not something""" start="00:04:12.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""that's easy to do by hand with query-replace.""" start="00:04:14.520" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Solution: Existing""" start="00:04:18.240" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Since this is Emacs we're talking about, of course""" start="00:04:18.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""there already exist solutions that implement this idea.""" start="00:04:20.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Here are few that we could find.""" start="00:04:23.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The EmacsWiki has a page dedicated to this problem.""" start="00:04:25.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Stack Overflow has an old post where a couple of""" start="00:04:28.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""users provided their solutions.""" start="00:04:31.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Mastering Emacs also gives a method along with other""" start="00:04:33.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""interesting query-replace-regexp (C-M-%) patterns.""" start="00:04:36.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""More recently, Tony Zorman made a blogpost providing""" start="00:04:39.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""a solution with an interface based on query-replace.""" start="00:04:42.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""I encourage you to take a look at these solutions if""" start="00:04:45.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""you're interested in the details.""" start="00:04:47.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""But while a step in the right direction, these solutions""" start="00:04:50.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""are not satisfactory because they all lack one or""" start="00:04:53.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""more of the following.""" start="00:04:55.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""One, they are not completely automated and require""" start="00:04:56.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the user to come up with a relatively complicated""" start="00:05:00.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and verbose query-replace-regexp invocation.""" start="00:05:02.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Two, they are restricted to performing only 2-element""" start="00:05:06.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""swaps rather than general parallel replacements.""" start="00:05:09.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Three, they don't provide any sort of interactivity""" start="00:05:12.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""during replacement and instead perform it in one shot.""" start="00:05:15.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Four, they don't attempt to integrate with the familiar""" start="00:05:18.620" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""query-replace interface, which supports skipping, undo,""" start="00:05:21.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""history and more advanced features like Lisp expressions""" start="00:05:25.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and recursive query edits.""" start="00:05:28.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Most importantly however, five, none of them were""" start="00:05:30.700" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""designed with regular expressions in mind and instead""" start="00:05:33.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""only ever consider literal strings.""" start="00:05:36.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""In fact, the only one that comes close is the""" start="00:05:39.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""half-automated solution that invokes query-replace-regexp""" start="00:05:43.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""with a specially crafted replacement.""" start="00:05:46.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""As an example, here's how you would use this technique""" start="00:05:48.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to perform a 3-element parallel regex replacement.""" start="00:05:51.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""It uses the backslash-comma Lisp expression feature""" start="00:05:54.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""in order to choose the appropriate target to substitute.""" start="00:05:57.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Aside from being very clumsy and tedious to write out,""" start="00:06:01.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""this approach makes it really hard to use more complex""" start="00:06:03.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""regular expressions that make use of capture groups""" start="00:06:06.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""themselves.""" start="00:06:09.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This was the biggest limitation that we wanted""" start="00:06:10.800" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to get rid of and the main motivation for our work.""" start="00:06:12.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""So, as an alternative to the existing zoo of 80% solutions,""" start="00:06:15.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""we aim to provide a 100% solution, one that handles""" start="00:06:19.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""regexes and consolidates all of the existing ideas""" start="00:06:24.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""into a single package.""" start="00:06:27.120" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Solution: query-replace-parallel""" start="00:06:29.080" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""We call it query-replace-parallel.""" start="00:06:29.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The package is free and open-source and can currently""" start="00:06:31.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""be found on GitHub under hokomo/query-replace-parallel.""" start="00:06:34.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The name is not yet finalized and we're open to any""" start="00:06:37.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""suggestions.""" start="00:06:40.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We hope to get it published on an Elisp""" start="00:06:41.503" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""package archive in the near future, but for now you""" start="00:06:43.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""can just download and load the main Elisp file manually.""" start="00:06:45.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""With all of that said, let's go through a few demos""" start="00:06:48.900" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to illustrate some use cases and see how to use the package.""" start="00:06:51.400" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Demonstration: Swap""" start="00:06:55.240" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Our first demo is a simple swap, like the one we""" start="00:06:55.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""showed at the beginning of the presentation.""" start="00:06:57.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This chunk of text is actually one of the tests""" start="00:06:59.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""from our package's code.""" start="00:07:02.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Assuming we have loaded  the package, we can execute""" start="00:07:03.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the query-replace-parallel command, a parallel version""" start="00:07:06.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""of the standard query-replace.""" start="00:07:09.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This command works with literal strings and will""" start="00:07:11.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""ask for each source and target in turn.""" start="00:07:14.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Our goal is to replace &quot;foo&quot; with &quot;bar&quot;""" start="00:07:16.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and &quot;bar&quot; with &quot;foo&quot;.""" start="00:07:21.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""After inputting our replacements, we terminate the""" start="00:07:24.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""prompt by pressing enter with empty input.""" start="00:07:27.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""At this point, everything functions the same as in""" start="00:07:29.860" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""a standard query-replace invocation.""" start="00:07:32.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The echo area shows the match and the replacement""" start="00:07:35.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""we're about to make.""" start="00:07:37.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We can perform replacements,""" start="00:07:38.703" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""undo them,""" start="00:07:43.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""skip them,""" start="00:07:46.503" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""execute them until the end,""" start="00:07:49.203" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and so on.""" start="00:07:50.240" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Demonstration: LaTeX""" start="00:07:53.970" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""The second demo shows our first regex use case.""" start="00:07:53.970" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Imagine we have the following LaTeX code.""" start="00:07:56.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We realize that we haven't been completely consistent""" start="00:07:58.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""in our use and naming of macros, so we decide to""" start="00:08:01.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""fix the problem.""" start="00:08:04.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This time we execute query-replace-parallel-regexp""" start="00:08:05.536" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""because we want to work with regex instead of literal""" start="00:08:08.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""strings.""" start="00:08:11.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We want to achieve two things.""" start="00:08:12.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""First, we want to wrap all usages of the variable n""" start="00:08:13.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""with the natvar macro.""" start="00:08:16.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Using the backslash-less-than and blackslash-greater-than""" start="00:08:18.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""constructs allows us to only match letters n not""" start="00:08:21.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""appearing as part of a larger word.""" start="00:08:23.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Second, we want to rename natvar to intvar because""" start="00:08:25.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the variables a, b and c are integers and not natural""" start="00:08:29.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""numbers.""" start="00:08:32.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We enter empty input to terminate the prompt and can""" start="00:08:33.300" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""now perform the replacements.""" start="00:08:35.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""There we go, the fixes are done and we didn't have""" start="00:08:42.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to think about in which order to apply them.""" start="00:08:44.480" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Demonstration: Regex""" start="00:08:48.700" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""We now take a look at a more complicated regex""" start="00:08:48.700" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""example to demonstrate that even advanced query-replace""" start="00:08:51.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""features are supported.""" start="00:08:53.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Each &quot;foo&quot; and &quot;bar&quot; in this example is followed by""" start="00:08:55.100" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""a number.""" start="00:08:57.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The goal is to not only swap &quot;foo&quot; and &quot;bar&quot;, but""" start="00:08:58.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""also increase or decrease the corresponding number.""" start="00:09:01.380" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We first match &quot;foo&quot; and capture the number that""" start="00:09:03.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""follows it.""" start="00:09:06.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""For the target, we make use of the backslash-comma""" start="00:09:07.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Lisp expression feature in order to replace the""" start="00:09:10.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""match with &quot;bar&quot; followed by the number's successor.""" start="00:09:12.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We do the same thing for &quot;bar&quot;, except that we""" start="00:09:15.540" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replace the number with its predecessor.""" start="00:09:17.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Performing the replacements, we can see how each""" start="00:09:27.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""number is incremented or decremented appropriately.""" start="00:09:29.120" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Demonstration: Order""" start="00:09:36.320" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""We haven't covered it explicitly so some of you may""" start="00:09:36.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""be wondering how parallel replacement deals with""" start="00:09:38.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""overlapping matches and whether the order of the""" start="00:09:41.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replacement pairs is significant.""" start="00:09:43.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This demo will clarify the exact behavior.""" start="00:09:45.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The first example has the sources &quot;watch&quot; and &quot;stopwatch&quot;.""" start="00:09:48.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Conceptually, the matches overlap, but the rule is""" start="00:09:57.500" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""that matches are always processed earliest first,""" start="00:10:00.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""regardless of their length or the ordering of the pairs.""" start="00:10:03.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Therefore it is &quot;stopwatch&quot; that gets replaced,""" start="00:10:06.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and not its substring &quot;watch&quot;.""" start="00:10:09.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The second example uses the sources &quot;watch&quot; and &quot;watchword&quot;.""" start="00:10:16.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Both of the matches now conceptually start at the same""" start="00:10:19.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""position.""" start="00:10:22.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""In situations like these the order of the pairs does""" start="00:10:23.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""matter, and ties are broken by prefering the pair that""" start="00:10:26.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""was entered first, which is behavior that is inherited""" start="00:10:29.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""from the Elisp regex engine.""" start="00:10:32.280" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""So, the substring &quot;watch&quot; in &quot;watchword&quot; is what gets""" start="00:10:34.460" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replaced in this case.""" start="00:10:37.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Situations where the order of the pairs is significant""" start="00:10:39.460" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""are not very common however, so the user generally""" start="00:10:41.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""doesn't have to worry about this edge case.""" start="00:10:44.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The order only matters when two or more sources""" start="00:10:46.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""share the same prefix, as in this example.""" start="00:10:49.960" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Demonstration: Fun""" start="00:10:54.440" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""The final demo tests the limits of the package and""" start="00:10:54.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""shows that it fully integrates with query-replace.""" start="00:10:56.960" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""It is really just for fun and can even serve as a""" start="00:10:59.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""small Emacs brainteaser.""" start="00:11:03.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""See if you can keep up!""" start="00:11:04.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We open a directory and enter Writable Dired mode""" start="00:11:06.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""in order to rename the directories &quot;foo&quot; and &quot;bar&quot;.""" start="00:11:09.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Instead of doing it quickly by hand, we decide to""" start="00:11:11.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""show off and use query-replace-parallel-regexp.""" start="00:11:14.760" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We enter our pairs and make use of the""" start="00:11:17.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""backslash-question-mark query edit feature.""" start="00:11:20.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Now whenever we perform a replacement, the query""" start="00:11:25.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""edit makes Emacs stop and prompt us for additional""" start="00:11:27.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""input to use as the target.""" start="00:11:30.840" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We confirm the renames and now enter the &quot;bar-lib&quot;""" start="00:11:36.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""directory in order to perform the same kind of""" start="00:11:39.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""replacement on &quot;baz&quot; and &quot;quux&quot;.""" start="00:11:42.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Rather than save time, we decide to be extra lazy""" start="00:11:44.500" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and take the long route.""" start="00:11:47.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We recall the first pair and initiate a recursive""" start="00:11:48.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""invocation of query-replace-parallel-regexp.""" start="00:11:52.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We are now replacing the replacement.""" start="00:11:54.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We apply our fixes and then do the same thing again""" start="00:12:01.020" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""with the second pair.""" start="00:12:04.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Recall and recurse.""" start="00:12:05.970" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We confirm the prompt and finally rename our directories.""" start="00:12:16.300" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Wow, that really paid off.""" start="00:12:25.360" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""Implementation""" start="00:12:29.120" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""Before we finish, a few quick words about the""" start="00:12:29.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""implementation for the curious.""" start="00:12:31.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Both query-replace-parallel and query-replace-parallel-regexp""" start="00:12:33.300" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""delegate to the complex perform-replace function""" start="00:12:36.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""which is the workhorse of query-replace's interactive""" start="00:12:39.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""mechanism.""" start="00:12:41.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The way we achieve multiple interleaved replacements""" start="00:12:43.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""is by providing perform-replace with a big &quot;matcher regex&quot;""" start="00:12:45.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and a special replacement function.""" start="00:12:49.120" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Essentially, a complex parallel replacement like this""" start="00:12:50.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""is transformed into a standard replacement like this.""" start="00:12:54.400" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This is similar to the trick shown earlier in the""" start="00:12:57.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""presentation.""" start="00:13:00.200" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Each source is put in its own capture group to allow""" start="00:13:00.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""the replacement function to determine which one matched""" start="00:13:03.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""and return the appropriate target.""" start="00:13:06.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""However, we now take care to support arbitrary""" start="00:13:08.980" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""regular expressions as sources.""" start="00:13:11.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We achieve this by converting each source regex into""" start="00:13:13.480" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""an equivalent one for which we can guarantee that its""" start="00:13:17.080" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""capture groups will not clash with our matcher regex.""" start="00:13:19.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Information about this conversion is stored, and""" start="00:13:22.920" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""once the replacement function is called it has""" start="00:13:26.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""enough data to apply the replacement from the""" start="00:13:28.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""viewpoint of the original regex.""" start="00:13:30.360" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""The regex transformation is reliable because it""" start="00:13:32.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""uses the rx library, allowing us to treat regexes""" start="00:13:35.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""as s-expressions and avoid any nasty manual parsing.""" start="00:13:38.520" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""In fact, rx itself is based on one of Olin Shivers'""" start="00:13:42.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""100% solutions:""" start="00:13:46.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""SRE, or the S-expression regex notation.""" start="00:13:48.436" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""We all stand on the shoulders of many giants, so""" start="00:13:51.320" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""let's strive to design good solutions that we can""" start="00:13:54.440" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""all benefit from, many years into the future!""" start="00:13:56.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Finally, because query-replace's core is not completely""" start="00:13:59.240" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""customizable, we did have to sprinkle in some advice""" start="00:14:03.000" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""to get certain things working.""" start="00:14:06.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""This concerns only minor cosmetic fixes and not the""" start="00:14:07.600" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""core replacement functionality, but we have nontheless""" start="00:14:11.160" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""tried to do it in the simplest and least intrusive way""" start="00:14:14.040" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""possible.""" start="00:14:16.680" video="mainVideo-parallel" id="subtitle"]]

[[!template new="1" text="""End""" start="00:14:18.740" video="mainVideo-parallel" id="subtitle"]]

[[!template text="""In conclusion, go download and play with the package.""" start="00:14:18.740" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Even if you're not performing overlapping replacements,""" start="00:14:21.680" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""you can still use query-replace-parallel for the""" start="00:14:24.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""peace of mind knowing that things won't go wrong if""" start="00:14:26.880" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""you perform more than one replacement at a time.""" start="00:14:29.720" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Feel free to let us know about any interesting or""" start="00:14:32.460" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""crazy use cases you might come up with, as well as""" start="00:14:34.640" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""improvements or bugs that make it only a 99% solution.""" start="00:14:37.560" video="mainVideo-parallel" id="subtitle"]]
[[!template text="""Thanks for listening and have a great EmacsConf!""" start="00:14:40.640" video="mainVideo-parallel" id="subtitle"]]

<a name="parallel-qanda-transcript"></a>
# Q&A transcript (unedited)

[[!template text="""[Speaker 0]: And I think we are live.""" start="00:00:08.620" video="qanda-parallel" id="subtitle"]]
[[!template text="""Hello again, everyone.""" start="00:00:09.620" video="qanda-parallel" id="subtitle"]]
[[!template text="""And hi, Lovro. How are you doing?""" start="00:00:10.940" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Just a second. Should I join the other room?""" start="00:00:15.339" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Oh, no, no, you can stay here.""" start="00:00:18.460" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: I can stay in the backstage.""" start="00:00:20.860" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Everything is fine. I don't think you are""" start="00:00:24.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""technically in the backstage right now you're""" start="00:00:25.520" video="qanda-parallel" id="subtitle"]]
[[!template text="""just in Big Blue Button with us.""" start="00:00:26.750" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Oh thanks. Oh because I have 2 of them open I""" start="00:00:30.040" video="qanda-parallel" id="subtitle"]]
[[!template text="""thought there were 2 different rooms.""" start="00:00:30.920" video="qanda-parallel" id="subtitle"]]
[[!template text="""1 is the backstage and the other,""" start="00:00:32.720" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: whichever, I can hear you and so can the""" start="00:00:38.239" video="qanda-parallel" id="subtitle"]]
[[!template text="""stream, so don't worry too much about which""" start="00:00:39.840" video="qanda-parallel" id="subtitle"]]
[[!template text="""is the backstage and which is the front page.""" start="00:00:41.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: I have no idea. Well, great,""" start="00:00:41.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""great. Okay, yeah. Yeah,""" start="00:00:43.660" video="qanda-parallel" id="subtitle"]]
[[!template text="""I'm doing great, just to answer your""" start="00:00:45.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""question.""" start="00:00:45.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Okay, great, great, Okay,""" start="00:00:47.379" video="qanda-parallel" id="subtitle"]]
[[!template text="""well splendid. So, I've pasted a link again""" start="00:00:49.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""on IRC if you want to ask your questions,""" start="00:00:51.520" video="qanda-parallel" id="subtitle"]]
[[!template text="""and I'd invite you to do so,""" start="00:00:53.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""because we have about 9 minutes of laborious""" start="00:00:54.620" video="qanda-parallel" id="subtitle"]]
[[!template text="""time to answer as many of them as possible.""" start="00:00:56.580" video="qanda-parallel" id="subtitle"]]
[[!template text="""And I'm going to start with the first 1.""" start="00:00:58.360" video="qanda-parallel" id="subtitle"]]
[[!template text="""This looks great and was very well-presented.""" start="00:01:01.100" video="qanda-parallel" id="subtitle"]]
[[!template text="""Do you have plans to upstream this""" start="00:01:03.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""functionality into Emacs?""" start="00:01:04.239" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: That's a good idea. That's something we""" start="00:01:08.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""thought about as well.""" start="00:01:08.860" video="qanda-parallel" id="subtitle"]]
[[!template text="""Currently, we haven't really contacted anyone""" start="00:01:11.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""to do this. Also, the current implementation,""" start="00:01:16.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""so as I mentioned in the presentation towards""" start="00:01:19.760" video="qanda-parallel" id="subtitle"]]
[[!template text="""the end, so we use a little bit of advice to""" start="00:01:22.120" video="qanda-parallel" id="subtitle"]]
[[!template text="""sort of patch some functionality of query""" start="00:01:24.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""replace because not everything was easy to""" start="00:01:26.479" video="qanda-parallel" id="subtitle"]]
[[!template text="""implement. The core functionality luckily""" start="00:01:28.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""was, But there's a couple of fixes we need to""" start="00:01:32.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""apply to the message function in order to""" start="00:01:34.200" video="qanda-parallel" id="subtitle"]]
[[!template text="""display a nice message in the echo buffer""" start="00:01:36.380" video="qanda-parallel" id="subtitle"]]
[[!template text="""because this doesn't happen on its own when""" start="00:01:39.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""we're using this trick with this big regex""" start="00:01:41.100" video="qanda-parallel" id="subtitle"]]
[[!template text="""and whatnot. So I don't think that the code""" start="00:01:45.360" video="qanda-parallel" id="subtitle"]]
[[!template text="""as it is would be upstreamable.""" start="00:01:47.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""I think probably if we wanted to upstream it,""" start="00:01:50.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""we would have to do some proper work on""" start="00:01:54.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""refactoring query place itself in order to""" start="00:01:57.180" video="qanda-parallel" id="subtitle"]]
[[!template text="""integrate all of this functionality just""" start="00:01:58.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""directly without any patching left and right.""" start="00:02:01.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""But yeah, definitely something I've given""" start="00:02:05.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""some thought, but so far no progress on it.""" start="00:02:10.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""I haven't actually started doing anything""" start="00:02:11.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""about it.""" start="00:02:12.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Right, So I'm curious now,""" start="00:02:17.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""you developed the feature and then you moved""" start="00:02:19.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""on to the presentation or did you want to do""" start="00:02:21.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""a presentation for EmacsConf and then you""" start="00:02:23.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""worked on something like this?""" start="00:02:24.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""Which was it first, the chicken or the egg?""" start="00:02:26.360" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Yeah, it was the former.""" start="00:02:28.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""So this is a problem I've been aware of for,""" start="00:02:31.320" video="qanda-parallel" id="subtitle"]]
[[!template text="""I mean, probably a couple of years.""" start="00:02:33.340" video="qanda-parallel" id="subtitle"]]
[[!template text="""And, you know, I talked to my friend""" start="00:02:35.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""Valentino about it and we had like a little""" start="00:02:37.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""discussion, you know, how would we do this?""" start="00:02:39.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""And then I remember back when I was""" start="00:02:41.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""researching about this problem and the""" start="00:02:44.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""various Emacs Lisp solutions,""" start="00:02:45.100" video="qanda-parallel" id="subtitle"]]
[[!template text="""all I could find were these solutions that""" start="00:02:47.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""would, you know, just shy away from""" start="00:02:49.400" video="qanda-parallel" id="subtitle"]]
[[!template text="""implementing the RegEx case,""" start="00:02:50.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""which is a really complicated 1.""" start="00:02:52.340" video="qanda-parallel" id="subtitle"]]
[[!template text="""And, after some discussion,""" start="00:02:54.720" video="qanda-parallel" id="subtitle"]]
[[!template text="""my friend and I decided,""" start="00:02:56.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""okay, what the hell? Let's,""" start="00:02:58.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""let's try and implement this.""" start="00:02:59.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""How hard can it be? And yeah,""" start="00:03:01.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""basically in 1 afternoon,""" start="00:03:03.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""the idea, our little trick and the whole""" start="00:03:06.300" video="qanda-parallel" id="subtitle"]]
[[!template text="""implementation was born.""" start="00:03:07.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""And then I think that was maybe around a year""" start="00:03:11.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""ago, maybe a bit less.""" start="00:03:12.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""And then through the months,""" start="00:03:14.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""we just thought, oh yeah,""" start="00:03:15.920" video="qanda-parallel" id="subtitle"]]
[[!template text="""maybe we could present this,""" start="00:03:17.420" video="qanda-parallel" id="subtitle"]]
[[!template text="""maybe it would be interesting for people to""" start="00:03:18.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""see and that's how we came up with the idea""" start="00:03:20.660" video="qanda-parallel" id="subtitle"]]
[[!template text="""to present at EmacsConf.""" start="00:03:22.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Okay, great. I don't see other people asking""" start="00:03:27.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""questions. So people, it's nice if I ask""" start="00:03:30.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""questions but you know,""" start="00:03:31.100" video="qanda-parallel" id="subtitle"]]
[[!template text="""the point is kind of for you to ask the""" start="00:03:33.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""questions. I see someone who's joined us on""" start="00:03:35.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""BBB. Peter, would you like to ask a question""" start="00:03:36.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""maybe? Otherwise I see another person writing""" start="00:03:41.720" video="qanda-parallel" id="subtitle"]]
[[!template text="""a question on the pad,""" start="00:03:43.040" video="qanda-parallel" id="subtitle"]]
[[!template text="""so we can either move for this 1.""" start="00:03:44.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""So I'll leave Peter to figure out if they""" start="00:03:46.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""want to ask a question.""" start="00:03:47.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""So I'm moving on to the next question.""" start="00:03:49.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 2]: I can jump in. That's a really well done talk""" start="00:03:57.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""and you really clearly laid out the problem""" start="00:04:01.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""and the solution there.""" start="00:04:03.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""While I was watching it,""" start="00:04:05.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""I was thinking maybe the nice way to name it""" start="00:04:10.740" video="qanda-parallel" id="subtitle"]]
[[!template text="""is just to name it query replace and query""" start="00:04:13.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""replace regext, you know,""" start="00:04:15.700" video="qanda-parallel" id="subtitle"]]
[[!template text="""overloading the original functions and then""" start="00:04:18.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""using a prefix number,""" start="00:04:23.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""like control number to indicate how many""" start="00:04:26.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""replacements you're going to do.""" start="00:04:29.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""But maybe that doesn't work with the""" start="00:04:31.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""recursive editing stuff,""" start="00:04:36.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""which I don't use much.""" start="00:04:37.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""So I don't have a good method.""" start="00:04:40.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: I think it would definitely work.""" start="00:04:43.260" video="qanda-parallel" id="subtitle"]]
[[!template text="""Well, the question is,""" start="00:04:46.260" video="qanda-parallel" id="subtitle"]]
[[!template text="""if we just overwrite the definitions,""" start="00:04:47.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""then, oh, well, I guess we could do that.""" start="00:04:51.700" video="qanda-parallel" id="subtitle"]]
[[!template text="""Nothing stops us. I mean,""" start="00:04:53.410" video="qanda-parallel" id="subtitle"]]
[[!template text="""we're in Emacs. We could definitely do that.""" start="00:04:54.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""And then if you give, like,""" start="00:04:55.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""a prefix argument, maybe it just drops you""" start="00:04:57.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""back to the original query replace.""" start="00:04:59.060" video="qanda-parallel" id="subtitle"]]
[[!template text="""Yeah, that's an idea. For now,""" start="00:05:01.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""we decided, OK, let's just keep everything""" start="00:05:02.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""explicitly separate just to avoid any""" start="00:05:05.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""confusion.""" start="00:05:05.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 2]: Yeah, I think that's the right thing to do""" start="00:05:09.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""for now. What I'm actually thinking is that""" start="00:05:11.820" video="qanda-parallel" id="subtitle"]]
[[!template text="""when you do query replace,""" start="00:05:13.620" video="qanda-parallel" id="subtitle"]]
[[!template text="""it just does the regular query replace.""" start="00:05:15.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""And if you're going to do,""" start="00:05:17.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""say, 3 parallel replacements,""" start="00:05:20.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""then you do Control-U,""" start="00:05:21.340" video="qanda-parallel" id="subtitle"]]
[[!template text="""query replace. Sorry. Control-3,""" start="00:05:25.580" video="qanda-parallel" id="subtitle"]]
[[!template text="""query replace. And then that way you don't""" start="00:05:28.580" video="qanda-parallel" id="subtitle"]]
[[!template text="""have The final prompt that you give nothing""" start="00:05:33.400" video="qanda-parallel" id="subtitle"]]
[[!template text="""to.""" start="00:05:33.760" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Exactly, that's actually not a bad idea.""" start="00:05:36.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""I think I like that. Yeah,""" start="00:05:39.720" video="qanda-parallel" id="subtitle"]]
[[!template text="""that's not a bad idea.""" start="00:05:40.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: It's always a quagmire whether to ask for an""" start="00:05:44.760" video="qanda-parallel" id="subtitle"]]
[[!template text="""argument or to use the universal argument.""" start="00:05:47.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""When you're working with Emacs and especially""" start="00:05:51.060" video="qanda-parallel" id="subtitle"]]
[[!template text="""the UX side of things in the package,""" start="00:05:52.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""it's so complicated to figure out which 1 you""" start="00:05:54.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""want to do. In this particular case,""" start="00:05:56.880" video="qanda-parallel" id="subtitle"]]
[[!template text="""I think it's the better option to use the""" start="00:06:00.340" video="qanda-parallel" id="subtitle"]]
[[!template text="""universal argument or any kind of argument""" start="00:06:02.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""with a control number before.""" start="00:06:04.040" video="qanda-parallel" id="subtitle"]]
[[!template text="""All right, we have about 3 more minutes of""" start="00:06:10.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""questions. Peter, if you don't mind,""" start="00:06:12.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""I'll keep reading the questions in the chat.""" start="00:06:14.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""Did you use pair programming while developing""" start="00:06:19.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""it, it being a package,""" start="00:06:21.100" video="qanda-parallel" id="subtitle"]]
[[!template text="""or did you work independently,""" start="00:06:22.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""alternating and reviewing with Valentino?""" start="00:06:24.840" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: It was definitely a pair programming kind of""" start="00:06:28.320" video="qanda-parallel" id="subtitle"]]
[[!template text="""thing. So if I remember correctly,""" start="00:06:29.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""I was sitting at the computer and Valentino""" start="00:06:32.760" video="qanda-parallel" id="subtitle"]]
[[!template text="""was in front of a whiteboard and we were just""" start="00:06:36.020" video="qanda-parallel" id="subtitle"]]
[[!template text="""dissecting this regex and a bunch of examples""" start="00:06:38.400" video="qanda-parallel" id="subtitle"]]
[[!template text="""and trying to get these capture groups and""" start="00:06:41.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""stuff that we have to remap internally to get""" start="00:06:44.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""these offsets right and avoid off by 1 error""" start="00:06:46.560" video="qanda-parallel" id="subtitle"]]
[[!template text="""and stuff like that. So yeah,""" start="00:06:48.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""definitely a team effort.""" start="00:06:49.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Okay, great. Moving on to the next question.""" start="00:06:53.660" video="qanda-parallel" id="subtitle"]]
[[!template text="""What is your background in programming?""" start="00:06:55.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""Was it difficult to implement following the""" start="00:06:57.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""same API and architecture as what is already""" start="00:06:59.700" video="qanda-parallel" id="subtitle"]]
[[!template text="""in Emacs?""" start="00:07:00.200" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: So maybe just a quick back story.""" start="00:07:05.400" video="qanda-parallel" id="subtitle"]]
[[!template text="""Both Valentino and I are actually PhD""" start="00:07:06.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""students in computer science,""" start="00:07:08.300" video="qanda-parallel" id="subtitle"]]
[[!template text="""and we literally share an office.""" start="00:07:09.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""So that's how we even started talking about""" start="00:07:12.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""this whole thing. And we both use Emacs,""" start="00:07:14.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""of course. But I don't think this was too""" start="00:07:18.380" video="qanda-parallel" id="subtitle"]]
[[!template text="""hard to implement because luckily all of the""" start="00:07:20.740" video="qanda-parallel" id="subtitle"]]
[[!template text="""interactive functionality like this""" start="00:07:22.300" video="qanda-parallel" id="subtitle"]]
[[!template text="""complicated undo, skipping,""" start="00:07:23.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""execute until the end and so on,""" start="00:07:25.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""all of this is really just already provided""" start="00:07:27.980" video="qanda-parallel" id="subtitle"]]
[[!template text="""by the Emacs queer replace implementation.""" start="00:07:29.860" video="qanda-parallel" id="subtitle"]]
[[!template text="""So sort of what we do is we just invoke it as""" start="00:07:34.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""a function and delegate to it.""" start="00:07:36.080" video="qanda-parallel" id="subtitle"]]
[[!template text="""And we came up with this clever trick to""" start="00:07:37.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""basically delegate this multi-replacement to""" start="00:07:42.380" video="qanda-parallel" id="subtitle"]]
[[!template text="""this 1 single function that's already there.""" start="00:07:45.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""So it wasn't too complicated.""" start="00:07:47.980" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Alright. And we have about 2 minutes of time""" start="00:07:54.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""for the last question.""" start="00:07:55.560" video="qanda-parallel" id="subtitle"]]
[[!template text="""What did you learn about Emacs programming or""" start="00:07:58.040" video="qanda-parallel" id="subtitle"]]
[[!template text="""programming in general while working on this""" start="00:08:00.020" video="qanda-parallel" id="subtitle"]]
[[!template text="""project? A very wide question for me.""" start="00:08:02.320" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Maybe 1 thing I would like to add to the""" start="00:08:05.840" video="qanda-parallel" id="subtitle"]]
[[!template text="""previous just answer is I don't want to say""" start="00:08:09.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""like you know we're PhDs,""" start="00:08:10.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""a PhD is required for this or anything,""" start="00:08:12.780" video="qanda-parallel" id="subtitle"]]
[[!template text="""not at all. It's mostly just for a little bit""" start="00:08:15.800" video="qanda-parallel" id="subtitle"]]
[[!template text="""of context, but I think obviously,""" start="00:08:19.220" video="qanda-parallel" id="subtitle"]]
[[!template text="""even if you're not a PhD,""" start="00:08:20.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""I mean, you don't even require like""" start="00:08:22.360" video="qanda-parallel" id="subtitle"]]
[[!template text="""university, you know, education or anything.""" start="00:08:24.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""It wasn't overly difficult to implement,""" start="00:08:27.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""sort of just read some code that's already""" start="00:08:30.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""there and you know follow what you see and""" start="00:08:33.539" video="qanda-parallel" id="subtitle"]]
[[!template text="""poke Emacs a little bit and do a little bit""" start="00:08:35.860" video="qanda-parallel" id="subtitle"]]
[[!template text="""of debugging on the internals and you can""" start="00:08:38.140" video="qanda-parallel" id="subtitle"]]
[[!template text="""definitely get it. So definitely not a""" start="00:08:40.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""prerequisite to have a degree or anything to""" start="00:08:42.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""do any of this stuff. Okay so Coming back to""" start="00:08:45.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: Yeah, I'm going to amend a little bit the""" start="00:08:48.420" video="qanda-parallel" id="subtitle"]]
[[!template text="""question because we only have 1 minute.""" start="00:08:49.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""So just 1 thing in 10 seconds,""" start="00:08:51.600" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 2]: what did you""" start="00:08:52.490" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: learn about this?""" start="00:08:53.040" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: your last question. What did I learn about""" start="00:08:54.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""Emacs programming? That Emacs is so flexible""" start="00:08:56.420" video="qanda-parallel" id="subtitle"]]
[[!template text="""that I can go and I can patch literally its""" start="00:08:59.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""message function. And that is how we achieve""" start="00:09:01.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""the nice message function in the echo buffer.""" start="00:09:03.680" video="qanda-parallel" id="subtitle"]]
[[!template text="""So I can literally go and patch something as""" start="00:09:06.720" video="qanda-parallel" id="subtitle"]]
[[!template text="""crucial as message.""" start="00:09:07.560" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: It's great. That's a lovely 1.""" start="00:09:09.920" video="qanda-parallel" id="subtitle"]]
[[!template text="""And I think, again, we're going back to the""" start="00:09:12.260" video="qanda-parallel" id="subtitle"]]
[[!template text="""philosophy of Emacs. Everything is""" start="00:09:13.660" video="qanda-parallel" id="subtitle"]]
[[!template text="""programmable and even changing the message""" start="00:09:15.200" video="qanda-parallel" id="subtitle"]]
[[!template text="""function is great. All right,""" start="00:09:16.640" video="qanda-parallel" id="subtitle"]]
[[!template text="""well, thank you so much,""" start="00:09:17.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""Lovro, and thanks to Valentino as well,""" start="00:09:19.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""who's not here, but who's contributed to this""" start="00:09:21.820" video="qanda-parallel" id="subtitle"]]
[[!template text="""talk. Any last word?""" start="00:09:23.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Well, just if you're gonna build any""" start="00:09:29.540" video="qanda-parallel" id="subtitle"]]
[[!template text="""solutions, try to make them as foolproof and""" start="00:09:31.980" video="qanda-parallel" id="subtitle"]]
[[!template text="""as 100% as possible so we get more of these""" start="00:09:34.360" video="qanda-parallel" id="subtitle"]]
[[!template text="""goodies that are nice and robust for""" start="00:09:36.280" video="qanda-parallel" id="subtitle"]]
[[!template text="""everybody to use.""" start="00:09:37.000" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: All right, lovely. Well,""" start="00:09:39.400" video="qanda-parallel" id="subtitle"]]
[[!template text="""thank you so much, Lover,""" start="00:09:40.240" video="qanda-parallel" id="subtitle"]]
[[!template text="""for your presentation and your answer.""" start="00:09:41.940" video="qanda-parallel" id="subtitle"]]
[[!template text="""We'll be moving on to the next talk in just""" start="00:09:44.340" video="qanda-parallel" id="subtitle"]]
[[!template text="""about 5 seconds, and I'll see you after.""" start="00:09:47.260" video="qanda-parallel" id="subtitle"]]
[[!template text="""Bye, Lovro!""" start="00:09:47.900" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Yep, bye bye!""" start="00:09:49.760" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 0]: So I'm just waiting to make sure my VNC is a""" start="00:10:01.440" video="qanda-parallel" id="subtitle"]]
[[!template text="""little slow. Okay, we switch to the next""" start="00:10:02.840" video="qanda-parallel" id="subtitle"]]
[[!template text="""talk. All right, Lover,""" start="00:10:03.480" video="qanda-parallel" id="subtitle"]]
[[!template text="""I'm gonna need to go get ready now.""" start="00:10:04.960" video="qanda-parallel" id="subtitle"]]
[[!template text="""Yep. Bye-bye, and thanks for your talk.""" start="00:10:09.060" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 1]: Bye, thank you, see you.""" start="00:10:11.160" video="qanda-parallel" id="subtitle"]]
[[!template text="""[Speaker 2]: You""" start="00:10:15.060" video="qanda-parallel" id="subtitle"]]

Questions or comments? Please e-mail [hokomo@disroot.org](mailto:hokomo@disroot.org?subject=Comment%20for%20EmacsConf%202023%20parallel%3A%20Parallel%20text%20replacement)


<!-- End of emacsconf-publish-after-page -->