SWI-Prolog stream I/O and tab completion in the swipl-window - io

What I'm Doing
I am currently working on creating a SWI-Prolog module that adds tab-completion capability to the swipl-win window. So far I've actually gotten it to where it reads a single character at a time without stopping/returning anything until a tab character is typed. I have also already written a predicate that returns all possible completions of an incompletely typed term by using substring-matching on a list of current terms (obtained via current_functor/2, current_arithmetic_function/1, current_predicate/2, etc [the predicate used will eventually be based off of context]).
If you want to see my code, it is here...just keep in mind that I'm not exactly a Prolog master yet (friendly tips are more than welcome).
What I'm Thinking
I realize that when I actually implement my main completion predicate (still unwritten), I'll have to figure out what the last "word" is in the input stream. I'm debating on whether I should create a new stream with everything in the input stream so far (so I don't have to change the position in the input stream/go back to the beginning) or write to a string...if I take the second approach, I'll start over on the string whenever a delimiting character is inputted (characters that start a new "word", like space, comma, parentheses, operators, etc.) so there won't be any searching through the stream every time tab is pressed.
However, there is another thing: When the user is navigating through and modifying a typed but not-yet-submitted query (via arrow keys and backspace and such), a separate stream is necessary to handle mid-stream completion. A string will do just fine if completion is requested at the end of a stream (handling backspace is as easy as lopping off the last character of the string), but since the string would only contain the current "word", tabber.pl would be at a loss in instances like that. Unless, of course, the current-word string would update and find the current word that the cursor is in as the user navigated and typed mid-stream... (could I use at_end_of_stream(Stream) for that?)
What I'm Asking
How do you think I ought to approach this (string or stream)? The store-to-string method and the make-a-new-stream way both sound like they each have their advantages, so I'm pretty sure the solution will be some sort of combination of both. Any ideas, corrections, or suggestions on accomplishing my goal? (pun intended)
In order to figure that out and really do this correctly, I think I'll also have to know how SWI-Prolog use the input and output streams in the swipl-win window. (It's obviously accepting input, but does it use the output stream to write to the window as you type [into the input stream]?)

Getting this done without changing the C code underlying the swipl-win.exe console will be hard. This also relates to a thread on the mailing list starting here. The completion caller is in src/pl-ntmain.c, do_complete()
for Windows and src/os/pl-rl.c, prolog_completion() for the GNU readline based completion used on Unix systems.
The first step to make is lead these two and the upcoming one described in the referenced thread back
to Prolog using a callback. That requires a small study of the design of the completion interfaces to arrive at a suitable Prolog callback. I guess that should pass in some representation of the entire line and the caret location and return a list of completions from the caret. With that, anyone can write their own smart completer.

Related

Checking text as you write it

I am writing a function (in Python 3) which will allow someone to revise a set text.
Set texts (in this situation) are pieces of text (I am doing the Iliad, for example) which you need to learn for an exam. In this function I am focusing on a user trying to learn the translation of the text off by heart.
In order to do this, I want to write the translation in a text file, then the user can test themselves by writing it up, and the program will check whether each word is correct by checking it against the known, correct translation.
I know I could simply use input() for this, but it is inadequate as the user would have to type the entire text, or small parts, at a time for this to work, and I want to correct as they type in order for them to remember their mistakes more easily.
I have not written any code yet as how I write the rest of the program will depend on how I code this part.

Defense against approximate string matching

How can I alter a string so that variations of approximate string matching can't match it with the original?
I made an IRCbot which runs a game based on the logfile of the channel. It prints quotes from the logs and players collect points by guessing "who said it". The channel is rather geeky and it took no more than 30 minutes for one of the players to build a bot which wins the game every time. I realize manual cheating is also easy and impossible to defend against, but consider this a competition between automated bots. I want to update my bot so that any fully automated bot will not be able to play the game :)
I've considered randomly deleting a character from the quotes, but agrep would still be able to match the string. I've considered replacing some of the characters by similar-looking alternate characters, but that would be trivial to reverse-engineer. I'm looking for ideas that will be harder to break.
Example line:
[14:15] <baobot> [QUOTE 13/15] Who famously declared "minulla ainakin paperin tekemisessä 1% ajasta menee algon suunnitteluun ja 99% menee paperin kirjoittamiseen"?
Print your quote as ascii-art.
Use something similar to the command-line-tools figlet or toilet (explaination).
Here is a quick example: like string2ascii-generator.
To get you started, you might want to copy the sourcecode from figlet.
Anything that can be used to scramble can most likely be unscrambled. Below are some suggestions though for your experiment:
Humans can read words if the first and last letter are in place and the inner portion is scrambled.
You can also do substitution, such as elite speak to replace some characters with numbers.
You might be able to find other characters in other languages that also look familiar to letters that are used, which means you can randomly substitute them as well.
You can also try to randomize the positions of the spaces. So remove them from the original position then move them around, or remove them completely.
Reverse some words.
Find ways to phoneticized words... in english "ph" sounds like "f" so you can find and replace some of them.
Try a combination of different things above, remove all spaces, CaMEl CaSE words, then do character substitutions, etc.
Overall, there are lots of ways to help make it harder, however if you follow a set pattern every time, then it'll be easier to program something to undo it. If you randomly do different things, so one input can yield several different outputs, then it'll be harder for someone to write a program to reverse the process.
Use Google translate.
For example, I ran your quote to Russian, then to English, and back to Finnish, and got
Minulla on ainakin 1% ajasta kirjassa otetaan suunnittelussa Algon ja 99% menee kirjoituspaperia
I have no idea if it is a correct Finnish; as far as I can tell it is still somewhat recognizable. If you think it is too recognizable for an approximate search, do more intermediate translations.

JCL - Get count of non space chars in a given area (mainframe)

I need to prepare some input data to run through a program, the data should be in the following format.
UID (1-11)|TxtLen (12-16)| Text (17-62)
I can use sort to position the fields properly and get the UID and text fields.
The ‘TxtLen’ is should contain the number of chars from the start of the text field to the last char in the text field.
i.e. “Hello”’s TxtLen is 5, “Hel lo”’s TxtLen is 6, “Hello World”’s TxtLen is 11, etc...
I want to know if there is a way of getting the TxtLen through JCL only, or is a program required to do this?
-Thanks
You will need a program.
I see a fair number of mainframe questions on Stack Overflow asking if something is possible with "JCL only." Keep in mind that JCL is mostly a means of executing programs, and actually does very little other than that. For instance, when you say
I can use sort to position the fields properly and get the UID and
text fields
sort is a program. It happens to be a program found on most systems (though there are different vendors' implementations, IBM has one, SyncSort has one, CA has one, etc.) There are plenty of other programs commonly found on mainframe systems.
And just to be pedantic, JCL doesn't actually do anything, JES does the work as it interprets JCL.
For your particular situation you could create a SORT exit, or process your data in Rexx, or you could use some of the Unix System Services commands and execute those via BPXBATCH or COZBATCH.
I've done ad-hoc conversions like this using a REXX program. The program is pretty straight-forward:
allocate the input and output files
open both files
begin loop:
read the input
extract the text field and strip trailing spaces
get length of trimmed text field and format as 5-digit numeric
overlay number back into record in the Len field positions
write out updated record
repeat loop until end of file
close both files
free allocated files
Let me know if you need some actual code. I've found that REXX is superior than COBOL when it comes to string functions and manipulations. I've even created and called REXX routines from COBOL to accomplish just that.

How do I save the character occupying a certain space in curses?

I'm beginning to try making some simple console games in C++ with curses, and my first project is just a large room to walk around in. I figure I'm gonna implement walking by having the program save the state of the square that the character is walking on, so when he walks onto the next square, it can restore whatever was there. Problem is, I don't know how to save the character at a certain position to a variable, and to my surprise I can't seem to find any comprehensive curses documentation. I'm looking for a function like this:
int storage = mvsavechar(1,1);
Does any such function exist?
You're looking for mvinch():
int storage = mvinch(1, 1) & A_CHARTEXT;
You're going to need to store the data for the room in some sort of data structure in your program. Curses is an output library.
I'd store screen state in a 80x24 (or whatever) char array. But probably you'd size the array to match the dimensions of your "large room". If the room were extremely large, you could store the equivalent of a sparse array by using (for example) a linked list of coordinates&contents.
Curses probably doesn't have the function you want because early terminals probably didn't have the capability of being interrogated about screen contents.
I don't know much about curses, what you want might be possible if curses maintained details of screen contents - but that seems very unlikely.

Search by using the keyboard in a list/grid - algorithm

I need to implement a custom search in a grid and I would like to find some user interface guidelines that explain the standard way to implement it.
I mean this kind of search that is initiated by the user using the keyboard. The focus on the grid must move to the first row that match the pressed key.
I would like to find a good algorithm to do it.
Thanks.
There is no standard way, many grids/lists implement this in different ways and it drives me bonkers. Some only search on the first letter, some search on multiple letters without indicating which ones, others show a (non-modal) window that shows which letters it is currently using, others keep this buffer hidden and use a timeout to reset, other don't reset at all or with a (hidden) key like esc.
From the way you phrase your question it sounds like a simple 'jump to first row that starts with the pressed char' - which is the simplest use case, and I fail to see what the 'algorithm' in this case should do.
If there is a specific application you want to mimic I think you should provide a detailed description of its behavior. Although I think that after making this description, the algorithm will be peanuts.

Resources