Skip to content

Instantly share code, notes, and snippets.

@macias
Last active June 27, 2016 06:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save macias/f6cddf39e457f0e0c350fef11113c936 to your computer and use it in GitHub Desktop.
Save macias/f6cddf39e457f0e0c350fef11113c936 to your computer and use it in GitHub Desktop.
quick&dirty reminder script
%% first "real" program converted to Skila
%% read more at: https://aboutskila.wordpress.com/2016/04/25/x-fullmoon-the-first-successful-conversion/
using System._;
var current_year Int = Date.now.year;
var current_month Int = Date.now.month;
var current_day Int = Date.now.day;
def main()
if Environment.arguments.count==1 then
let parts = Environment.arguments[0].split("-");
if not (current_year,current_month,current_day) ?= * parts.map(p => p to ?Int) then
throw !Exception("Argument error.");
end
end
processing();
end
def print_tasks(title String,tasks ~String) String
var res = !"";
if not tasks.empty() then
res ++= "${title}:\n";
for s in tasks do
res ++= "* ${s}\n";
end
end
return res;
end
def days_in_month(var yyyy Int,var mm Int) Int
mm++;
if mm==13 then
mm = 1;
++yyyy;
end
let d = Date(yyyy,mm,1).addDays(-1);
return d.day;
end
def add_delta_YM(var year Int,var month Int,var day Int,dy Int,dm Int) (Int*3)
assert(dm>=0,"Only positive values");
year += dy;
month += dm;
year += (month-1).div(12);
month = (month-1).mod(12) + 1;
if day>days_in_month(year,month) then
day = days_in_month(year,month);
end
return (year,month,day);
end
def process_date(var yyyy Int,var mm Int,var dd Int,var day_of_week Int) (Int*4)
%% input: Monday -- 1, Sunday -- 7
if day_of_week>0 then %% given day of the week is required
day_of_week = (day_of_week==7?0:day_of_week); %% internal conversion -- 0 is Sunday, 6 is Saturday
var dw = Date(yyyy,mm,dd).dayOfWeek.ordinal;
if dw>day_of_week then
dw -= 7;
end
let t = Date(yyyy,mm,dd).addDays(day_of_week-dw);
(yyyy,mm,dd) = (t.year, t.month, t.day);
end
let days = days_in_month(yyyy,mm); %% correction because of the length of the month
if dd>days then
dd = days;
end
var distance = (Date(yyyy,mm,dd)-Date(current_year,current_month,current_day)).totalDays;
return (yyyy,mm,dd,distance);
end
def processing()
let current_tasks = ![String]();
let upcoming_tasks = ![String]();
let executables_ask = ![String]();
let executables_run = ![String]();
let dates_filename = Io.Path.combine(Io.Path.getDirectoryName(Environment.executablePath),"fullmoon.dates");
assert(Io.File.exists(dates_filename),"Dates file does not exist.");
for s in Io.File.readLines(dates_filename)
.map(s => s.replace(/#.*/,"").replace(/^\s+/,"").replace(/\s+$/,""))
.filter(s => not s.empty)
do
let (date, cycle_str, task_desc, advance_str, day_of_week_str)
= * do
let parts = s.split(";");
parts ++ "".copy((5-parts.count()));
end
let cycle = cycle_str to ?Int ?? 0;
let day_of_week = day_of_week_str to ?Int ?? 0;
%% yyyy -- given year, mm -- month, dd -- day
var (yyyy,mm,dd)
= * do
let date_parts = /^(?:(\d{4})-)?(?:(\d{1,2})-)?(\d{1,2})$/.match(date)
.at(0).captures
.map(m => date.slice(m.index,m.count) to ?Int ?? throw !Exception("Ill-formed date."));
%% optional parts start from year, thus we have to prepend zeros, not append them
0.copy((3-date_parts.count())) ++ date_parts;
end
var cycle_mode = 0;
if yyyy==0 then
yyyy = current_year;
cycle_mode = 2;
end
if mm==0 then
mm = current_month;
cycle_mode = 1;
end
(yyyy,mm,dd,var distance) = *process_date(yyyy,mm,dd,day_of_week);
%% yyyy,mm,dd are corrected now
%% distance -- distance (in days) from today to given date (yyyy,mm,dd)
if cycle>0 then
if distance<0 then
distance = (-distance).mod(cycle);
if distance>0 then
distance = cycle-distance;
end
else
%% if there is a cyclic event, computed distance to the nearest date, not to given one
%% thus -- compute modulo
distance = distance.abs().mod(cycle);
end
else if distance<0 then %% given event passed
if cycle_mode==1 then %% monthly event
(yyyy,mm,dd) = *add_delta_YM(yyyy,mm,dd,0,1);
else if cycle_mode==2 then %% annual event
(yyyy,mm,dd) = *add_delta_YM(yyyy,mm,dd,1,0);
end
(yyyy,mm,dd,distance) = *process_date(yyyy,mm,dd,day_of_week);
end
if advance_str=="?" then
if distance==0 then
executables_ask!append(task_desc);
end
else if advance_str=="!" then
if distance==0 then
executables_run!append(task_desc);
end
else if distance==0 then
current_tasks!append(task_desc);
else if advance_str != "" and distance>0
and (let advance ?= advance_str to ?Int) and distance<=advance then
upcoming_tasks!append("+${distance}: ${task_desc}");
end
end-for
let msg = print_tasks("Upcoming tasks",upcoming_tasks)
++
print_tasks("Current tasks",current_tasks);
if not msg.empty or (not executables_ask.empty) then
let proc = Process.call("kdialog","--title \"X-FullMoon\" --"++(executables_ask.empty ? "msgbox":"yesno")++" \""++msg++"\"");
if proc.exitCode==0 then
for exe in executables_ask do
Process.start(exe);
end
end
end
for exe in executables_run do
Process.start(exe);
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment