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