-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathflowchart.ado
983 lines (944 loc) · 39.2 KB
/
flowchart.ado
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
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
*! version 0.0.8 18feb2019 Isaac M. E. Dodd
*##############################################################################*
********************************************************************************
*** FLOWCHART - SUBJECT DISPOSITION FLOW DIAGRAM FIGURE GENERATOR ****
********************************************************************************
*##############################################################################*
* FLOWCHART --------------------------------------------------------------------
capture program drop flowchart
program define flowchart
version 13
syntax [anything] [using/] [, name(string) value(string) template(string) output(string) arrow(string) *]
if("`1'" == "" | "`1'" == "getstarted" | "`1'" == "firsttime" | ("`1'" == "get" & "`2'" == "started")) {
display ""
flowchart_hline
flowchart_header
flowchart_title
flowchart_subtitle "Getting Started"
display ""
if("`1'" == "" | "`1'" == "firsttime") {
display " Setup: If this is your first time running the flowchart package, type: " //_newline
display " . {stata flowchart setup:flowchart setup}" _newline
display `" Start with the example flow diagram in "flowchart_example1.do" "'
display ""
}
display `" To start a new flowchart, here is a general starting point: "'
display `" Start with the command '. flowchart init using <filename>.data'"'
display `" (<filename>.data is an automatically generated/regenerated variable file.)"'
display `" Study the documentation and examples on how to properly format 'writerow' commands."'
display `" Use the 'connect' command to draw arrows between the blocks in each row."'
display `" End a diagram with the 'flowchart finalize' command with 2 important options:"'
display `" - template("...") is the .texdoc file, is an ancillary file which you don't need to edit."'
display `" - output("...") is the .tikz file which is automatically generated/regenerated."'
display ""
if("`1'" == "" | "`1'" == "firsttime") {
display `" If you do not have a LaTeX distribution installed you can get started using an online editor:"'
display `" {browse "https://www.overleaf.com/"}"'
display `" {browse "https://papeeria.com/"}"'
display `" {browse "https://www.latexbase.com/"}"'
display `" See the notes in "flowchart_example1.do" on how to eventually get started with a full LaTeX setup."'
display ""
}
flowchart_subtitle "Other Options"
display " 1. Updates: To update flowchart, type: " //_newline
display " . {stata flowchart setup, update:flowchart setup, update}" _newline
display " 2. Help: For extensive documentation, type: " //_newline
display " . {help flowchart:help flowchart}" _newline
display " 3. Support: For the URL to submit a support ticket, type: " //_newline
display " . {stata flowchart setup, support:flowchart setup, support}" _newline
display " 4. Uninstall: To uninstall flowchart, type: " //_newline
display " . {stata flowchart setup, uninstall:flowchart setup, uninstall}"
display ""
flowchart_subtitle "Website"
display " The flowchart package's website is available at:"
display `" {browse "https://github.com/IsaacDodd/flowchart/"}"'
display ""
flowchart_subtitle "License"
display " GNU LGPL 2007 - By installing this program you agree to this license, available in full here:" //_newline
display `" {browse "https://github.com/IsaacDodd/flowchart/blob/master/LICENSE.txt"}"'
display ""
display "Read this message again at anytime by typing '{stata flowchart getstarted:flowchart getstarted}'"
display ""
flowchart_footer
flowchart_hline
}
else if("`1'" == "status" | "`1'" == "status,") {
display ""
flowchart_header
flowchart_title
flowchart_footer
}
else if("`1'" == "help" | "`1'" == "help,") {
help flowchart
}
else if("`1'" == "init" | "`1'" == "init,") {
global Flowchart_Settings = "" // Stores settings in a space-delimited string.
global Flowchart_IteratorBlockfields = 0
global Flowchart_IteratorPathfields = 0
.Global.blockfields=.object.new
.Global.pathfields=.object.new
.Global.blockfields.Declare array list
.Global.pathfields.Declare array list
capture file close FlowchartFile
if("$Flowchart_Debug" == "on") {
display _rc
}
file open FlowchartFile using "`using'", write text replace
if("$Flowchart_Debug" == "on") {
display _rc
}
flowchart_init
display ""
display "...flowchart initialized."
}
else if("`1'" == "close" | "`1'" == "finalize" | "`1'" == "close," | "`1'" == "finalize," ) {
if("$Flowchart_Debug" == "on") {
display "Closed."
}
capture file close FlowchartFile
flowchart_tdfinalize, template("`template'") output("`output'")
}
else if("`1'" == "setup" | "`1'" == "setup,") {
gettoken varfirst varothers : 0
if("$Flowchart_Debug" == "on") {
display " First Variable: `varfirst'"
display `" Other Variables: `varothers'"'
}
flowchart_setup, `varothers' // Setup Function
}
else if("`1'" == "debug" | "`1'" == "debug,") {
gettoken varfirst varothers : 0
if("$Flowchart_Debug" == "on") {
display " First Variable: `varfirst'"
display `" Other Variables: `varothers'"'
}
flowchart_debug, `varothers' // Debug Function
}
else if("`1'" == "set") {
if("`2'" == "layout" | "`2'" == "layout,") {
if("$Flowchart_Debug" == "on") {
display "Write: `2' `name' `value'"
* To Do: Not yet implemented, other options: Move the variable writing to finalize so that if the
* user overrides default values they are committed afterwards. Use cond() to iterate through each
* variable to determine if the user has specified a new layout variable to override the default.
}
flowchart_writevar, name(`"set_`name'"') value(`"`value'"')
}
else if("`2'" == "variable" | "`2'" == "variable,") {
if("$Flowchart_Debug" == "on") {
display "Write: `2' `name' `value'"
}
flowchart_writevar, name(`"`name'"') value(`"`value'"')
}
}
else if("`1'" == "connect") {
if("$Flowchart_Debug" == "on") {
display "Connect: `1' `2' `3'"
}
if("`arrow'" != "") {
if("`arrow'" == "angled" | "`arrow'" == "angle" | "`arrow'" == "angledrev" | "`arrow'" == "anglerev") {
if("`arrow'" == "angled" | "`arrow'" == "angle") {
local arrow = "-|"
}
else if("`arrow'" == "angledrev" | "`arrow'" == "anglerev") { // Reverse the arrow direction
local arrow = "|-"
}
if("$Flowchart_Debug" == "on") {
display "`3'"
}
if(strpos(trim("`3'"), ",") > 0) {
local 3 = substr(trim("`3'"), 1, strpos(trim("`3'"), ",")-1)
if("$Flowchart_Debug" == "on") {
display "`3'"
}
}
}
}
else {
local arrow = "--"
}
flowchart_tdwrite_pathfield `" \path (`2') `arrow' (`3');"'
}
else {
*Sub-Commands that Require More Advanced Parsing
* Parse the token for a possible sub-command that contains a parameter (e.g., flowchart subcommand(parameter): ... )
* This is necessary since Stata's 'syntax' command returns the subcommand token `1' with a colon. This method ensures the proper string is parsed.
gettoken subcommand 0 : 0, parse(" :") quotes
while `"`subcommand'"' != ":" & `"`subcommand'"' != "" {
local subcmdwithparam `"`subcmdwithparam' `subcommand'"'
gettoken subcommand 0 : 0, parse(" :") quotes
if("$Flowchart_Debug" == "on") {
display ""
display "COMMAND PARSING: "
display `"Subcommand via GetToken: `subcommand'"'
}
local subcmdsyntax = "`1'"
if("$Flowchart_Debug" == "on") {
display "Subcommand via Syntax: `subcmdsyntax'"
display `"Subcommand with Parameter: `subcmdwithparam'"'
display `"Compound Quotes (CQ's): `0'"'
}
}
* Parse the possible sub-command with parameter, accounting for any whitespace within the passed parameter and subcommand.
local subparam = trim(substr(trim("`subcmdwithparam'"), strpos(trim("`subcmdwithparam'"), "(")+1, length(trim("`subcmdwithparam'"))-strpos(trim("`subcmdwithparam'"), "(")-1))
local subcmdparsed = substr(trim("`subcmdwithparam'"), 1, strpos(trim("`subcmdwithparam'"), "(")-1)
if("$Flowchart_Debug" == "on") {
display `"Subparameter via String Parse (CQs): `subparam'"'
display `"Subcommand via String Parse (CQs): `subcmdparsed'"'
}
if("`1'" == "writerow:" | "`1'" == "writerow" | "`subcmdparsed'" == "writerow" | trim("`subcmdparsed'") == "writerow") {
gettoken varfirst varothers : 0
if("$Flowchart_Debug" == "on") {
display ""
display "ROW CONTENT: "
display ""
display " First Variable: `varfirst'"
display ""
* display " Macro Without Quotes: " `varothers' <-- Breaks with flowchart_blank
* display ""
display `" Compound Quotes (CQ's): `varothers'"'
display ""
display `" Entire Statement (With CQ's): `0'"'
display ""
display "TOKENS:"
display ""
}
local i = 1 // Token Iterator
local blockparse = "center" // First Block Default = Center
flowchart_tdwrite_blockfield `" % Row - `subparam'"' // Row Command with Subparam (This is the Rowname)
while ("``i''" != "") { // while: TokenWhileLoop -- Loop through all of the tokens passed after the 'writerow(subparam):' call
if("$Flowchart_Debug" == "on") {
display "BLOCK START ---- [blockparse: `blockparse']"
display "`i': ``i''" // Print Token Number that starts the block, and the contents of that Token
}
if("``i''" == "`subcmdparsed'" | trim("``i''") == "`subcmdwithparam'" | trim("``i''") == "`subcmdsyntax'") {
local i = `i' + 1 // If the first token is the subparameter detected, ignore it and move to the next token instead.
continue
}
else if(trim("``i''") == "," | ((lower(trim("``i''")) == "flowchart_blank" | lower(trim("``i''")) == "flowchart_blank,") & "`blockparse'" == "center") ) {
* If a comma is encountered, or the block is blank/empty on the first block (default center), switch the blockparse flag to parse the left block (lblock) instead of the default center block (cblock).
local blockparse = "left"
flowchart_tdwrite_blockfield `" % -- Blank Center Block"' // flowchart_blank detected at the start of a new row, the center block.
local i = `i' + 1 // Move to the next token after the loop continues.
continue
}
* Generate a Look-Ahead Macro: This allows conditional if statements to anticipate the end of a block. (Returns 1 triplet/line ahead of the current triplet/line being parsed.)
local ilookahead = `i' + 3
if("$Flowchart_Debug" == "on") {
display `" [blockparse: `blockparse']"'
display `" LA: |``ilookahead''|"'
}
if("`blockparse'" == "center") {
local blockparsetoken = `" \node [block_`blockparse'] (`subparam'_`blockparse') {"'
} // fi: End of BlockParse
else if("`blockparse'" == "left") {
local blockparsetoken = `" & \node [block_`blockparse'] (`subparam'_`blockparse') {"'
} // fi: End of BlockParse
local k = 1 // Line Iterator - The first line (k=1) is the lead line. If only 1 line for the block is present (i.e., the Look-Ahead is a ',' after the lead-line) then the lead line represents a singleton lead-line, which is the only line in the block.
local stop = ""
while("`stop'" == "") { // while: LineWhileLoop - Loop through all of the lines for each block. The 'Stop' flag is raised when a comma is encountered or there is no more content passed in the command to parse.
if("$Flowchart_Debug" == "on") {
display " ---- NEW LINE"
}
if(trim("``i''") == "," | ((lower(trim("``i''")) == "flowchart_blank" | lower(trim("``i''")) == "flowchart_blank,") & "`blockparse'" == "center") ) { // Inept - To Do
* Here, if the first token encountered is a ',' or it's the first block parsed and the block is blank, produce no content. (If the second block, the left block, is blank, it needs to continue to produce a blank line '& \\' character.)
if("$Flowchart_Debug" == "on") {
display " --- "
display " --- Blank First Row --- "
display " --- Switching to parse the next block."
display " --- "
}
local blockparse = "left"
local stop = "stop"
break
}
if( trim("``i''") == "flowchart_blank" & "`blockparse'" == "left") {
if("$Flowchart_Debug" == "on") {
display " FLOWCHART_BLANK [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwrite_blockfield `" & \\ % -- Blank Left Block"' // flowchart_blank detected at the start of a new row, the center block.
local stop = "stop"
continue, break
}
local linename = `"``i''"' // Field 1 of the Line is expected to be the line-name, which is also the variable_name.
if("$Flowchart_Debug" == "on") {
display " token: `i'"
display " desc: ``i''"
}
local i = `i' + 1 // Move to the next field in the triplet/line.
if("$Flowchart_Debug" == "on") {
display " token: `i'"
display " lnum: ``i''"
}
local linenum = `"``i''"' // Field 2 of the Line is expected to be the line's value-number, variable_value, the (n=#).
flowchart_writevar, name(`"`linename'"') value(`"`linenum'"') // Store both the number and the line's name, with the line-name as
* the variable_name and the line's value-number as the variable_value with an equal sign as the delimiter (variable_name = variable_value)
* with a newline after. (Write it to the figvalue file.)
local i = `i' + 1 // Move to the next field in the triplet/line.
if("$Flowchart_Debug" == "on") {
display " token: `i'"
display " desc: ``i''"
}
local linedesc = `"``i''"' // Field 3 of the Line is expected to be the descriptive sentence.
if("$Flowchart_Debug" == "on") {
display " Added to Block-Line [`k']: "
}
if(`k' == 1) {
if(trim("``ilookahead''") == ",") {
local ilookaheadx2 = `ilookahead' + 1
if("$Flowchart_Debug" == "on") {
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
display "Lead-Line LA"
display "Look Ahead x 1: |``ilookahead''|"
display "Look Ahead x 2: |``ilookaheadx2''|"
}
if(lower(trim("``ilookaheadx2''")) == "flowchart_blank") {
if("$Flowchart_Debug" == "on") {
display "...--- EndBlank Detection on Singleton:"
display " --- Singleton Lead-line on Center Block but BLANK Left Block (k=1, LA is Comma, LA is flowchart_blank): tdwriteline - [content] [lead] [singleton] [end] [endblank]"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') lead(`"`blockparsetoken'"') singleton end endblank
if("$Flowchart_Debug" == "on") {
display "BREAK SINGLETON"
}
local blockparse = "left"
local i = `i' + 2 // Move by 2 tokens to move past the flowchart_blank
local stop = "stop"
continue, break
}
else {
if("$Flowchart_Debug" == "on") {
display " --- Singleton Lead-line on Center Block (k=1, LA is Comma): tdwriteline - [content] [lead] [singleton]"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') lead(`"`blockparsetoken'"') singleton
}
}
else if(trim("``ilookahead''") == "") {
if("$Flowchart_Debug" == "on") {
display " --- Singleton Lead-line on Left Block With Blank Center Block (so k=1) and Singleton Left Block (so LA is Blank): tdwriteline - [content] [lead] [singleton] [end]"
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') lead(`"`blockparsetoken'"') singleton end
}
else {
if("$Flowchart_Debug" == "on") {
*display " --- Singleton Lead-line on Left Block With Blank Center Block (so k=1) and Singleton Left Block (so LA is Blank): tdwriteline - [content] [lead] [singleton] [end]"
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') lead(`"`blockparsetoken'"')
}
}
else if(trim("``ilookahead''") == "," | trim("``ilookahead''") == "" | lower(trim("``i''")) == "flowchart_blank" | lower(trim("``ilookahead''")) == "flowchart_blank") {
local ilookaheadx2 = `ilookahead' + 1
if("$Flowchart_Debug" == "on") {
display "Non-Lead-Line LA"
display "Look Ahead x 1: ``ilookahead''"
display "Look Ahead x 2: ``ilookaheadx2''"
}
if(trim("``ilookahead''") == "") {
if("$Flowchart_Debug" == "on") {
display " --- End of Row with New Row - LA is Blank: tdwriteline - [content] [newrow] [end]"
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') newrow end
}
else if( (trim("``ilookahead''") == "," & trim("``ilookaheadx2''") == "") | lower(trim("``ilookaheadx2''")) == "flowchart_blank" ) {
if("$Flowchart_Debug" == "on") {
display "...--- EndBlank Detection: Second Block is Blank... tdwriteline - [content] [newrow] [end] [endblank]"
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') newrow end endblank
* The second block, the left block, is blank: Stop the LineWhileLoop to stop parsing the flowchart_blank token and any tokens after it.
if(lower(trim("``ilookaheadx2''")) == "flowchart_blank") {
if("$Flowchart_Debug" == "on") {
display "BREAK"
}
local i = `i' + 1
local stop = "stop"
continue, break
}
}
else {
if("$Flowchart_Debug" == "on") {
display "...--- End of Row: tdwriteline - [content] [end]""
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"') end
}
}
else {
if("$Flowchart_Debug" == "on") {
display "...--- Same Row, End of Line: tdwriteline - [content] "
display " [blockparse: `blockparse'] [ i#: `i'] [ token: ``i''] [ k: `k']"
}
flowchart_tdwriteline, name(`"`linename'"') num(`"`linenum'"') desc(`"`linedesc'"')
}
if("$Flowchart_Debug" == "on") {
display " ---- END OF LINE"
display ""
}
local k = `k' + 1
local i = `i' + 1
local ilookahead = `ilookahead' + 3
if("$Flowchart_Debug" == "on") {
display `" LA: ``ilookahead'' "'
}
if(trim("``i''") == "," | "``i''" == "") {
local blockparse = "left"
local stop = "stop"
}
} // elihw: End of LineWhileLoop
if("$Flowchart_Debug" == "tikz") {
flowchart_tdwrite_blockfield `" % +- Debug - End block for row: `subparam'"' // End of the Row
}
local i = `i' + 1
} // elihw: End of TokenWhile
} // fi: End of Writerow
} // fi: End of SyntaxCmdElse
end
capture program drop flowchart_setup
program define flowchart_setup
syntax [anything] [, update support uninstall]
display ""
display "|||||| Setup"
display ""
if("`uninstall'" != "") {
display "Uninstalling 'flowchart' package installation..."
display ""
capture ado uninstall flowchart
if (_rc) {
display as error "Uninstall Error: Previous version of 'flowchart' could not be uninstalled."
exit 111
}
else {
display "...Package 'flowchart' uninstalled successfully."
display ""
display "Note: If you uninstalled the package due to an error, please notify the developers"
display " of this error so that it can be fixed for all users by submitting an issue"
display " at the following URL:"
display ""
display `"{browse "https://github.com/IsaacDodd/flowchart/issues/new/"}"'
}
}
else if("`support'" != "") {
display ""
display "Open a new support ticket using the following URL: " _newline
display `"{browse "https://github.com/IsaacDodd/flowchart/issues/new/"}"'
display ""
}
else if("`update'" != "") {
display "Updating 'flowchart' package installation..."
display ""
capture ado uninstall flowchart
if (_rc) {
display as error "Update Error: Previous version of 'flowchart' could not be uninstalled."
exit 111
}
capture net install flowchart, replace from("https://raw.github.com/IsaacDodd/flowchart/master/")
if (_rc) {
display "Update Error: Update could not be completed."
display "Instructions:"
display " 1. Uninstall 'flowchart' by running:"
display " . {stata ado uninstall flowchart:ado uninstall flowchart}"
display " 2. Install 'flowchart' from GitHub directly by running:"
display `" . net install flowchart, replace from("https://raw.github.com/IsaacDodd/flowchart/master/")"'
display " If Instruction #2 does not work, check your internet connection."
display ""
capture ssc install flowchart, replace // Attempt to reinstall flwochart from SSC.
if(_rc) {
display as error "Update Error: Attempt to reinstall flowchart failed. Please reinstall flowchart."
exit 499
}
}
else {
display "...Update to flowchart installed successfully."
display ""
}
}
else {
* SETUP (Default)
* Update Flowchart from GitHub.
display " (1/3) Updating 'flowchart' installation ..."
display ""
capture ado uninstall flowchart // Same effect as ssc or net uninstall flowchart.
if (_rc) {
display as error "Setup Error: Update of 'flowchart' could not be completed. Attempt to update a previous version of flowchart has failed."
// exit 111 <-- This is the normal exit code. Rather than exist here, try to continue to see if the flowchart installation can be replaced.
}
capture net install flowchart, replace from("https://raw.github.com/IsaacDodd/flowchart/master/")
if (_rc) {
capture ssc install flowchart // Attempt to reinstall flowchart from SSC again since it was previously uninstalled.
display as error "Setup Error: Update of 'flowchart' could not be completed. Please check your internet connection and try again, or you may need to reinstall flowchart."
exit 499
}
else {
display "...Update to flowchart installed successfully."
display "Note: Updates to Flowchart will take effect when Stata is restarted."
display ""
}
* Install an updated version of texdoc
display " (2/3) Installing/Updating 'texdoc'..."
display ""
* Install texdoc
display " ...Installing/Updating Texdoc..."
capture ssc install texdoc, replace
if (_rc) {
display as error "Setup Error: Installation of dependency 'texdoc' could not be completed. Please check your internet connection and try again."
exit 499
}
* Install sjlatex
display " ...Installing/Updating sjlatex..."
capture net install sjlatex, from("http://www.stata-journal.com/production")
if (_rc) {
display as error "Setup Error: Installation of dependency 'sjlatex' for dependency 'texdoc' could not be completed. Please check your internet connection and try again."
exit 499
}
else {
display "...Texdoc installed/updated successfully."
display ""
}
display " (3/3) Installing Ancillary Files for 'flowchart'..."
display ""
capture net get flowchart, from("https://raw.github.com/IsaacDodd/flowchart/master/")
if (_rc) {
display as error "Setup Error: Setup could not install Ancillary Files. Please connect to the internet and try again." _newline ///
" (1) Check your current working directory to see if these ancillary files already exist." _newline ///
" If so, there is no need to re-run setup. Safely ignore this error message." _newline ///
" (2) Try running the following command:" _newline ///
`" . net get flowchart, from("https://raw.github.com/isaacdodd/flowchart/master/")"' _newline ///
" (3) You may also download these ancillary files directly from the latest release at the following URL:" _newline ///
`" {browse "https://github.com/IsaacDodd/flowchart/releases"} "'
exit 499
}
else {
display ""
display "...Ancillary files installed successfully in current working directory:"
pwd
display ""
}
display "|||||| Setup Complete"
display ""
flowchart_hline
display ""
if(_rc == 0) {
sleep 2000
flowchart firsttime // Print the get started message. Include the 'first time' part of the message
}
}
end
capture program drop flowchart_debug
program define flowchart_debug
syntax [anything] [, on off tikz logreset check info deletefiles yes]
if("`on'" == "on") {
global Flowchart_Debug = "on"
set more off
set linesize 161
local logid = subinstr("`c(current_date)'_`c(current_time)'", ":", "", .)
local logid = subinstr("`logid'", " ", "", .)
capture log query DebugLog
* If a log has already been started, DebugLog will exist. If it is off (i.e., it was started but has been closed/turned off),
* append to the existing log. If DebugLog does not exist (r(status) is blank) or it exists but is on already, replace the log.
flowchart_subtitle "DEBUG MODE: ON"
display ""
display " Starting Debug Log..."
display ""
if("`r(status)'" == "off") {
capture log close DebugLog
log using "DebugLog.log", name(DebugLog) append text
local debugtitle = "STARTED"
}
else {
capture log close DebugLog
log using "DebugLog.log", name(DebugLog) replace text
local debugtitle = "RESUMED"
}
capture log close DebugLog
log using "DebugLog.log", name(DebugLog) append text
display ""
flowchart_header "DEBUG LOG `debugtitle': Log ID = `logid'"
display ""
display ""
}
else if("`off'" == "off") {
global Flowchart_Debug = "off"
capture log off DebugLog
if(_rc) {
display as error "Could not turn off DebugLog."
}
else {
display "...DebugLog Off."
}
display ""
flowchart_footer "DEBUG MODE: OFF"
display ""
display ""
}
else if("`tikz'" == "tikz") {
global Flowchart_Debug = "tikz"
display ""
flowchart_header "DEBUG MODE: TikZ"
display ""
display ""
}
else if("`check'" == "check") {
flowchart_hline
flowchart_header "DEBUG CHECK"
flowchart_debugcheck
flowchart_footer
flowchart_hline
}
else if("`logreset'" == "logreset") {
capture log close DebugLog
if(_rc) {
display as error "DebugLog could not be closed."
display _rc
}
else {
display "...DebugLog Closed."
display ""
flowchart_footer "DEBUG LOG RESET" // Close just the log without turning off $Flowchart_Debug
}
}
else if("`close'" == "close") {
global Flowchart_Debug = "off"
capture log close DebugLog // Close the log and also turn off $Flowchart_Debug
if(_rc) {
display as error "Could not close DebugLog."
}
else {
display "...DebugLog Closed."
display ""
flowchart_footer "DEBUG MODE: OFF"
display ""
}
}
else if("`info'" == "info") {
display ""
flowchart_hline
flowchart_header "DEBUG INFO"
display ""
flowchart_subtitle "Debug Options"
display ""
display "1. To Debug Code:" _newline
display " Turn Debugging Mode On: "
display " . {stata flowchart debug on:flowchart debug on}"
display " Use this at the start of code that produces errors." _newline
display " Turn Debugging Mode Off: "
display " . {stata flowchart debug off:flowchart debug off}"
display " Use this at the end of code that produces errors." _newline
display " This will generate DebugLog.log in your working directory with debugging information." _newline
display "2. To Get Environment Information: "
display " . {stata flowchart debug check:flowchart debug check}"
display " This will give you versioning information on Stata, the flowchart package, and dependencies installed." _newline
display "3. To Debug TikZ Code: "
display " . {stata flowchart debug tikz:flowchart debug tikz}"
display " This will insert debugging information into the TikZ code." _newline
display "4. To Uninstall Flowchart: "
display " . {stata flowchart setup, uninstall:flowchart setup, uninstall}"
display " This will uninstall the flowchart package. The dependencies will remain." _newline
display "Read this message again at anytime by typing '{stata flowchart debug info:flowchart debug info}'"
flowchart_footer
flowchart_hline
}
else if("`deletefiles'" == "deletefiles") {
if("`yes'" == "yes") {
flowchart_debugdeletefiles
}
else {
display "Are you sure you want to delete the ancillary files in the current working directory?"
display " {stata flowchart debug deletefiles yes: Yes}"
}
}
else {
if("$Flowchart_Debug" == "on") {
flowchart debug off
}
else if("$Flowchart_Debug" == "off") {
flowchart debug on
}
else {
flowchart debug info
}
}
end
capture program drop flowchart_debugdeletefiles
program define flowchart_debugdeletefiles
* DeleteFiles - This deletes the ancillary files from the current working directory - Use with caution.
capture rm methods--figure-flowchart.tex
capture rm methods--figure-flowchart.data
capture rm methods--figure-flowchart.tikz
capture rm manuscript.tex
capture rm license.txt
capture rm figure-flowchart.texdoc
capture rm example1output.pdf
capture rm example2output.pdf
capture rm flowchart_example1.do
capture rm flowchart_example2.do
display ""
display " ...Ancillary Files Deleted."
end
capture program drop flowchart_debugcheck
program define flowchart_debugcheck
display ""
* Machine Inforation:
flowchart_subtitle "Machine"
display ""
display " [Operating System]"
display "`c(os)'"
display " [Machine Type]"
display "`c(machine_type)'"
display ""
* Stata Version Information:
flowchart_subtitle "Stata"
display ""
display " [Version]"
version // Returns the STATA Version #
display ""
display " [ADO Directory]"
capture noisily net query
display ""
* Dependencies - Check Presence & Give Version #'s:
flowchart_subtitle "Dependency Check"
display ""
display " 1. [Flowchart Package]"
capture noisily which flowchart
if(_rc) {
display as error "Package 'flowchart' likely uninstalled itself. Please try reinstalling the package again."
exit 111
}
capture noisily ado dir flowchart
if(_rc) {
display as error "ADO Directory could not be returned for the 'flowchart' package."
exit 111
}
display ""
display " 2. [TexDoc Package]"
capture noisily which texdoc
if(_rc) {
display as error "Package 'texdoc' is required by the flowchart package. Please run command 'flowchart setup' and try again."
exit 111
}
display ""
display " 3. [SJLatex]"
capture noisily which sjlatex
if(_rc) {
display as error "Package 'sjlatex' is required by the 'texdoc' package. Please run command 'flowchart setup' and try again."
exit 111
}
display ""
end
capture program drop flowchart_init
program define flowchart_init
flowchart_writevar, name("set_dummy") value("null") // Set dummy variable since the first variable is not recognized by texdoc.
flowchart_writevar, name("set_draw") value("black")
flowchart_writevar, name("set_fill") value("white")
flowchart_writevar, name("set_center_textwidth") value("18em")
flowchart_writevar, name("set_center_textalign") value("centered")
flowchart_writevar, name("set_center_minheight") value("4em")
flowchart_writevar, name("set_left_textwidth") value("21em")
flowchart_writevar, name("set_left_textalign") value("ragged")
flowchart_writevar, name("set_left_minheight") value("4em")
flowchart_writevar, name("set_left_innersep") value("6pt")
/* To Do: Future Releases: Implement row-options - 'flowchart writerow(rowname,rowoption): ...' -- Allow noborder, assign, and lost-style boxes.
flowchart_writevar, name("set_noborder_textwidth") value("18em")
flowchart_writevar, name("set_noborder_textalign") value("centered")
flowchart_writevar, name("set_noborder_minheight") value("1em")
flowchart_writevar, name("set_noborder_draw") value("none")
flowchart_writevar, name("set_noborder_fill") value("none")
flowchart_writevar, name("set_assign_textwidth") value("18em")
flowchart_writevar, name("set_assign_textalign") value("ragged")
flowchart_writevar, name("set_assign_minheight") value("3em")
flowchart_writevar, name("set_assign_innersep") value("6pt")
flowchart_writevar, name("set_lost_textwidth") value("16em")
flowchart_writevar, name("set_lost_textalign") value("ragged")
flowchart_writevar, name("set_lost_minheight") value("3em")
flowchart_writevar, name("set_lost_innersep") value("6pt")*/
end
capture program drop flowchart_writevar
program define flowchart_writevar
syntax [anything] [, name(string) value(string) *]
local variablerow "`name' = `value'"
file write FlowchartFile "`variablerow'" _n
if(substr("`name'",1,4) == "set_") {
global Flowchart_Settings = `"$Flowchart_Settings @`name'"'
global Flowchart_Settings = `"$Flowchart_Settings "`value'""'
}
end
capture program drop flowchart_tdfinalize
program define flowchart_tdfinalize
syntax , template(string) output(string)
***\\ TIKZ PICTURE: Write the TikZ Picture to the file.
if("$Flowchart_Debug" == "on") {
display "`template' `output'"
}
texdoc do "`template'", init("`output'") replace
* Important Note: The '.tikz' extension here is important since if it is not specified, calling 'texdoc do' in the Main Analysis Do File will overwrite the .tex file of the same name in the same directory.
texdoc close
end
capture program drop flowchart_tdwrite_blockfield
program define flowchart_tdwrite_blockfield
syntax [anything] [, indent]
global Flowchart_IteratorBlockfields = $Flowchart_IteratorBlockfields + 1
.blockfields.list[$Flowchart_IteratorBlockfields] = `"`1'"'
if("$Flowchart_Debug" == "on") {
display "1=|`1'|, 2=|`2'|, 3=|`3'| indent=|`indent'|"
}
* texdoc write "`varname'"
end
capture program drop flowchart_tdwrite_pathfield
program define flowchart_tdwrite_pathfield
syntax [anything] [, indent]
global Flowchart_IteratorPathfields = $Flowchart_IteratorPathfields + 1
.pathfields.list[$Flowchart_IteratorPathfields] = `"`1'"'
if("$Flowchart_Debug" == "on") {
display "1=|`1'|, 2=|`2'|, 3=|`3'| indent=|`indent'|"
}
* texdoc write "`varname'"
end
capture program drop flowchart_tdwriteline
program define flowchart_tdwriteline
syntax [anything] [, indent lead(string) singleton end endblank newrow name(string) num(string) desc(string)]
if("`lead'" != "") {
if("`singleton'" != "") {
if("`end'" != "") {
if("`endblank'" != "") {
local addrowskip = "true"
}
local linestring = `"`lead'`desc' (n=\figvalue{`name'})}; \\"' // Usually, a left-block that has only 1 line (a singleton) when the center-block was blank.
}
else {
local linestring = `"`lead'`desc' (n=\figvalue{`name'})}; "'
}
}
else {
local linestring = `"`lead'`desc' (n=\figvalue{`name'}): \\"'
}
}
else {
* Determine ending first (suffix)
if("`end'" != "") {
if("`newrow'" != "") {
if("`endblank'" != "") {
local suffix = "}; \\" // Add Row-Skip: + " & \\"
local addrowskip = "true"
}
else {
local suffix = "}; \\"
}
}
else {
local suffix = "};" // No New Row (i.e., it is the first block/center block, so don't print \\ at the end).
}
}
else {
local suffix = "\\"
}
if("`indent'" != "") {
local linestring = `" \h\h \figvalue{`name'} `desc' `suffix'"'
}
else {
local linestring = `" \h `desc' (n=\figvalue{`name'}) `suffix'"'
}
}
if("$Flowchart_Debug" == "on") {
display `"Blockfield Linestring: `linestring'"'
}
global Flowchart_IteratorBlockfields = $Flowchart_IteratorBlockfields + 1
.blockfields.list[$Flowchart_IteratorBlockfields] = `"`linestring'"'
if("`addrowskip'" == "true") {
global Flowchart_IteratorBlockfields = $Flowchart_IteratorBlockfields + 1
.blockfields.list[$Flowchart_IteratorBlockfields] = `" & \\"'
global Flowchart_IteratorBlockfields = $Flowchart_IteratorBlockfields + 1
.blockfields.list[$Flowchart_IteratorBlockfields] = `" % -- Blank Left Block"'
macro drop addrowskip // Guarantee this is deleted from memory and only happens when it is supposed to happen.
if("$Flowchart_Debug" == "on") {
display `"Blockfield Linestring: & \\"'
display `"Blockfield Linestring: % -- Blank Left Block"'
}
}
*flowchart_tdwrite_blockfield `"`linestring'"'
* texdoc write "`varname'"
end
capture program drop flowchart_header
program define flowchart_header
syntax [anything]
if ("`1'" != "") {
local text = "`1'"
}
else {
local text = "FLOWCHART"
}
display "{bf:|||||| `text'}"
end
capture program drop flowchart_footer
program define flowchart_footer
syntax [anything]
if ("`1'" != "") {
local text = "`1'"
}
else {
local text = "FLOWCHART"
}
display "{bf:|||||| `text'}"
end
capture program drop flowchart_hline
program define flowchart_hline
display "{hline}"
end
capture program drop flowchart_subtitle
program define flowchart_subtitle
syntax [anything]
display `" {title:`1'}:"' // Requirement: Quotes around text. Safer to use quotes with input to avoid unusual errors rather than compound quotes.
end
capture program drop flowchart_title
program define flowchart_title
syntax [anything] [, num(string)]
if("`num'" == "") {
local num = floor((5-1+1)*runiform() + 1)
}
* Based on ASCII Generated from: http://www.network-science.de/ascii/
* Citation: Seyfferth, Jorg. (19 Feb. 2011.). Imprint / Impressum. Network-science.de. Retrieved from http://www.network-science.de/impressum.html
* larry3d
display "" // New Line - Before Title
if("`num'" == "1") {
display " ___ ___ __ __ "
display " /'___\/\_ \ /\ \ /\ \__ "
display " /\ \__/\//\ \ ___ __ __ __ ___\ \ \___ __ _ __\ \ ,_\ "
display " \ \ ,__\ \ \ \ / __\`\/\ \/\ \/\ \ /'___\ \ _ \`\ /'__\`\ /\\`'__\ \ \ \ "
display " \ \ \_/ \_\ \_/\ \_\ \ \ \_/ \_/ \/\ \__/\ \ \ \ \/\ \_\.\_\ \ \/ \ \ \_ "
display " \ \_\ /\____\ \____/\ \___ ___/'\ \____\\ \_\ \_\ \__/.\_\\ \_\ \ \__\ "
display " \/_/ \/____/\/___/ \/__//__/ \/____/ \/_/\/_/\/__/\/_/ \/_/ \/__/ "
}
* ogre
else if("`num'" == "2") {
display " __ _ _ _ "
display " / _| | _____ _____| |__ __ _ _ __| |_ "
display "| |_| |/ _ \ \ /\ / / __| '_ \ / _\` | '__| __| "
display "| _| | (_) \ V V / (__| | | | (_| | | | |_ "
display "|_| |_|\___/ \_/\_/ \___|_| |_|\__,_|_| \__| "
}
* slant
else if("`num'" == "3") {
display " ______ __ __ "
display " / __/ /___ _ _______/ /_ ____ ______/ /_ "
display " / /_/ / __ \ | /| / / ___/ __ \/ __ \`/ ___/ __/ "
display " / __/ / /_/ / |/ |/ / /__/ / / / /_/ / / / /_ "
display " /_/ /_/\____/|__/|__/\___/_/ /_/\__,_/_/ \__/ "
}
* smslant
else if("`num'" == "4") {
display " _____ __ __ "
display " / _/ /__ _ ______/ / ___ _____/ /_ "
display " / _/ / _ \ |/|/ / __/ _ \/ _ \`/ __/ __/ "
display " /_//_/\___/__,__/\__/_//_/\_,_/_/ \__/ "
}
* speed
else if("`num'" == "5") {
display " _____________ ______ _____ "
display " ___ __/__ /________ __________ /_______ _________ /_ "
display " __ /_ __ /_ __ \_ | /| / / ___/_ __ \ __ \`/_ ___/ __/ "
display " _ __/ _ / / /_/ /_ |/ |/ // /__ _ / / / /_/ /_ / / /_ "
display " /_/ /_/ \____/____/|__/ \___/ /_/ /_/\__,_/ /_/ \__/ "
}
display "" // New Line - After Title
end