1 module seed;
2 
3 // -- IMPORTS
4 
5 import core.stdc.stdlib : exit;
6 import std.ascii : isDigit, isLower, isUpper;
7 import std.conv : to;
8 import std.file : dirEntries, exists, mkdirRecurse, read, readText, remove, rmdir, thisExePath, write, SpanMode;
9 import std.path : dirName;
10 import std.stdio : writeln;
11 import std.string : capitalize, endsWith, indexOf, join, lastIndexOf, replace, split, startsWith, strip, stripRight, toLower, toUpper;
12 import std.uni : isAlpha;
13 
14 // -- TYPES
15 
16 enum VERBOSITY
17 {
18     Error,
19     Warning,
20     Activity,
21     Action,
22     Operation,
23     Information,
24     Debug
25 }
26 
27 // -- VARIABLES
28 
29 VERBOSITY
30     Verbosity = VERBOSITY.Debug;
31 
32 // -- FUNCTIONS
33 
34 void SetVerbosity(
35     VERBOSITY verbosity
36     )
37 {
38     Verbosity = verbosity;
39 }
40 
41 // ~~
42 
43 bool HasVerbosity(
44     VERBOSITY verbosity
45     )
46 {
47     return Verbosity >= verbosity;
48 }
49 
50 // ~~
51 
52 void PrintWarning(
53     string message
54     )
55 {
56     writeln( "*** WARNING : ", message );
57 }
58 
59 // ~~
60 
61 void PrintError(
62     string message
63     )
64 {
65     writeln( "*** ERROR : ", message );
66 }
67 
68 // ~~
69 
70 void Abort(
71     string message
72     )
73 {
74     PrintError( message );
75 
76     exit( -1 );
77 }
78 
79 // ~~
80 
81 void Abort(
82     string message,
83     Exception exception
84     )
85 {
86     PrintError( message );
87     PrintError( exception.msg );
88 
89     exit( -1 );
90 }
91 
92 // ~~
93 
94 bool IsLinux(
95     )
96 {
97     version ( linux )
98     {
99         return true;
100     }
101     else
102     {
103         return false;
104     }
105 }
106 
107 // ~~
108 
109 bool IsMacOs(
110     )
111 {
112     version ( OSX )
113     {
114         return true;
115     }
116     else
117     {
118         return false;
119     }
120 }
121 
122 // ~~
123 
124 bool IsWindows(
125     )
126 {
127     version ( Windows )
128     {
129         return true;
130     }
131     else
132     {
133         return false;
134     }
135 }
136 
137 // ~~
138 
139 bool IsAlphabeticalCharacter(
140     char character
141     )
142 {
143     return
144         ( character >= 'a' && character <= 'z' )
145         || ( character >= 'A' && character <= 'Z' );
146 }
147 
148 // ~~
149 
150 bool IsIdentifierCharacter(
151     char character
152     )
153 {
154     return
155         ( character >= 'a' && character <= 'z' )
156         || ( character >= 'A' && character <= 'Z' )
157         || ( character >= '0' && character <= '9' )
158         || character == '_';
159 }
160 
161 // ~~
162 
163 bool IsDecimalCharacter(
164     char character
165     )
166 {
167     return ( character >= '0' && character <= '9' );
168 }
169 
170 // ~~
171 
172 bool IsDecimalCharacter(
173     dchar character
174     )
175 {
176     return ( character >= '0' && character <= '9' );
177 }
178 
179 // ~~
180 
181 bool IsNumberCharacter(
182     char character
183     )
184 {
185     return
186         ( character >= '0' && character <= '9' )
187         || character == '.'
188         || character == '-'
189         || character == 'e'
190         || character == 'E';
191 }
192 
193 // ~~
194 
195 bool IsSpaceCharacter(
196     dchar character
197     )
198 {
199     return
200         character == dchar( ' ' )
201         || character == dchar( '\t' )
202         || character == dchar( 0xA0 );
203 }
204 
205 // ~~
206 
207 bool IsDigitCharacter(
208     dchar character
209     )
210 {
211     return
212         character >= '0'
213         && character <= '9';
214 }
215 
216 // ~~
217 
218 bool IsVowelCharacter(
219     char character
220     )
221 {
222     return "aeiouy".indexOf( character ) >= 0;
223 }
224 
225 // ~~
226 
227 bool IsConsonantCharacter(
228     char character
229     )
230 {
231     return "bcdfghjklmnpqrstvwx".indexOf( character ) >= 0;
232 }
233 
234 // ~~
235 
236 bool StartsByVowel(
237     string text
238     )
239 {
240     return
241         text != ""
242         && IsVowelCharacter( text[ 0 ] );
243 }
244 
245 // ~~
246 
247 bool StartsByConsonant(
248     string text
249     )
250 {
251     return
252         text != ""
253         && IsConsonantCharacter( text[ 0 ] );
254 }
255 
256 // ~~
257 
258 bool EndsByVowel(
259     string text
260     )
261 {
262     return
263         text != ""
264         && IsVowelCharacter( text[ $ - 1 ] );
265 }
266 
267 // ~~
268 
269 bool EndsByConsonant(
270     string text
271     )
272 {
273     return
274         text != ""
275         && IsConsonantCharacter( text[ $ - 1 ] );
276 }
277 
278 // ~~
279 
280 string GetBooleanText(
281     bool boolean
282     )
283 {
284     if ( boolean )
285     {
286         return "true";
287     }
288     else
289     {
290         return "false";
291     }
292 }
293 
294 // ~~
295 
296 bool IsNatural(
297     string text
298     )
299 {
300     if ( text.length > 0 )
301     {
302         foreach ( character; text )
303         {
304             if ( character < '0'
305                  || character > '9' )
306             {
307                 return false;
308             }
309         }
310 
311         return true;
312     }
313     else
314     {
315         return false;
316     }
317 }
318 
319 // ~~
320 
321 bool IsInteger(
322     string text
323     )
324 {
325     if ( text.length > 0
326          && text[ 0 ] == '-' )
327     {
328         text = text[ 1 .. $ ];
329     }
330 
331     return IsNatural( text );
332 }
333 
334 // ~~
335 
336 ulong GetNatural(
337     string text
338     )
339 {
340     try
341     {
342         return text.to!ulong();
343     }
344     catch ( Exception exception )
345     {
346         Abort( "Invalid natural : " ~ text, exception );
347     }
348 
349     return 0;
350 }
351 
352 // ~~
353 
354 long GetInteger(
355     string text
356     )
357 {
358     try
359     {
360         return text.to!long();
361     }
362     catch ( Exception exception )
363     {
364         Abort( "Invalid integer : " ~ text, exception );
365     }
366 
367     return 0;
368 }
369 
370 // ~~
371 
372 double GetReal(
373     long integer
374     )
375 {
376     return integer.to!double();
377 }
378 
379 // ~~
380 
381 double GetReal(
382     string text
383     )
384 {
385     try
386     {
387         return text.to!double();
388     }
389     catch ( Exception exception )
390     {
391         Abort( "Invalid real : " ~ text, exception );
392     }
393 
394     return 0.0;
395 }
396 
397 // ~~
398 
399 bool ContainsText(
400     string text,
401     string searched_text
402     )
403 {
404     return text.indexOf( searched_text ) >= 0;
405 }
406 
407 // ~~
408 
409 bool HasPrefix(
410     string text,
411     string prefix
412     )
413 {
414     return text.startsWith( prefix );
415 }
416 
417 // ~~
418 
419 bool HasSuffix(
420     string text,
421     string suffix
422     )
423 {
424     return text.endsWith( suffix );
425 }
426 
427 // ~~
428 
429 string GetPrefix(
430     string text,
431     string separator
432     )
433 {
434     return text.split( separator )[ 0 ];
435 }
436 
437 // ~~
438 
439 string GetSuffix(
440     string text,
441     string separator
442     )
443 {
444     return text.split( separator )[ $ - 1 ];
445 }
446 
447 // ~~
448 
449 string AddPrefix(
450     string text,
451     string prefix
452     )
453 {
454     return prefix ~ text;
455 }
456 
457 // ~~
458 
459 string AddSuffix(
460     string text,
461     string suffix
462     )
463 {
464     return text ~ suffix;
465 }
466 
467 // ~~
468 
469 string RemovePrefix(
470     string text,
471     string prefix
472     )
473 {
474     if ( text.startsWith( prefix ) )
475     {
476         return text[ prefix.length .. $ ];
477     }
478     else
479     {
480         return text;
481     }
482 }
483 
484 // ~~
485 
486 string RemoveSuffix(
487     string text,
488     string suffix
489     )
490 {
491     if ( text.endsWith( suffix ) )
492     {
493         return text[ 0 .. $ - suffix.length ];
494     }
495     else
496     {
497         return text;
498     }
499 }
500 
501 // ~~
502 
503 string ReplacePrefix(
504     string text,
505     string old_prefix,
506     string new_prefix
507     )
508 {
509     if ( text.startsWith( old_prefix ) )
510     {
511         return new_prefix ~ text[ old_prefix.length .. $ ];
512     }
513     else
514     {
515         return text;
516     }
517 }
518 
519 // ~~
520 
521 string ReplaceSuffix(
522     string text,
523     string old_suffix,
524     string new_suffix
525     )
526 {
527     if ( text.endsWith( old_suffix ) )
528     {
529         return text[ 0 .. $ - old_suffix.length ] ~ new_suffix;
530     }
531     else
532     {
533         return text;
534     }
535 }
536 
537 // ~~
538 
539 string ReplaceText(
540     string text,
541     string old_text,
542     string new_text
543     )
544 {
545     return text.replace( old_text, new_text );
546 }
547 
548 // ~~
549 
550 string GetStrippedText(
551     string text
552     )
553 {
554     dstring
555         unicode_text;
556 
557     unicode_text = text.to!dstring();
558 
559     while ( unicode_text.length > 0
560             && IsSpaceCharacter( unicode_text[ 0 ] ) )
561     {
562         unicode_text = unicode_text[ 1 .. $ ];
563     }
564 
565     while ( unicode_text.length > 0
566             && IsSpaceCharacter( unicode_text[ $ - 1 ] ) )
567     {
568         unicode_text = unicode_text[ 0 .. $ - 1 ];
569     }
570 
571     return unicode_text.to!string();
572 }
573 
574 // ~~
575 
576 string GetLeftStrippedText(
577     string text
578     )
579 {
580     dstring
581         unicode_text;
582 
583     unicode_text = text.to!dstring();
584 
585     while ( unicode_text.length > 0
586             && IsSpaceCharacter( unicode_text[ 0 ] ) )
587     {
588         unicode_text = unicode_text[ 1 .. $ ];
589     }
590 
591     return unicode_text.to!string();
592 }
593 
594 // ~~
595 
596 string GetRightStrippedText(
597     string text
598     )
599 {
600     dstring
601         unicode_text;
602 
603     unicode_text = text.to!dstring();
604 
605     while ( unicode_text.length > 0
606             && IsSpaceCharacter( unicode_text[ $ - 1 ] ) )
607     {
608         unicode_text = unicode_text[ 0 .. $ - 1 ];
609     }
610 
611     return unicode_text.to!string();
612 }
613 
614 // ~~
615 
616 string GetMinorCaseText(
617     string text
618     )
619 {
620     dstring
621         unicode_text;
622 
623     if ( text == "" )
624     {
625         return "";
626     }
627     else
628     {
629         unicode_text = text.to!dstring();
630 
631         return ( unicode_text[ 0 .. 1 ].toLower() ~ unicode_text[ 1 .. $ ] ).to!string();
632     }
633 }
634 
635 // ~~
636 
637 string GetMajorCaseText(
638     string text
639     )
640 {
641     dstring
642         unicode_text;
643 
644     if ( text == "" )
645     {
646         return "";
647     }
648     else
649     {
650         unicode_text = text.to!dstring();
651 
652         return ( unicode_text[ 0 .. 1 ].capitalize() ~ unicode_text[ 1 .. $ ] ).to!string();
653     }
654 }
655 
656 // ~~
657 
658 string GetLowerCaseText(
659     string text
660     )
661 {
662     return text.toLower();
663 }
664 
665 // ~~
666 
667 string GetUpperCaseText(
668     string text
669     )
670 {
671     return text.toUpper();
672 }
673 
674 // ~~
675 
676 string GetSpacedText(
677     string text
678     )
679 {
680     foreach ( character; [ '\t', '_', '-', ',', ';', ':', '.', '!', '?' ] )
681     {
682         text = text.replace( character, ' ' );
683     }
684 
685     while ( text.indexOf( "  " ) >= 0 )
686     {
687         text = text.replace( "  ", " " );
688     }
689 
690     return text;
691 }
692 
693 // ~~
694 
695 string GetPascalCaseText(
696     string text
697     )
698 {
699     string[]
700         word_array;
701 
702     word_array = text.GetSpacedText().strip().split( ' ' );
703 
704     foreach ( ref word; word_array )
705     {
706         word = word.GetMajorCaseText();
707     }
708 
709     return word_array.join( "" );
710 }
711 
712 // ~~
713 
714 string GetCamelCaseText(
715     string text
716     )
717 {
718     return text.GetPascalCaseText().GetMinorCaseText();
719 }
720 
721 // ~~
722 
723 string GetSnakeCaseText(
724     string text
725     )
726 {
727     dchar
728         character,
729         next_character,
730         prior_character;
731     long
732         character_index;
733     dstring
734         snake_case_text,
735         unicode_text;
736 
737     unicode_text = text.GetSpacedText().strip().to!dstring();
738 
739     snake_case_text = "";
740     prior_character = 0;
741 
742     for ( character_index = 0;
743           character_index < unicode_text.length;
744           ++character_index )
745     {
746         character = unicode_text[ character_index ];
747 
748         if ( character_index + 1 < unicode_text.length )
749         {
750             next_character = unicode_text[ character_index + 1 ];
751         }
752         else
753         {
754             next_character = 0;
755         }
756 
757         if ( ( prior_character.isLower()
758                && ( character.isUpper()
759                     || character.isDigit() ) )
760              || ( prior_character.isDigit()
761                   && ( character.isLower()
762                        || character.isUpper() ) )
763              || ( prior_character.isUpper()
764                   && character.isUpper()
765                   && next_character.isLower() ) )
766         {
767             snake_case_text ~= '_';
768         }
769 
770         if ( character == ' '
771              && !snake_case_text.endsWith( '_' ) )
772         {
773             character = '_';
774         }
775 
776         snake_case_text ~= character;
777         prior_character = character;
778     }
779 
780     return snake_case_text.to!string().toLower();
781 }
782 
783 // ~~
784 
785 string GetKebabCaseText(
786     string text
787     )
788 {
789     return GetSnakeCaseText( text ).replace( '_', '-' );
790 }
791 
792 // ~~
793 
794 dchar GetSlugCharacter(
795     dchar character
796     )
797 {
798     switch ( character )
799     {
800         case 'à' : return 'a';
801         case 'â' : return 'a';
802         case 'é' : return 'e';
803         case 'è' : return 'e';
804         case 'ê' : return 'e';
805         case 'ë' : return 'e';
806         case 'î' : return 'i';
807         case 'ï' : return 'i';
808         case 'ô' : return 'o';
809         case 'ö' : return 'o';
810         case 'û' : return 'u';
811         case 'ü' : return 'u';
812         case 'ç' : return 'c';
813         case 'ñ' : return 'n';
814         case 'À' : return 'a';
815         case 'Â' : return 'a';
816         case 'É' : return 'e';
817         case 'È' : return 'e';
818         case 'Ê' : return 'e';
819         case 'Ë' : return 'e';
820         case 'Î' : return 'i';
821         case 'Ï' : return 'i';
822         case 'Ô' : return 'o';
823         case 'Ö' : return 'o';
824         case 'Û' : return 'u';
825         case 'Ü' : return 'u';
826         case 'C' : return 'c';
827         case 'Ñ' : return 'n';
828         default : return character.toLower();
829     }
830 }
831 
832 // ~~
833 
834 string GetSlugCaseText(
835     string text
836     )
837 {
838     dstring
839         slug_case_text,
840         unicode_text;
841 
842     unicode_text = text.GetSpacedText().strip().to!dstring();
843 
844     foreach ( character; unicode_text )
845     {
846         if ( character.isAlpha() )
847         {
848             slug_case_text ~= GetSlugCharacter( character );
849         }
850         else if ( character >= '0'
851                   && character <= '9' )
852         {
853             if ( slug_case_text != ""
854                  && !slug_case_text.endsWith( '-' )
855                  && !IsDecimalCharacter( slug_case_text[ $ - 1 ] ) )
856             {
857                 slug_case_text ~= '-';
858             }
859 
860             slug_case_text ~= character;
861         }
862         else
863         {
864             if ( !slug_case_text.endsWith( '-' ) )
865             {
866                 slug_case_text ~= '-';
867             }
868         }
869     }
870 
871     while ( slug_case_text.endsWith( '-' ) )
872     {
873         slug_case_text = slug_case_text[ 0 .. $ - 1 ];
874     }
875 
876     return slug_case_text.to!string();
877 }
878 
879 // ~~
880 
881 string GetFileCaseText(
882     string text
883     )
884 {
885     return GetSlugCaseText( text ).replace( '-', '_' );
886 }
887 
888 // ~~
889 
890 string GetBasilText(
891     string text
892     )
893 {
894     return
895         text
896             .replace( "\\", "\\\\" )
897             .replace( "~", "\\~" )
898             .replace( "^", "\\^" )
899             .replace( "\n", "\\\\n" )
900             .replace( "\r", "\\\\r" )
901             .replace( "\t", "\\\\t" );
902 }
903 
904 // ~~
905 
906 string GetCsvText(
907     string text
908     )
909 {
910     if ( text.indexOf( '"' ) >= 0
911          || text.indexOf( ',' ) >= 0
912          || text.indexOf( '\r' ) >= 0
913          || text.indexOf( '\n' ) >= 0 )
914     {
915         return "\"" ~ text.replace( "\"", "\"\"" ) ~ "\"";
916     }
917     else
918     {
919         return text;
920     }
921 }
922 
923 // ~~
924 
925 string GetJsonText(
926     string text
927     )
928 {
929     return
930         "\""
931         ~ text
932             .replace( "\\", "\\\\" )
933             .replace( "\n", "\\n" )
934             .replace( "\r", "\\r" )
935             .replace( "\t", "\\t" )
936             .replace( "\"", "\\\"" )
937         ~ "\"";
938 }
939 
940 // ~~
941 
942 string GetExecutablePath(
943     string file_name
944     )
945 {
946     return dirName( thisExePath() ) ~ "/" ~ file_name;
947 }
948 
949 
950 
951 // ~~
952 
953 string GetLogicalPath(
954     string path
955     )
956 {
957     return path.replace( '\\', '/' );
958 }
959 
960 // ~~
961 
962 string GetFolderPath(
963     string file_path
964     )
965 {
966     long
967         slash_character_index;
968 
969     slash_character_index = file_path.GetLogicalPath().lastIndexOf( '/' );
970 
971     if ( slash_character_index >= 0 )
972     {
973         return file_path[ 0 .. slash_character_index + 1 ];
974     }
975     else
976     {
977         return "";
978     }
979 }
980 
981 // ~~
982 
983 string GetFileName(
984     string file_path
985     )
986 {
987     long
988         slash_character_index;
989 
990     slash_character_index = file_path.GetLogicalPath().lastIndexOf( '/' );
991 
992     if ( slash_character_index >= 0 )
993     {
994         return file_path[ slash_character_index + 1 .. $ ];
995     }
996     else
997     {
998         return file_path;
999     }
1000 }
1001 
1002 // ~~
1003 
1004 string GetFileLabel(
1005     string file_path
1006     )
1007 {
1008     long
1009         dot_character_index;
1010     string
1011         file_name;
1012 
1013     file_name = file_path.GetFileName();
1014     dot_character_index = file_name.lastIndexOf( '.' );
1015 
1016     if ( dot_character_index >= 0 )
1017     {
1018         return file_name[ 0 .. dot_character_index - 1 ];
1019     }
1020     else
1021     {
1022         return file_name;
1023     }
1024 }
1025 
1026 // ~~
1027 
1028 string GetFileExtension(
1029     string file_path
1030     )
1031 {
1032     long
1033         dot_character_index;
1034     string
1035         file_name;
1036 
1037     file_name = file_path.GetFileName();
1038     dot_character_index = file_name.lastIndexOf( '.' );
1039 
1040     if ( dot_character_index >= 0 )
1041     {
1042         return file_name[ dot_character_index .. $ ];
1043     }
1044     else
1045     {
1046         return "";
1047     }
1048 }
1049 
1050 // ~~
1051 
1052 bool IsEmptyFolder(
1053     string folder_path
1054     )
1055 {
1056     bool
1057         it_is_empty_folder;
1058 
1059     try
1060     {
1061         it_is_empty_folder = true;
1062 
1063         foreach ( folder_entry; dirEntries( folder_path, SpanMode.shallow ) )
1064         {
1065             it_is_empty_folder = false;
1066 
1067             break;
1068         }
1069     }
1070     catch ( Exception exception )
1071     {
1072         Abort( "Can't read folder : " ~ folder_path, exception );
1073     }
1074 
1075     return it_is_empty_folder;
1076 }
1077 
1078 // ~~
1079 
1080 void CreateFolder(
1081     string folder_path
1082     )
1083 {
1084     if ( folder_path != ""
1085          && folder_path != "/"
1086          && !folder_path.exists() )
1087     {
1088         if ( HasVerbosity( VERBOSITY.Operation ) )
1089         {
1090             writeln( "Creating folder : ", folder_path );
1091         }
1092 
1093         try
1094         {
1095             folder_path.mkdirRecurse();
1096         }
1097         catch ( Exception exception )
1098         {
1099             Abort( "Can't create folder : " ~ folder_path, exception );
1100         }
1101     }
1102 }
1103 
1104 // ~~
1105 
1106 void RemoveFolder(
1107     string folder_path
1108     )
1109 {
1110     writeln( "Removing folder : ", folder_path );
1111 
1112     try
1113     {
1114         folder_path.rmdir();
1115     }
1116     catch ( Exception exception )
1117     {
1118         Abort( "Can't create folder : " ~ folder_path, exception );
1119     }
1120 }
1121 
1122 // ~~
1123 
1124 void RemoveFile(
1125     string file_path
1126     )
1127 {
1128     writeln( "Removing file : ", file_path );
1129 
1130     try
1131     {
1132         file_path.remove();
1133     }
1134     catch ( Exception exception )
1135     {
1136         Abort( "Can't remove file : " ~ file_path, exception );
1137     }
1138 }
1139 
1140 // ~~
1141 
1142 void WriteByteArray(
1143     string file_path,
1144     ubyte[] file_byte_array,
1145     bool folder_is_created = true
1146     )
1147 {
1148     if ( folder_is_created )
1149     {
1150         CreateFolder( file_path.dirName() );
1151     }
1152 
1153     if ( HasVerbosity( VERBOSITY.Operation ) )
1154     {
1155         writeln( "Writing file : ", file_path );
1156     }
1157 
1158     try
1159     {
1160         file_path.write( file_byte_array );
1161     }
1162     catch ( Exception exception )
1163     {
1164         Abort( "Can't write file : " ~ file_path, exception );
1165     }
1166 }
1167 
1168 // ~~
1169 
1170 ubyte[] ReadByteArray(
1171     string file_path
1172     )
1173 {
1174     ubyte[]
1175         file_byte_array;
1176 
1177     if ( HasVerbosity( VERBOSITY.Operation ) )
1178     {
1179         writeln( "Reading file : ", file_path );
1180     }
1181 
1182     try
1183     {
1184         file_byte_array = cast( ubyte[] )file_path.read();
1185     }
1186     catch ( Exception exception )
1187     {
1188         Abort( "Can't read file : " ~ file_path, exception );
1189     }
1190 
1191     return file_byte_array;
1192 }
1193 
1194 // ~~
1195 
1196 void WriteText(
1197     string file_path,
1198     string file_text,
1199     bool folder_is_created = true
1200     )
1201 {
1202     if ( folder_is_created )
1203     {
1204         CreateFolder( file_path.dirName() );
1205     }
1206 
1207     if ( HasVerbosity( VERBOSITY.Operation ) )
1208     {
1209         writeln( "Writing file : ", file_path );
1210     }
1211 
1212     file_text = file_text.stripRight();
1213 
1214     if ( file_text != ""
1215          && !file_text.endsWith( '\n' ) )
1216     {
1217         file_text ~= '\n';
1218     }
1219 
1220     try
1221     {
1222         if ( !file_path.exists()
1223              || file_path.readText() != file_text )
1224         {
1225             file_path.write( file_text );
1226         }
1227     }
1228     catch ( Exception exception )
1229     {
1230         Abort( "Can't write file : " ~ file_path, exception );
1231     }
1232 }
1233 
1234 // ~~
1235 
1236 string ReadText(
1237     string file_path
1238     )
1239 {
1240     string
1241         file_text;
1242 
1243     if ( HasVerbosity( VERBOSITY.Operation ) )
1244     {
1245         writeln( "Reading file : ", file_path );
1246     }
1247 
1248     try
1249     {
1250         file_text = file_path.readText();
1251     }
1252     catch ( Exception exception )
1253     {
1254         Abort( "Can't read file : " ~ file_path, exception );
1255     }
1256 
1257     return file_text;
1258 }
1259