squeeze

A static site generator that can put the toothpaste back in the tube.
git clone https://git.stjo.hn/squeeze
Log | Files | Refs | README | LICENSE

helpers.pl (3757B)


      1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      2 % File: helpers.pl
      3 % Description: Misc. utility predicates.
      4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      5 
      6 % read_file(+Stream, -Codes).
      7 %	Read a file to a list of character codes.
      8 read_file(Stream, Codes):-
      9 	get_code(Stream, Code),
     10 	read_file_next(Code, Stream, Codes).
     11 
     12 read_file_next(-1, _, []).
     13 
     14 read_file_next(Code, Stream, [Code|Rest]):-
     15 	read_file(Stream, Rest).
     16 
     17 
     18 % replace(+FindCodes, +ReplaceCodes, +Haystack, -Result).
     19 %	Find instances of FindCodes in Haystack and replace with ReplaceCodes.
     20 %	All four arguments are lists of character codes.
     21 replace(FindCodes, ReplaceCodes, Haystack, Result):-
     22 	substrings(FindCodes, Substrings, Haystack, []),
     23 	substrings(ReplaceCodes, Substrings, Result, []).
     24 
     25 substrings(Delimiter, [Substring|Substrings]) -->
     26 	anything(Substring),
     27 	Delimiter,
     28 	substrings(Delimiter, Substrings).
     29 
     30 substrings(_, [Substring]) --> anything(Substring).
     31 
     32 
     33 % write_codes(+CodesList).
     34 %   Loop through a list of character codes, convert each one to a
     35 %   character, and write them to the current output stream one at
     36 %   a time. This is better than converting the whole list to an atom
     37 %   with atom_codes/2, which can trigger a segfault if the atom is too long.
     38 write_codes(_, []).
     39 
     40 write_codes(Stream, [X|Rest]):-
     41 	char_code(Char, X),
     42 	write(Stream, Char),
     43 	write_codes(Stream, Rest).
     44 
     45 
     46 % join(?List, +Separator, ?Atom).
     47 %   Join elements of a list into an atom separated by a separator.
     48 %   Written specifically as a join predicate, but should work as a split.
     49 join([], _, '').
     50 
     51 join([A], _, A).
     52 
     53 join([First|Rest], Separator, Result):-
     54 	join(Rest, Separator, End),
     55 	atom_concat(First, Separator, FirstPlusSeparator),
     56 	atom_concat(FirstPlusSeparator, End, Result).
     57 
     58 
     59 % format_date(-RFCDate, +Date).
     60 %   Parse and format a date according to RFC 822.
     61 format_date(RFCDate, Date):-
     62 	date_stamp(YearCodes, MonthCodes, DayCodes, Date, []),
     63 	number_codes(Year, YearCodes),
     64 	number_codes(Month, MonthCodes),
     65 	number_codes(Day, DayCodes),
     66 	day_of_week(date(Year, Month, Day), DayOfWeek),
     67 	day(DayOfWeek, DayOfWeekNameCodes),
     68 	month(Month, MonthNameCodes, _),
     69 	rfc_822(YearCodes, MonthNameCodes, DayCodes, DayOfWeekNameCodes, RFCDate, []).
     70 
     71 % TODO: Implement support for other date formats.
     72 % Currently we support YYYY-MM-DD.
     73 date_stamp(YearCodes, MonthCodes, DayCodes) -->
     74 	anything(YearCodes),
     75 	"-",
     76 	anything(MonthCodes),
     77 	"-",
     78 	anything(DayCodes).
     79 
     80 rfc_822(YearCodes, MonthNameCodes, DayCodes, DayOfWeekNameCodes) -->
     81 	anything(DayOfWeekNameCodes),
     82 	", ",
     83 	anything(DayCodes),
     84 	" ",
     85 	anything(MonthNameCodes),
     86 	" ",
     87 	anything(YearCodes),
     88 	" 00:00:00 GMT".
     89 
     90 day_of_week(date(Year, Month, Day), DayOfWeek):-
     91 	magic_year(Year, Month, MagicYear),
     92 	month(Month, _, MagicMonth),
     93 	DayOfWeek is (MagicYear + MagicYear // 4 - MagicYear // 100 + MagicYear // 400 + MagicMonth + Day) mod 7.
     94 
     95 magic_year(Year, Month, MagicYear):-
     96 	Month < 3,
     97 	MagicYear is Year - 1.
     98 
     99 magic_year(Year, _, Year).
    100 
    101 % month(?MonthNumber, ?ShortName, -MagicNumber).
    102 %   Magic numbers, used for calculating the day of the week,
    103 %   are as defined in Sakamoto's methods:
    104 %   https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Sakamoto's_methods
    105 month(1, "Jan", 0).
    106 month(2, "Feb", 3).
    107 month(3, "Mar", 2).
    108 month(4, "Apr", 5).
    109 month(5, "May", 0).
    110 month(6, "Jun", 3).
    111 month(7, "Jul", 5).
    112 month(8, "Aug", 1).
    113 month(9, "Sep", 4).
    114 month(10, "Oct", 6).
    115 month(11, "Nov", 2).
    116 month(12, "Dec", 4).
    117 
    118 day(0, "Sun").
    119 day(1, "Mon").
    120 day(2, "Tue").
    121 day(3, "Wed").
    122 day(4, "Thu").
    123 day(5, "Fri").
    124 day(6, "Sat").
    125 
    126 
    127 anything([]) --> [].
    128 
    129 anything([X|Rest]) --> [X], anything(Rest).
    130 
    131 
    132 whitespace --> [].
    133 
    134 whitespace --> newline, whitespace.
    135 
    136 whitespace --> tab, whitespace.
    137 
    138 whitespace --> " ", whitespace.
    139 
    140 newline --> "\n".
    141 
    142 tab --> "\t".