So you want to help programming segusoLand, and you need an intro to the code? This is the place.
First of all:
The big advantage of prolog is that the code is very concise and readable.
(For your information, I was formerly a fan of C++ and C#.)
If you don't know Prolog, don't worry, because the main part that needs help is C++ coding. Read the TODO document for additional informations.
This section requires prolog knowledge.
Suppose you want to add to segusoLand a new verb called "view picture", which requires:
You need to add the following prolog facts to the file segusoLand.pl:
verbRequiresAtLeastOneObjectSatisfying('View picture', program, supports('View picture')). verbRequiresAtLeastOneObjectSatisfying('View picture', file, pictureFile).
Let us now comment this code.
verbRequiresAtLeastOneObjectSatisfying('View picture', program, supports('View picture')).means that segusoLand will check, for each program P, whether the following holds:
supports('View picture', P).if true, then he will show the verb when P is selected.
verbRequiresAtLeastOneObjectSatisfying('View picture', file, pictureFile).This means that segusoLand will check, for each file F, whether the following is true:
pictureFile(F).This info is used for narrowing.
supports( 'View picture', 'Kuickshow'). supports( 'View picture', 'Eye of Gnome').
onVerbExecuted('View picture', N, N):- %please don't mind N, N for now :-) selected(program, P), shellName(P, P2), findall(F, selected(file, F), Files), sort(Files, Sorted), fromListOfFilesToQuotedString(Sorted, String), concat_atom([P2, ' ', String, ' &'], Command), writeln(Command), shell(Command, Status), displayProgramNotInstalledIfNecessary(P, Status).Let's comment the code above:
onVerbExecuted('View picture', N, N):- %please don't mind N, N for now :-)This is called when the user presses the "Go" button.
N is the current list of tasks. We leave it unchanged in this simple example, so we output the same N.
selected(program, P),Pick on selected program at random and call it P.
In general, the user can select more than one program, then click GO. It would be nice to display an error message here if there is more than one program selected.
It is also possible to prevent the Go button from appearing if there is more than one program/file/device selected, or less than 523 files selected :-) . For such things you need to add a clause to the predicate selectionIncompatibleWithVerb/1, but I won't describe it in this basic example.
shellName(P, P2),Puts in P2 the shell name of P. (e.g. if P='Kuickshow' then P2='kuickshow').
findall(F, selected(file, F), Files),find the set of all selected files and put it into Files. Files will be a list of atoms, such as
Files = ['file.pdf' , 'file2.pdf' ]Now to the next line:
sort(Files, Sorted),This sets Sorted to be equal to Files, but sorted, and with duplicates removed (actually duplicates shouldn't be unless there is a bug in my code).
fromListOfFilesToQuotedString(Sorted, String),String is a prolog atom obtained concatenating the elements of Sorted. For example
String='file.pdf file2.pdf'A prolog atom can be thought of as a C++ string :-)
concat_atom([P2, ' ', String, ' &'], Command),Command is the atom obtained concatenating P2, '', String, ' &'. In other words, Command will be something like
Command='kuickshow file1.gif file2.gif &'now to the next line:
writeln(Command),this outputs the command for debug purposes.
shell(Command, Status),This executes Command as a CLI command, and sets Status = 0 (success) or 1 (failure)
displayProgramNotInstalledIfNecessary(P, Status).gives an error message if Status = 0 and the program is not installed.
Let us implement the verb "Mail to...", which requires:
This time we will take the time into account. The current implementation is the following:
verbRequiresAtLeastOneObjectSatisfying('Mail to...', file, anyFile). verbRequiresAtLeastOneObjectSatisfying('Mail to...', program, supports('Mail to...')). supports( 'Mail to...', 'Kmail'). onVerbExecuted('Mail to...', Tasks, NewTasks):- selected(program, 'Kmail'), createActionFromSelection('Mail to...', A), % REGION choose one time at random. @@ we should process all selected times! selected(time, T), convertTimeToNumber(T, N), % END NewTasks2 = [(N, A) | Tasks], onTimer(NewTasks2, NewTasks). executeActionNow(['Mail to...', Files, Programs, _]):- (Programs\=['Kmail'] -> writeln(error-program-should-be-kmail); true), sort(Files, SortedFiles), fromListOfFilesToQuotedString(SortedFiles, String), concat_atom(['kmail --attach ', String, ' &'], Command), writeln(Command), shell(Command, _), addStringToLog('Sent file by mail').Let us comment this code.
verbRequiresAtLeastOneObjectSatisfying('Mail to...', file, anyFile).This should be familiar. segusoLand will check, for each file F, whether
anyFile(F)holds. And this always holds, since anyFile/1 is defined as
anyFile(_).:-) Now to the next line: [TO BE CONTINUED]