-
Notifications
You must be signed in to change notification settings - Fork 0
/
poster.hs
executable file
·1434 lines (1251 loc) · 65 KB
/
poster.hs
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
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{-# LANGUAGE NoMonomorphismRestriction #-}
-- {-# LANGUAGE TypeFamilies #-}
-- to generate the poster:
-- ghc --make poster.hs
-- ./poster -o poster.pdf -w 1685 or
-- ./poster -o poster.png -w 10000 (to generate a png with width 10000)
-- to understand the code, go to http://projects.haskell.org/diagrams/manual/diagrams-manual.html
-- expected format: Din A1: 594 x 841
-- or Din A0: 841 x 1189 mm (sqrt 2 / 1)
import Diagrams.Prelude
import Diagrams.Backend.Cairo.CmdLine
-- import Diagrams.Backend.SVG.CmdLine
import Data.Word
import Graphics.SVGFonts
import qualified Diagrams.TwoD.Size as Size
import Text.Highlighting.Kate
import Data.Tree
import Data.Colour hiding (atop)
import Data.Maybe
import Paths_unixPoster(getDataFileName)
import Data.Either
main = do
folderImg <- getDataFileName "img/folder.png"
filesImg <- getDataFileName "img/files.png"
pdp7 <- getDataFileName "img/pdp7_3.png"
let imagePaths = [folderImg,filesImg,pdp7]
possibleImages <- mapM loadImageExt imagePaths
let loadedImages = rights possibleImages
let diagramImages = map imageToDiagram loadedImages
let diagram = unixPoster diagramImages
mainWith diagram
imageToDiagram :: DImage Double External -> QDiagram Cairo V2 Double Any
imageToDiagram imageData = image imageData
--------------------------------------------------
-- basic building blocks of the diagram
--------------------------------------------------
unixPoster images
= {-# SCC "poster" #-} strutY 3 ===
header # centerXY
=== strutY 4 ===
poster_portrait images # centerXY -- poster_body
# applyAll (map linesToLProcessing
["wc","cut","grep","head","tail","tee","more","less","sort","uniq","tr","rev"]) # centerXY
# applyAll (map toLines ["find","tree","ls","cat"]) # centerXY
# applyAll (map toSeveralFilesInput ["cmp","diff"]) # centerXY
# applyAll (map folderToChild ["ls","mkdir","rmdir","cd","tree","pwd","cp","mv","find"]) # centerXY
# applyAll (map filesToChild ["ls","cp","mv","chmod","cat","touch","rm","ln","stat"]) # centerXY
# applyAll (map pipingExample [("pwd", "piping7"), ("piping7", "rev"), ("piping7", "cut"),
("ls", "piping0"), ("piping0", "wc"),
("piping1", "ps"), ("piping1","head"),
("piping2", "ps"), ("piping2", "wc"),
("piping3", "ps"), ("piping3", "grep"),
("piping4", "history"), ("piping4", "grep"),
("piping5", "ps"), ("piping5", "less"),
("piping6", "history"), ("piping6", "grep"), ("piping6","cut"),
("piping8", "ls"), ("piping8", "grep"),
("redir1", "ps"),
("redir2", "date"),
("find", "redir3"),-- ("redir3", "outputRedirection"),
("find", "redir4"),-- ("redir4", "outputRedirection"),
("grep", "redir5"),("redir5", "outputRedirection"),
("find", "redir6")-- ,("redir6", "outputRedirection")
])
===
scriptingH # centerXY -- scriptingV
===
strutY 2
===
copyright # centerXY
===
strutY 2
-- connections = {-# SCC "connections" #-}
poster_body [folder,fil,pdp7] = ((input folder fil) ||| strutX 3 ||| commandBodyL) |||
( (outp ||| strutX 5 ||| commandBodyM ||| redirection ||| commandBodyR ||| strutX 3)
===
(scriptingV ||| strutX 3 ||| dollarOps ||| strutX 3 ||| (files pdp7))
)
poster_portrait [folder,fil,pdp7] = ((input folder fil) ||| strutX 3 ||| ( (commandBodyL ||| (outp
=== strutY 2 ===
redirection))
===
((files pdp7) ||| strutX 3 ||| dollarOps) )
)
||| strutX 5 |||
(commandBodyM === strutY 5 === commandBodyR)
folderToChild child
= withName "folder" $ \rb ->
withName child $ \cb ->
( flip atop ( fromMaybe origin (traceP (location rb) unit_X rb)
~~~ fromMaybe origin (traceP (location cb) unitX cb) # lc salmon) )
filesToChild child
= withName "files" $ \rb ->
withName child $ \cb ->
flip atop ( fromMaybe (location rb) (traceP (location rb) unit_X rb)
~~~ fromMaybe (location cb) (traceP (location cb) unitX cb) # lc seagreen)
toSeveralFilesInput child
= withName "twoFiles" $ \rb ->
withName child $ \cb ->
flip atop ( fromMaybe origin (traceP (location rb) unit_X rb)
~~~ fromMaybe origin (traceP (location cb) unitX cb) # lc silver # opacity 0.8)
linesToLProcessing child
= withName "lines" $ \rb ->
withName child $ \cb ->
flip atop ( fromMaybe origin (traceP (location rb) unit_X rb)
~~~ fromMaybe origin (traceP (location cb) unitX cb) # lc plum # opacity 0.2)
toLines child
= withName child $ \rb ->
withName "lines" $ \cb ->
flip atop ( fromMaybe origin (traceP (location rb) unit_X rb)
~~~ fromMaybe origin (traceP (location cb) unitX cb) # lc plum # opacity 0.2)
pipingExamples (box0,boxes) = mconcat $ map (pipingExample box0) boxes
pipingExample (from, to)
= withName from $ \rb ->
withName to $ \cb ->
flip atop ( fromMaybe origin (traceP (location rb) unit_X rb)
~~~ fromMaybe origin (traceP (location cb) unitX cb) # lc silver)
-- connect two points with a bezier curve horizontally
p1 ~~~ p2 = (stroke $ translate (p1 .-. origin) $ pathFromTrail segs) # lwL 0.4
where c1 = p1 .+^ (r2 (3,0))
c2 = p2 .+^ (r2 (-3,0))
segs = fromSegments [bezier3 (c1 .-. p1) (c2 .-. p1) (p2 .-. p1)]
header = (textLin "UNIX - Commands" 10 black) # alignBR
input folderImg filesImg = (strutY 15
===
i # centerXY
=== strutY 35 ===
folder # centerXY
===
folderPic folderImg # named "folder"
=== strutY 70 ===
files # centerXY
===
filesPic filesImg # named "files"
=== strutY 33 ===
h # centerXY
=== strutY 2 ===
twoFilesIcon # named "twoFiles" # centerXY
) # alignTL
where
i = textLin "Input" 4 black # alignBR
folder = textLin "Directories" 3 black # alignBR
files = textLin "Files" 3 black # alignBR
h = textLin "Two Files" 3 black # alignBR
folderPic f = f # scaleUToX 10
inputRedirection = textBox ["InputRedirection"] 2 white red 0.3 # centerXY
filesPic f = f # scaleUToX 10
linesIcon = textBox ["------","------","------","------"] 1 white blue 0.3
twoFilesIcon = linesIcon ||| strutX 1 ||| linesIcon
commandBodyL = fileSystem # alignTL
fileSystem = {-# SCC "fileSystem" #-} groupedCommands "File System" 120 230
[unix_cd , unix_pwd, unix_mkdir, unix_rmdir, unix_find ||| strutX 3 ||| ( redir_Example3 # centerXY # named "redir3"
=== strutY 1 ===
redir_Example4 # centerXY # named "redir4"
=== strutY 1 ===
redir_Example6 # centerXY # named "redir6"
) # alignTL,
unix_tree, unix_ls, unix_cp, unix_mv, unix_cat, unix_echo,
(unix_chmod ||| unix_permissions),
unix_touch, unix_rm, unix_ln, unix_stat, unix_cmp, unix_diff, unix_df, unix_du -- , unix_quota # named "quota"
]
outp = ( i # centerXY
=== strutY 2 ===
piping # centerXY # named "piping"
=== strutY 4 ===
piping_Example7 # centerXY # named "piping7"
=== strutY 4 ===
piping_Example0 # centerXY # named "piping0"
=== strutY 4 ===
piping_Example2 # centerXY # named "piping2"
=== strutY 4 ===
piping_Example3 # centerXY # named "piping3"
=== strutY 4 ===
piping_Example1 # centerXY # named "piping1"
=== strutY 4 ===
g # centerXY
=== strutY 2 ===
linesIcon # centerXY # named "lines"
=== strutY 5 ===
piping_Example4 # centerXY # named "piping4"
=== strutY 5 ===
piping_Example5 # centerXY # named "piping5"
=== strutY 5 ===
piping_Example6 # centerXY # named "piping6"
) # alignTL
where
i = textLin "Output/Input" 4 black # alignBR
g = textLin "File/Lines" 3 black # alignBR
commandBodyM = lineProcessing # alignTL
lineProcessing = groupedCommands "Processing of Lines" 95 160
[unix_rev, unix_wc, unix_cut, unix_grep, unix_tee,
unix_head ||| strutX 1 ||| unix_tail,
unix_more, unix_less, unix_sort, unix_uniq, unix_tr
]
redirection = (
strutY 10
===
i # centerXY
=== strutY 2 ===
redir # centerXY # named "outputRedirection"
=== strutY 5 ===
redir_Example0 # centerXY # named "redir0"
=== strutY 5 ===
redir_Example1 # centerXY # named "redir1"
=== strutY 5 ===
redir_Example2 # centerXY # named "redir2"
=== strutY 5 ===
inpRedirection_Example # centerXY
) # alignTL
where i = textLin "Output Redirection" 4 black # alignBR
commandBodyR = processes # alignTL
processes = groupedCommands "Processes and OS" 95 150
[unix_ps,
unix_top,unix_and,unix_jobs,unix_bg,unix_fg,unix_fork,unix_exec,unix_exit,unix_wait,
unix_kill,unix_killall,unix_sudo,unix_su,unix_finger,unix_who,unix_which,
unix_env ||| strutX 1 ||| unix_man ||| strutX 1 ||| unix_info,
unix_date ||| strutX 1 ||| unix_cal ||| strutX 1 ||| unix_free ||| strutX 1 ||| unix_uptime ||| strutX 1 ||| unix_clear,
unix__exit ||| unix_sleep, unix_history]
copyright = -- (textBit "\x00a9" 6 black # alignBR) ||| strutX 2 |||
(textLin "Generated with the Haskell diagrams library" 4 black)
scriptingV = (header === strutY 1 === ((scripting0
===
strutY 1
===
scripting1
===
strutY 1
===
scripting2
===
strutY 1
===
scripting3) # centerXY ) ) # alignTL
where
header = textLin "Scripting" 5 black # centerXY
scriptingH = (header === strutY 3 === (scripting0
||| strutX 1 |||
scripting1
||| strutX 1 |||
(scripting2
===
strutY 1
===
scripting3) ) # centerXY )
where
header = textLin "Scripting" 5 black # centerXY
files i = strutX 2 ||| (header === strutY 3 === (((drawTreeDiagram (fileSystemTree2 blue)) # centerXY) `atop` im)) # alignTL
where
header = textLin "Files and Directories" 5 black # centerXY
im = i # scaleUToX 90
redir = textBoxWithHeader
"Output Redirection"
["of the channels",
"stdout = 1,",
"stderr = 2:",
"> Redirect stdout",
"2> Redirect stderr",
"2>&1 Redirect stderr",
" to stdout",
">> Append to stdout",
"2>&1 | Pipe stdout and",
" stderr to",
" another command" ] 2 white indianred # alignTL
redir_Example0 = textBoxWithHeader
"echo \"Obama\" > president"
["writes to file 'president'",
"instead of the screen"
] 1.75 white indianred # alignTL
redir_Example1 = textBoxWithHeader
"ps -ef > procList"
["the table showing all",
"processes is output to",
"file 'procList'"
] 2 white indianred # alignTL
redir_Example2 = textBoxWithHeader
"date >> procList"
["current date and time",
"is appended at the end",
"of file 'procList'"
] 2 white indianred # alignTL
redir_Example3 = textBoxWithHeader
"find peanuts 2> badReport"
["the errors - if any - resulting",
"from searching for peanuts are",
"output to file 'badReport'",
"instead of the screen",
"at the end of file 'procList'"
] 2 white indianred # alignTL
redir_Example4 = textBoxWithHeader
"find peanuts 1> result 2> badReport"
["the output from searching for",
"peanuts are written into file",
"'result' and the errors - if any",
" - to file 'badReport' instead ",
"of the screen"
] 2 white indianred # alignTL
redir_Example5 = textBoxWithHeader
"grep 0.5 integers 2> /dev/null"
["sends the error report to /dev/null",
"- the system's \"black hole\" -",
"instead of printing it to the screen"
] 2 white indianred # alignTL
redir_Example6 = textBoxWithHeader
"find peanuts 2>> failures 1>> found"
["the output from searching for",
"peanuts are appended to file 'found'",
"and the errors - if any - to file",
"'failures' instead of being printed",
"to the screen"
] 2 white indianred # alignTL
inpRedirection_Example = textBoxWithHeader
"Input Redirection"
[ "while read x; do",
"echo -e $(wc -w $x)",
"done < fileToBeRead",
"the content of file",
"'fileToBeRead' is used",
"as input for 'read x',",
"thus allowing to process",
"'fileToBeRead' line-by-line"
] 2 white indianred
piping = textBoxWithHeader
"Piping"
["The output of","one command",
"becomes the input","of the other"] 2 white grey # alignTL
piping_Example0 = textBoxWithHeader
"ls | wc -w"
["counts the files/directories",
"contained in the current",
"directory"
] 2 white grey # alignTL
piping_Example1 = textBoxWithHeader
"ps -e | head"
["displays the first 10 lines",
"of the table that shows all",
"processes"
] 2 white grey # alignTL
piping_Example2 = textBoxWithHeader
"ps -e | wc -l"
["counts the number of rows in",
"the table that shows all",
"processes"
] 2 white grey # alignTL
piping_Example3 = textBoxWithHeader
"ps -e | grep bash"
["shows all processes that",
"are shells"
] 2 white grey # alignTL
piping_Example4 = textBoxWithHeader
"history | grep \"|\""
["shows all commands in the",
"history that involved piping"
] 2 white grey # alignTL
piping_Example5 = textBoxWithHeader
"ps -e | less"
["displays the table that shows",
"all processes in a scrollable",
"view"
] 2 white grey # alignTL
piping_Example6 = textBoxWithHeader
"history | grep \"|\" | cut -d \"|\" -f2"
[ "shows all commands",
"behind a (first) pipe"
] 1.5 white grey # alignTL
piping_Example7 = textBoxWithHeader
"pwd | rev | cut -d \"/\" -f1 | rev"
["displays the name of the current",
"directory without the leading path"
] 1.5 white grey # alignTL
piping_Example8 = textBoxWithHeader
"ls -l | grep -v ^-"
["displays all contents of the current",
"directory that are not regular files"
] 2 white # fc grey # alignTL
--------------------------------------------------
-- helper functions for the layout
--------------------------------------------------
--
groupedCommands txt w h commands = (((header # centerXY === strutY 5 === commandRows # centerXY) # alignTL) `atop` roundedBox)
# centerXY # pad 1.05 # alignBL # lc black # fc black
-- `atop` roundedBox
where
-- placing commands below each other
header = textLin txt 5 black # alignBL
commandRows = vcat' (with & sep .~ 1) commands # alignTL
roundedBox = (roundedRect width hhh 2) # alignTL # fc grey # lc grey # opacity 0.2
width = w -- Size.width (placedCommands :: D R2)
hhh = h -- Size.height (placedCommands :: D R2)
command t = textBox [t] 2 black red 0.3 # centerXY # named t # alignTL
description t | null t = mempty
| otherwise = textBox2 t 2 black blue # alignTL
c_option op comment | null op = mempty
| (length op) + (length comment) > 100 = (textBox [op] 1.5 black green 0.3)
===
(textBox2 [comment] 1.7 black white)
| otherwise = (textBox [op] 1.5 black green 0.3)
|||
(textBox2 [comment] 1.7 black white)
-- command and options aligned from left to right
-- command description [ (Option, Example output from this option) ]
commandWOptions c d ops = commandBox c d (map optAndOutput ops)
-- command and for every option a new line
commandVerticalOptions c d ops = commandVBox c d (map vOptAndOutput ops)
commandDescriptionExample c d lines = c ||| d ||| (terminal lines 1.5)
-- commandBox :: Diagram b -> Diagram b -> [Diagram b] -> Diagram b
commandBox c d opts = (c ||| d) === placedOptions # fc red # lc red
where
placedOptions = hcat' (with & sep .~ 0.5) opts
-- commandVBox :: V b ~ V2 => Diagram b -> Diagram b -> [Diagram b] -> Diagram b
commandVBox c d opts = (c ||| d) === placedOptions # fc red # lc red
where
placedOptions = vcat' (with & sep .~ 0.5) opts
-- textbox with example code below the option
optAndOutput (opt,lines) | (length lines) <= 3 = strutX 1 ||| (opt === (terminal lines 1.5)) # centerXY # pad 1.02 # alignTL
| otherwise = strutX 1 ||| (opt === (terminal lines 1)) # centerXY # pad 1.02 # alignTL
vOptAndOutput (opt,lines) | (length lines) <= 3 = strutX 1 ||| (opt ||| ((terminal lines 1.5) # alignTL ) ) # alignTL
| otherwise = strutX 1 ||| (opt ||| ((terminal lines 1) # alignTL ) ) # alignTL
fancyRoundedBox w h hh c = ( (roundedRect (w-0.4-size*0.04) (hh-0.4-size*0.04) (h/5)) # centerXY # lwL 0 # fc (blend 0.5 c white)
`atop`
(roundedRect w hh (h/5)) # centerXY # lwL 0 # fc (blend 0.5 c black) ) # alignTL # opacity 0.7
where size | w > hh = hh
| otherwise = w
-- reduce the size of an object by len in all directions
border hrel w h obj | w > len && h > len = obj # scaleX ((w-len)/w)
# scaleY ((h-len)/h)
# translateX (len/2)
# translateY (-len/2)
| otherwise = obj
where len = hrel*h
terminal lines h = (border 0.3 w hh placedTextLines) `atop` roundedBox
where
-- placing textLines below each other
placedTextLines = vcat' (with & sep .~ h/5) textLines # alignTL # lc white # fc white
textLines = map (\t -> (textBit t h white) # alignTL) lines
roundedBox = (roundedRect w hh 0.5) # alignTL # lc black # fc black -- # opacity 0.5
w = Size.width (placedTextLines :: D V2 Double)
hh = Size.height (placedTextLines :: D V2 Double)
textBox lines h c0 c1 b = (border b w hh placedTextLines) `atop` roundedBox
where
-- placing textLines below each other
placedTextLines = vcat' (with & sep .~ h/5) textLines # alignTL
textLines = map (\t -> (textBit t h c0) # alignTL) lines
roundedBox = fancyRoundedBox w h hh c1
w = Size.width (placedTextLines :: D V2 Double)
hh = Size.height (placedTextLines :: D V2 Double)
textBox2 lines h c0 c1 = (border 0.3 w hh placedTextLines) `atop` roundedBox
where
-- placing textLines below each other
placedTextLines = vcat' (with & sep .~ h/5) textLines # alignTL
textLines = map (\t -> (textLin t h c0) # alignTL) lines
roundedBox = fancyRoundedBox w h hh c1
w = Size.width (placedTextLines :: D V2 Double)
hh = Size.height (placedTextLines :: D V2 Double)
textBoxWithHeader line lines h c0 c1 = (border 0.3 w hh placedTextLines) `atop` roundedBox
where
-- placing textLines below each other
placedTextLines = ((textBit line h black # centerXY) === (vcat' (with & sep .~ h/5) textLines # centerXY)) # alignTL
textLines = map (\t -> (textBit t h c0) # alignTL) lines
roundedBox = fancyRoundedBox w h hh c1
w = Size.width (placedTextLines :: D V2 Double)
hh = Size.height (placedTextLines :: D V2 Double)
highlightedText code h c lang = (border 0.15 w hh placedTextLines) `atop` roundedBox
where
-- placing textLines below each other
placedTextLines = vcat' (with & sep .~ h/5) textLines # alignTL
textLines = map l hlines # alignTL
l line = hcat' (with & sep .~ 0.1) (map token line)
token (CommentTok,str) = textBit str h blue # fc blue # alignBR
token (KeywordTok,str) = textBit str h red # fc blue # alignBR
token (FloatTok,str) = textBit str h orange # fc blue # alignBR
token (CharTok,str) = textBit str h violet # fc blue # alignBR
token (StringTok,str) = textBit str h violet # fc blue # alignBR
token (FunctionTok,str) = textBit str h black # fc blue # alignBR
token (_,str) = textBit str h grey # fc blue # alignBR
roundedBox = (roundedRect w hh (h/5)) # alignTL # opacity 0.3
w = Size.width (placedTextLines :: D V2 Double)
hh = Size.height (placedTextLines :: D V2 Double)
hlines :: [SourceLine]
hlines = map concat $ map (highlightAs lang) code
textBit t h c | null t = mempty
| otherwise = {-# SCC "textBit" #-} textSVG_ (TextOpts bit INSIDE_H HADV False 1 h) t # fc c # lc c
# lwL 0.1 # fillRule EvenOdd
textLin t h c | null t = mempty
| otherwise = {-# SCC "textLin" #-} textSVG_ (TextOpts lin INSIDE_H HADV False 1 h) t # fc c # lc c
# lwL 0.1 # fillRule EvenOdd
----------------------------------------------------------------------------------------------------------
-- detailed content, generated with the helper functions
----------------------------------------------------------------------------------------------------------
---------------
-- filesystem
---------------
unix_echo = commandWOptions (command "echo") (description ["display a line of text"])
[(c_option "-n" "do not output the trailing newline", []),
(c_option "-e" "enable interpreatation of backslash escapes", [])]
unix_ls = commandWOptions (command "ls") (description ["list content of directories"])
[(c_option "-l" "detailed output",["drwxr-xr-x 11 rod rod 12288 Jun 23 13:33 Downloads",
-- "-rw-r--r-- 1 rod rod 179 Nov 9 2011 examples.desktop",
"drwxrwxr-x 3 rod rod 4096 May 8 23:23 workspace",
"-rw-rw-r-- 1 rod rod 481 Feb 18 12:12 X.ini"]),
(c_option "-a or --a" "list all (also hidden files)",[
"-rw-r--r-- 1 rod rod 179 Nov 9 2011 .config",
"drwxr-xr-x 11 rod rod 12288 Jun 23 13:33 Downloads",
"-rw-r--r-- 1 rod rod 179 Nov 9 2011 examples.desktop",
"drwxrwxr-x 3 rod rod 4096 May 8 23:23 workspace",
"-rw-rw-r-- 1 rod rod 481 Feb 18 12:12 X.ini"]),
(c_option "-i" "prints inode number",["1594379 bin",
"1594488 Deleted",
"1594382 file2",
"1594330 films"]),
(c_option "-R" "list subdirectories' contents recursively",
[".:",
"bin deleted file2 films",
-- "./bin:aravind colour jace raman reader",
"./deleted:dir1 dir2 dir3 file1 file2 file3 list.txt",
"./deleted/dir1: ",
"./deleted/dir2: dir",
-- "./deleted/dir2/dir: ",
-- "./deleted/dir3: ",
"./films:action comedy horror",
"./films/action:firstBlood",
-- "./films/comedy:supernaturalComedy",
-- "./films/comedy/supernaturalComedy:ghostbusters ghostbusters2",
-- "./films/horror:slasher zombie",
-- "./films/horror/slasher:halloween",
"./films/horror/zombie:28DaysLater predator"])]
unix_cat = commandWOptions (command "cat") (description ["concatenate file contents and print them on the screen"])
[(c_option "-E" "end each line with $",
["Remember, remember$",
"The fifth of November!$",
"Gunpowder, treason, and plot.$",
"I see no reason why the gunpowder treason$",
"should ever be forgot.$"]), (c_option "-s" "only the first one of repeated empty lines is printed",["#!/bin/bash",
"",
"clear",
"while [ true ]; do",
" sleep 1",
" echo -e \"I am the shit!\"",
"done",
"",
"echo -e \"I stopped being the shit.\""]),
(c_option "-n" "numbers the lines printed",
["1 Remember, remember",
"2 The fifth of November!",
"3 Gunpowder, treason, and plot.",
"4 I see no reason why the gunpowder treason",
"5 should ever be forgot."])]
unix_touch = commandDescriptionExample (command "touch")
(description ["creates new files"])
["touch file{1,2,3}","ls","file1 file2 file3"]
unix_mkdir = commandWOptions (command "mkdir") (description ["creates directories"])
[(c_option "-p" "creates directories with parent directories in one go", []),
(c_option "-v" "print a message for each creatad directory (to stderr)", [])]
unix_rmdir = commandWOptions (command "rmdir") (description ["deletes directories if they are empty"])
[(c_option "-p" "removes directories and their empty subdirectories in one go", []),
(c_option "-v" "output a diagnostic for every directory processed", [])]
unix_cd = commandDescriptionExample (command "cd") (description ["change to directory"]) ["cd ~ # change to the home directory"]
unix_rm = commandWOptions (command "rm") (description ["deletes files"])
[(c_option "-r" "deletes directories and their contents/subdirectories recursively", []),
(c_option "-i" "asks before every deletion", []),
(c_option "-v" "explain what is being done", [])]
unix_cp = commandWOptions (command "cp") (description ["copies files"])
[(c_option "-r" "copies directories and their contents/subdirectories recursively", []),
-- (c_option "-s" "results are not copies but symbolic links", []),
(c_option "-b" "makes backups of existing destination files first", [])]
unix_mv = commandWOptions (command "mv") (description ["moves or renames files"])
[(c_option "-i" "asks before an existing file is overwritten", [])]
unix_ln = commandWOptions (command "ln") (description ["creates file links"])
[(c_option " " "no option results in hard links", []),
(c_option "-l" "makes symbolic instead of hard links", []),
(c_option "-t" "puts the generated links into a specified directory", [])]
unix_stat = commandWOptions (command "stat") (description ["prints information on file status"])
[(c_option "" "",
[" File: `wordList'", " Size: 6338 Blocks: 16 IO Block: 4096 regular file",
"Device: fd01h/64769d Inode: 1594466 Links: 1",
"Access: (0670/-rw-rwx---) Uid: ( 1964/auric.goldfinger) Gid: ( 100/users)",
"Access: 2012-07-13 11:09:46.000000000 +0100",
"Modify: 2012-06-22 13:18:01.000000000 +0100",
"Change: 2012-07-09 15:00:10.000000000 +0100"]),
(c_option "-t" "information is given in terse form",
["wordList 6338 16 81b8 2209 100 fd01 1594466",
"1 0 0 1342174186 1340367481 1341842410 4096"]),
(c_option "-f" "status of file system instead of file is reported",
["File: \"wordList\""," ID: adc9b05614460536 Namelen: 255 Type: ext2/ext3",
"Block size: 4096 Fundamental block size: 4096",
"Blocks: Total: 7240958 Free: 5622141 Available: 5254321",
"Inodes: Total: 1839600 Free: 1702146"])]
unix_tree = commandWOptions (command "tree") (description ["displays directory contents as tree"])
[(c_option "" "",
["films",
"|-- action",
"| `-- firstBlood",
"|-- comedy",
"| `-- supernaturalComedy",
"| |-- ghostbusters",
"| `-- ghostbusters2",
"`-- horror",
" |-- slasher",
-- " | `-- halloween",
-- " `-- zombie",
-- " |-- 28DaysLater",
-- " `-- predator",
"",
"6 directories, 6 files"]),
(c_option "-d" "only directories", -- are considered",
["films",
"|-- action",
"|-- comedy",
"| `-- supernaturalComedy",
"`-- horror",
" |-- slasher",
" `-- zombie",
"",
"6 directories"]),
(c_option "-a" "entries starting with '.'",
[".",
-- "|-- .asd.swp",
"|-- .bash_history",
"|-- .bash_profile",
"|-- .bashrc",
-- "|-- .qwetzi.swp",
-- "|-- .script1.swp",
-- "|-- .viminfo",
-- "|-- .vimrc",
-- "|-- Deleted",
-- "|-- bin",
-- "| |-- aravind",
-- "| |-- colour",
-- "| |-- jace",
-- "| |-- raman",
"|-- deleted",
"| |-- dir1",
"| |-- file1",
-- "| |-- file2",
-- "| |-- file3",
-- "| `-- list.txt",
-- "|-- file2",
"",
"4 directories, 18 files"]),
(c_option "-u" "prints username", -- of the files",
["films",
"|-- [nerd.gee] action",
"| `-- [nerd.gee] firstBlood",
"|-- [nerd.gee] comedy",
"| `-- [nerd.gee] supernaturalComedy",
-- "| |-- [nerd.gee] ghostbusters",
"| `-- [nerd.gee] ghostbusters",
----- "`-- [nerd.gee] horror",
" |-- [nerd.gee] slasher",
-- " | `-- [nerd.gee] halloween",
-- " `-- [nerd.gee] zombie",
-- " |-- [nerd.gee] 28DaysLater",
-- " `-- [nerd.gee] predator",
"",
"6 directories, 6 files"]),
(c_option "-l" "follows symbolic links", []),
(c_option "--inodes" "prints inode number",
["films",
"|-- [1594337] action",
"| `-- [1594346] firstBlood",
"|-- [1594336] comedy",
"| `-- [1594349] supernaturalComedy",
"| `-- [1594344] ghostbusters",
" |-- [1594335] slasher",
"",
"6 directories, 6 files"])]
unix_pwd = commandDescriptionExample (command "pwd")
(description ["prints name of current directory"])
["/home/auric.goldfinger/projects/secret/grandslam"]
unix_find = commandVerticalOptions (command "find") (description ["looks for files"])
[ (c_option "find auxFile" "looks for files named \"auxFile\" in the current directory only",
["find: auxFile: No such file or directory"]),
(c_option "find -name auxFile" "looks for files named \"auxFile\" in the current directory and its subdirectories",
["./subdir1/thatDir/auxFile", "./subdir1/auxFile"]),
(c_option "find -maxdepth 2 -name auxFile"
"looks for files named \"auxFile\" in the (sub)directories up to level 2 (current directory being level 1)",
["./subdir1/auxFile"]),
(c_option "find /home -maxdepth 1 -name \"james*\""
"looks for files/directories whose names start with \"james\" in the directory '/home' (first level only)",
["/home/james.bond",
"/home/james.brown",
"/home/james.cook",
"/home/james.kirk"]),
(c_option "find -empty" "returns only directories/regular files that are empty", ["./subdir1/dirWithoutContent"]),
(c_option "-type l" "returns only symbolic links",["./subdir1/auxFile"]),
(c_option "find -amin +25" "returns only files/directories accessed more than 25 minutes ago",
[".", "./subdir1/auxFile"]),
(c_option "find -atime -2" "returns only files/directories accessed less than 48 hours ago",
[".", "./subdir1", "./subdir1/thatDir",
"./subdir1/thatDir/auxFile",
"./subdir1/auxFile"]),
(c_option "find -mmin 100" "returns only files/directories with data modified exactly 100 minutes ago", ["./subdir1"]),
(c_option "find -perm 700" "returns only files/directories where owner has all permissions, group and others have no permission",
["./subdir1/dirWithoutContent"]),
(c_option " find -name *Content -delete" "finds all files/directories whose names end with 'Content' and deletes them",[]),
(c_option "find /bin/ch* -exec wc '{}' \\;"
"finds all files with names starting with 'ch' in directory '/bin' and executes command 'wc' on them",
[" 134 1381 56984 /bin/chgrp",
" 110 1183 54112 /bin/chmod",
" 148 1489 59180 /bin/chown"]),
(c_option "find -name auxFile -type f -exec chmod go+r '{}' \\;"
"finds all regular files named 'auxFile' and adds read permission for group and others on those files",[]) ]
unix_df = commandWOptions (command "df") (description ["reports usage of disk space by file system"])
[(c_option "" "",
["Filesystem 1K-blocks Used Available Use% Mounted on",
"/dev/mapper/VolGroup00-LogVol00",
" 10063176 7788044 1763952 82% /",
"/dev/mapper/VolGroup00-LogVol02",
" 28963832 6533316 20959236 24% /home",
"/dev/sda1 194442 18711 165692 11% /boot",
"tmpfs 517380 96 517284 1% /dev/shm"]),
(c_option "-h" "sizes are given in easily understandable units",
["Filesystem Size Used Avail Use% Mounted on",
"/dev/mapper/VolGroup00-LogVol00 9.6G 7.5G 1.7G 82% /",
"/dev/mapper/VolGroup00-LogVol02 28G 6.0G 21G 23% /home",
"/dev/sda1 190M 19M 162M 11% /boot",
"tmpfs 506M 96K 506M 1% /dev/shm" ]),
(c_option "-i" "information on inodes instead of sizes is given",
[ "Filesystem Inodes IUsed IFree IUse% Mounted on",
"/dev/mapper/VolGroup00-LogVol00 638976 136235 502741 22% /",
"/dev/mapper/VolGroup00-LogVol02 1839600 135016 1704584 8% /home",
"/dev/sda1 50200 40 50160 1% /boot",
"tmpfs 129345 3 129342 1% /dev/shm" ]) ]
unix_du = commandWOptions (command "du") (description ["estimates space usage by directories"])
[(c_option "" "",
["8 ./dir",
"8 ./films/horror/zombie",
"8 ./films/horror/slasher",
"24 ./films/horror",
"8 ./films/action",
"168 ."]),
(c_option "-s" "display total space usage only", ["168."]),
(c_option "--time" "give also last modifaction time",
["8 2012-07-03 14:17 ./dir",
"8 2012-06-20 12:38 ./films/horror/zombie",
"8 2012-06-20 12:38 ./films/horror/slasher",
"24 2012-06-20 12:38 ./films/horror",
"168 2012-07-03 14:17 ."]) ]
unix_quota = commandDescriptionExample (command "quota")
(description ["reports usage of disk space by and limits for the user"])
["Disk quotas for user hugo.drax (uid 1979):",
" Filesystem blocks quota limit grace files quota limit grace",
"/dev/mapper/VolGroup00-LogVol02",
" 820 5000 5000 173 00"]
unix_chmod = commandVerticalOptions (command "chmod") (description ["sets/changes file permissions"])
[(c_option "chmod u+rw myFile" "adds read and write permission for file \"myFile\" to the owners permissions", []),
(c_option "chmod g-wx myFile" "removes write and execute permission for file \"myFile\" from the groups' permissions", []),
(c_option "chmod o-wx myFile" "removes write and execute permission for file \"myFile\" from the others' permissions", []),
(c_option "chmod a=r myFile" "sets the permissions for myFile to read for all owner, group, and others (and nothing else)", []),
-- (c_option "chmod 754 myFile" "sets the permissions for myFile to read, write, and execute for the owner, read and execute for the owner's group, and read for others", []),
-- (c_option "-v" "gives a short message after setting permissions", ["mode of `d1/d2/myFile' retained as 0754 (rwxr-xr--)"]),
-- (c_option "-c" "gives a short message only if changes are made", ["mode of `d1/d2/myFile' changed to 0777 (rwxrwxrwx)"]),
(c_option "-R" "sets permissions on files and directories recursively", [])]
unix_permissions = textBox
["chmod UGO myfile (User Group Other)",
"eg: chmod 754 myfile",
"where each octal number stands for rwx:",
-- "000 = 0 none",
"001 = 1 = --x = execute only",
"010 = 2 = -w- = write only",
"011 = 3 = -wx = write and execute",
"100 = 4 = r-- = read only",
"101 = 5 = r-x = read and execute",
"110 = 6 = rw- = read and write",
"111 = 7 = rwx = full"
] 1.3 white grey 0.3 # alignTL
-----------------------------
-- Processing of Lines
-----------------------------
unix_wc = commandWOptions (command "wc") (description ["counts lines, words, characters"])
[(c_option "" "", ["80 171 935 hangman"]),
(c_option "-l" "number of lines", ["80 hangman"]),
(c_option "-w" "number of words", ["171 hangman"]),
(c_option "-c" "number of characters",["935 hangman"])]
unix_cut = commandVerticalOptions (command "cut") (description ["selects and displays sections from lines in a file"])
[(c_option "cut -c1-7 PrimeMinisters" "selects the 1st to 7th character of every line in file\"PrimeMinisters\"",
[--"Maggie",
--"John Ma",
"Tony Bl",
"Gordon",
"David C"]),
(c_option "cut -f1 -d\"-\" PrimeMinisters" "selects 1st field of every line in file \"PrimeMinisters\", interpreting '-' as field delimiter",
[--"Maggie Thatcher|1979",
--"John Major|1990",
"Tony Blair|1997",
"Gordon Brown|2007",
"David Cameron|2010"]),
(c_option "cut -f1,3 -d \"|\" --output-delimiter=\"; \" PrimeMinisters"
"selects 1st and 3rd field of every line in file \"PrimeMinisters\", interpreting '|' as field delimiter and replacing it by '; ' for the output",
[--"Maggie Thatcher; Tories",
--"John Major; Tories",
"Tony Blair; Labour",
"Gordon Brown; Labour",
"David Cameron; Tories"]) ]
unix_grep = commandVerticalOptions (command "grep") (description ["searches in files for lines matching a specified pattern, and prints the results"])
[ (c_option "grep Tories PrimeMinisters" "searches for lines containing 'Tories' in file \"PrimeMinisters\"",
["Maggie Thatcher|1979-1990|Tories|1979, 1983, 1987",
"John Major|1990-1997|Tories|1992 elections",
"David Cameron|2010-20??|Tories|2010 elections"]),
(c_option "grep -c Labour PrimeMinisters" "searches for 'Labour' in file \"PrimeMinisters\", prints only a count of matching lines found",["2"]),
(c_option "grep -f FourLetterNames PrimeMinisters" "searches in file \"PrimeMinisters\" for patterns read from file \"FourLetterNames\"",
["John Major|1990-1997|Tories|1992 elections",
"Tony Blair|1997-2007|Labour|1997, 2001, 2005 elections"]),
(c_option "grep -i G PrimeMinisters" "searches case-insensitive for 'G' in file \"PrimeMinisters\"",
["Maggie Thatcher|1979-1990|Tories|1979, 1983, 1987",
"Gordon Brown|2007-2010|Labour|elections"]),
(c_option "grep -n Tony PrimeMinisters" "searches for 'Tony' in file \"PrimeMinisters\", prints also the numbers of the lines found",
["3:Tony Blair|1997-2007|Labour|1997, 2001, 2005 elections"]),
(c_option "grep -v Tories PrimeMinisters" "selects and prints only those lines of file \"PrimeMinisters\" not matching the pattern 'Tories'",
["Tony Bliar|1997-2007|Labour|1997, 2001, 2005 elections",
"Gordon Brown|2007-2010|Labour|elections"]) ]
unix_tee = commandWOptions (command "tee") (description ["writes input to stdout and a file at the same time"])
[ (c_option "tee tFile" "writes the input of the user into file \"tFile\" as well as to the terminal",
["Hello, this is me writing some text.",
"Hello, this is me writing some text.",
"Why did that repeat?",
"Why did that repeat?",
-- "Ah, I see - it's because I use 'tee'!",
-- "Ah, I see - it's because I use 'tee'!",
"^C"]),
(c_option "tee -a tFile" "appends the input to file \"tFile\" instead of overwriting it",
["And more text. Will this be added to the content of \"tFile\" instead of replacing it?",
"And more text. Will this be added to the content of \"tFile\" instead of replacing it?",
"Yes it does!",
-- "Yes it does!",
"^C"]) ]
unix_tail = commandWOptions (command "tail") (description ["prints the last 10 lines to stdout"])
[ (c_option "" "", ["line 19", ":","line 29"]),
(c_option "-n" "prints the last n lines", ["line 19",":","line 19+n"]) ]
unix_head = commandWOptions (command "head") (description ["prints the first 10 lines to stdout"])
[ (c_option "" "", ["line 1", ":","line 10"]),
(c_option "-n" "prints the first n lines", ["line 1", ":","line n"]) ]
unix_more = commandWOptions (command "more") (description ["loads a whole file and prints its content to the screen one page at a time"]) []
unix_less = commandWOptions (command "less") (description ["prints a file's content to the screen in a scrollable view, loading only as much of the file as needed"]) []
unix_sort = commandVerticalOptions (command "sort") (description ["prints sorted file contents to stdout"])
[ (c_option "sort Beatles" "sorts lines in file \"Beatles\" and prints them out",
["Harrison, George, 1943, 2001",
"Lennon, John, 1940, 1980",
"McCartney, Paul, 1942, 20??",
"Starr, Ringo, 1940, 20??"]),
(c_option "sort -r Beatles" "sorts lines in file \"Beatles\" in reverse order and prints them out",
["Starr, Ringo, 1940, 20??",
"McCartney, Paul, 1942, 20??",
"Lennon, John, 1940, 1980",
"Harrison, George, 1943, 2001"]),
(c_option "sort -c Beatles" "does not sort but check if lines in file \"Beatles\" are sorted",
["sort: Beatles:3: disorder: Harrison, George, 1943, 2001"]),
-- (c_option "-b" "leading blanks are ignored", ["???"]),
(c_option "sort -n Commodities" "sorts lines of file \"Commodities\" numerically",
["27.5$/oz. Silver",
"106.5$/bbl. Oil",
"1600$/oz. Gold"]),
(c_option "sort -k 2 Commodities" "sorts lines of file \"Commodities\", the sort key is understood to start 2nd field",
["1600$/oz. Gold",
"106.5$/bbl. Oil",
"27.5$/oz. Silver"]) ]
unix_uniq = commandVerticalOptions (command "uniq")
(description ["prints lines to stdout omitting those who are copies of their predecessor"])
[ (c_option "uniq USPresidentialElectionWinners" "prints lines of file \"USPresidentialElectionWinners\" to stdout omitting repetitions",
["George Bush",
"Bill Clinton",
"George W. Bush",
"Barack Obama"]),
(c_option "uniq -c USPresidentialElectionWinners"
"prints non-double lines of file \"USPresidentialElectionWinners\" to stdout, together with the number of occurrences",
["1 George Bush",
"2 Bill Clinton",
"2 George W. Bush",
"1 Barack Obama"]),
(c_option "uniq -u USPresidentialElectionWinners" "prints only non-repeated lines of file \"USPresidentialElectionWinners\"",