:- use_module(library(lib)). :- lib(by_unix). :- lib(options). :- lib(debug_call). alert_defaults( Defs ) :- Defs = [ critical(false), debug(false), help(false), title(title), timeout(false), type(both) ]. :- debuc(alert(info)). /** alert( +Opts ). Display an alert at a specific time. The predicate can send messages via Linux commands notify-send and zenity. There are 3 main elements in the message the title (Title) of the widow and the message (Mess) to which the time is prefixed. Opts * critical(Crit=false) escalate to critical level (Only relevant to notify messages. In some Oses it keeps the message on-screen till closed by user.) * debug(Dbg=false) progress informational messages * help print help and exit * help(Help=false) print help and exit * message(Mess) body of message * timeout(Tout=false) time out in seconds. Default passes nothing, where notify expires according to defaults and zenity does not at all. * title(Title=title) title of window/messsage * type(Type=both) type of message: notify, zenity or both * when(At) when (currently at('HH:MM'), at(HH,MM) and in(RelTime) are recognised) RelTime can be of the form Xs, Ym or Zh which are interpreted as seconds minutes and hours. If there is no time specifier prostfix, then RelTime is interpreted in minutes. According to some manual entries for the command, the implementation of notfiy-send is not stable for some parameters across OSes. With a numerical Tout, the zenity call will expire as a failure, as interaction is expected. On Linux Mint 22.3, notify-send does not honour this flag, you can use =|Crit=true|= for a persistant message. == > upsh alert title=one message=two when=in=1 debug=true % Sleeping for : 60 secs. > which supsh supsh: aliased to upsh p !* >& /dev/null & > upsh alert help % upsh alert title=titlE message=messagE when=in=5s % upsh alert title=titlE message=messagE when=at=9,0 % % with supsh aliased to- supsh: aliased to upsh p !* >& /dev/null & % supsh alert title=titlE message=messagE when=at=16\\:00 type=notify == Different time formats. == > upsh alert title=titleE message=messagE when=in=0.2m debug=true % Sleeping for : 12.0 secs. % Title: titleE % Msg: titleE % Creating messages for both commands. % Sending: notify-send(titleE,15:30 messagE) % Sending: zenity(--info,--title,titleE,--text,15:30 messagE) > upsh alert title=titleE message=messagE when=in=1s debug=true % Sleeping for : 1 secs. % Title: titleE % Msg: titleE ... upsh> date ; upsh p alert title=one message=two when=at=16,00 debug=true Mon 9 Mar 15:32:06 GMT 2026 % Sleeping for : 1673.3508853912354 secs. % Title: one % Msg: two ... == Persistancy of messages. == > upsh alert title=one message=two when=in=1s critical=true type=notify % in Linux Mint 22.3, this will create a persistant notify message > upsh alert title=one message=two when=in=1s timeout=4 % in Linux Mint 22.3, this will create a transient zenity message that will last 4s (def is persistent till user interaction) == @author nicos angelopoulos @version 0:1 2021/04/09 @version 0:2 2026/03/09, added option critical(Crit), postfix time and at(HH,MM) format (with examples) @tbd type check type */ alert( Args ) :- Self = alert, options_append( Self, Args, Opts ), alert_opts( Self, Opts ). alert_opts( _Self, Opts ) :- ( memberchk(help,Opts);options(help(true),Opts) ), !, debuc( alert(info), 'upsh alert title=titlE message=messagE when=in=5s', [] ), debuc( alert(info), 'upsh alert title=titlE message=messagE when=at=9,0', [] ), debuc( alert(info), '', true ), debuc( alert(info), 'with supsh aliased to- upsh p !* >& /dev/null &', [] ), debuc( alert(info), 'supsh alert title=titlE message=messagE when=at=16\\\\:00 type=notify', [] ). alert_opts( Self, Opts ) :- options( when(When), Opts ), options( title(Tit), Opts ), options( message(Msg), Opts ), options( type(Type), Opts ), options( critical(Crit), Opts ), options( timeout(Tout), Opts ), abs_time( When, Delay ), atert( Delay, Self, Tit, Msg, Type, Crit, Tout ). abs_time( in(Rime), Delay ) :- !, ( atom_concat(DelayAtm,s,Rime) -> atom_number( DelayAtm, Delay ) ; ( atom_concat(HoursAtm,h,Rime) -> atom_number( HoursAtm, Hours ), Delay is Hours * 360 ; ( atom_concat(MinAtm,m,Rime) -> atom_number(MinAtm,Min) ; Rime = Min ), Delay is Min * 60 ) ). abs_time( at(Ha,Ma), Delay ) :- abs_time( Ha, Ma, Delay ). abs_time( at(At), Delay ) :- atomic_list_concat( [Ha,Ma], ':', At ), abs_time( Ha, Ma, Delay ). abs_time( Ha, Ma, Delay ) :- get_time( NowStamp ), stamp_date_time( NowStamp, Now, local ), Now =.. [T0,TY,TM,TD,_TH,_TN,_TS,T7,T8,T9], ( number(Ha) -> Ha = HH ; atom_number(Ha, HH) ), ( number(Ma) -> Ma = MN ; atom_number(Ma, MN) ), AtD =.. [T0,TY,TM,TD,HH,MN,0,T7,T8,T9], date_time_stamp( AtD, AtStamp ), Delay is AtStamp - NowStamp, check_delay( Delay ). atert( Delay, Self, Tit, Msg, Type, Crit, Tout ) :- debuc( Self, 'Sleeping for : ~w secs.', [Delay] ), sleep( Delay ), debuc( Self, 'Title: ~w', [Tit] ), debuc( Self, 'Msg: ~w', [Tit] ), get_time( NowStamp ), stamp_date_time( NowStamp, Now, local ), Now =.. [_T0,_TY,_TM,_TD,TH,TN,_TS,_T7,_T8,_T9], atomic_list_concat( [TH,':',TN,'\n',Msg], '', Full ), aterty( Type, Tit, Full, Crit, Tout, Self ). aterty( both, Tit, Msg, Crit, Tout, Self ) :- !, debuc( Self, 'Creating messages for both commands.', true ), aterty( notify, Tit, Msg, Crit, Tout, Self ), aterty( zenity, Tit, Msg, Crit, Tout, Self ). aterty( notify, Tit, Msg, Crit, Tout, Self ) :- !, ( Crit == true -> ( Tout == false -> Goal = 'notify-send'('--urgency=critical',Tit,Msg) ; atom_concat( '--expire-time=', Tout, Exp ), Goal = 'notify-send'('--urgency=critical',Exp,Tit,Msg) ) ; ( Tout == false -> Goal = 'notify-send'(Tit,Msg) ; atom_concat( '--expire-time=', Tout, Exp ), Goal = 'notify-send'(Exp,Tit,Msg) ) ), debuc( Self, 'Sending: ~w', [Goal] ), @ Goal. aterty( zenity, Tit, Msg, _Crit, Tout, Self ) :- !, ( Tout == false -> Goal = zenity(--info,--title,Tit,--text,Msg) ; atom_concat('--timeout=',Tout,Exp), Goal = zenity(Exp,--warning,--title,Tit,--text,Msg) ), debuc( Self, 'Sending: ~w', Goal ), ( @ Goal -> true; true ). check_delay( Delay ) :- Delay < 0, !, throw( negative_delay(Delay) ). check_delay( _ ).