Basic Input from the Command Line in Rebol - user-input

I am currently in the process of learning Rebol.
In other languages I know, I can read input from the command line, for example in Java:
Scanner sc = new Scanner(System.in)
sc.nextLine();
In C#
Console.ReadLine();
In C
scanf("%s", s);
I was wondering how one would accomplish the same thing in Rebol.

You can use the input command to ask for input at the console.
>> name: input
Joe
== "Joe"

The ask function complements input by printing a string prior to requesting input:
age: ask "How old are you? "
It also has a /hide refinement to conceal input:
pass: ask/hide "Enter your password: "
At this time, /hide is not implemented in Rebol 3 alphas
A longer answer (and for intermediate-level at least) would include monitoring the system/ports/input port (you can do source input for how this is done for you)—this can be used in cases where input doesn't originate at the console (such as shell, CGI).

Related

Redirect stio and still printing in the terminal

Thanks to this great answer from #Przemyslaw Szufel, we can easily redirect stdio output into a file providing its path.
I wanted to know if it is possible to both redirect stio output to a file and still continue print it in the terminal. That is probably an easy feature to achieve but I could not find it!
And obviously not running the code twice :)
You need a Tee Stream such as https://github.com/fredrikekre/TeeStreams.jl/.
Unfortunately the interface of redirect_stdio does not accept abstract IO for its sink. It requires it to be an IOStream which is a concrete Julia type.
So it seems like there is no good way with the redirect_stdio via streams.
However redirect_stdio does accept sockets and named pipes and this is a way you could consider (yet too complex for this simple tasks - maybe someone finds a more elegant solution).
First you need to create a pipe server that will be running asynchronously in your REPL session (this is code for Windows for Linux you will probably need to remove \\.\pipe\ from the pipe name):
using Sockets
srv = Sockets.listen(raw"\\.\pipe\TeePipe")
mystdout = stdout
#async begin
open("log.txt", "w") do f
sock = accept(srv)
while !eof(sock)
line = readline(sock)
println(mystdout, line)
flush(mystdout)
println(f, line)
flush(f)
end
end
end
Now at the same REPL session you create the client:
teelogger = Sockets.connect(raw"\\.\pipe\TeePipe")
And here is a sample REPL session showing that this works:
julia> redirect_stdio(stdout=teelogger) do
println("Line1")
println("Line2")
#show 3+4
end
Line1
Line2
3 + 4 = 7
7
shell> more log.txt
Line1
Line2
3 + 4 = 7

Perl interface with Aspell

I am trying to identify misspelled words with Aspell via Perl. I am working on a Linux server without administrator privileges which means I have access to Perl and Aspell but not, for example, Text::Aspell which is a Perl interface for Aspell.
I want to do the very simple task of passing a list of words to Aspell and having it return the words that are misspelled. If the words I want to check are "dad word lkjlkjlkj" I can do this through the command line with the following commands:
aspell list
dad word lkjlkjlkj
Aspell requires CTRL + D at the end to submit the word list. It would then return "lkjlkjlkj", as this isn't in the dictionary.
In order to do the exact same thing, but submitted via Perl (because I need to do this for thousands of documents) I have tried:
my $list = q(dad word lkjlkjlkj):
my #arguments = ("aspell list", $list, "^D");
my $aspell_out=`#arguments`;
print "Aspell output = $aspell_out\n";
The expected output is "Aspell output = lkjlkjlkj" because this is the output that Aspell gives when you submit these commands via the command line. However, the actual output is just "Aspell output = ". That is, Perl does not capture any output from Aspell. No errors are thrown.
I am not an expert programmer, but I thought this would be a fairly simple task. I've tried various iterations of this code and nothing works. I did some digging and I'm concerned that perhaps because Aspell is interactive, I need to use something like Expect, but I cannot figure out how to use it. Nor am I sure that it is actually the solution to my problem. I also think ^D should be an appropriate replacement for CTRL+D at the end of the commands, but all I know is it doesn't throw an error. I also tried \cd instead. Whatever it is, there is obviously an issue in either submitting the command or capturing the output.
The complication with using aspell out of a program is that it is an interactive and command-line driver tool, as you suspect. However, there is a simple way to do what you need.
In order to use aspell's command list one needs to pass it words via STDIN, as its man page says. While I find the GNU Aspell manual a little difficult to get going with, passing input to a program via its STDIN is easy enough and we can rewrite the invocation as
echo dad word lkj | aspell list
We get lkj printed back, as due. Now this can run out of a program just as it stands
my $word_list = q(word lkj good asdf);
my $cmd = qq(echo $word_list | aspell list);
my #aspell_out = qx($cmd);
print for #aspell_out;
This prints lines lkj and asdf.
I assemble the command in a string (as opposed to an array) for specific reasons, explained below. The qx is the operator form of backticks, which I prefer for its far superior readability.
Note that qx can return all output in a string, if in scalar context (assigned to a scalar for example), or in a list when in list context. Here I assign to an array so you get each word as an element (alas, each also comes with a newline, so may want to do chomp #aspell_out;).
Comment on a list vs string form of a command
I think that it's safe to recommend to use a list-form for a command, in general. So we'd say
my #cmd = ('ls', '-l', $dir); # to be run as an external command
instead of
my $cmd = "ls -l $dir"; # to be run as an external command
The list form generally makes it easier to manage the command, and it avoids the shell altogether.
However, this case is a little different
The qx operator doesn't really behave differently -- the array gets concatenated into a string, and that runs. The very fact that we can pass it an array is incidental, and not even documented
We need to pipe input to aspell's STDIN, and shell does that for us simply. We can use a shell with command's LIST form as well, but then we'd need to invoke it explicitly. We can also go for aspell's STDIN by means other than the shell but that's more complex
With a command in a list the command name must be the first word, so that "aspell list" from the question is wrong and it should fail (there is no command named that) ... except that in this case it wouldn't (if the rest were correct), since for qx the array gets collapsed into a string
Finally, apsell nicely exposes its API in a C library and that's been utilized for the module you mention. I'd suggest to install it as a user (no privileges needed) and use that.
You should take a step back and investigate if you can install Text::Aspell without administrator privilige. In most cases that's perfectly possible.
You can install modules into your home directory. If there is no C-compiler available on the server you can install the module on a compatible machine, compile and copy the files.

python subprocess pipe comparing string - removing rubbish

I have a c program that reads a rfid tag. I am trying to get output from that c program (it uses sudo and args) and compare it to a string
Here is my code as well as some debugging information.
import subprocess
#args - the c program and its args
args = ["sudo", "./rc522", "-r", "-b", "1"]
process = subprocess.Popen(args,stdout=subprocess.PIPE,stderr=None)
rfidRead=process.communicate()[0]
rfidRead=rfidRead.decode('utf-8')
print (len(rfidRead))
rfidRead = rfidRead[14:440]
print (len(rfidRead))
print (rfidRead)
if "49.4f.09.0a.0c.0f.00.00.00.00.00.00.00.00.00.00" in rfidRead:
print("unlocked")
else:
print("Not unlocked")
here is the output...
446
426
49.4f.09.0a.0c.0f.00.00.00.00.00.00.00.00.00.00
Not unlocked
I just cant find the hidden characters and things from the pipe output
Can you help please?
This is the rfidRead output using repr:
'\x1b[1;93m4\x1b[00m\x1b[1;93m9\x1b[00m.\x1b[1;93m4\x1b[00m\x1b[1;93mf\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m9\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93ma\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93mc\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93mf\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0\x1b[00m.\x1b[1;93m0\x1b[00m\x1b[1;93m0'
I worked out the answer with the help of jasonharper.
After doing the repr(...) I decided to google \x1b and found a stackoverflow article about vt100 and that this is vt100 code, so I did another google search to decode vt100, and I got a regular expression to remove the escape codes... here is the article I found. How can I remove the ANSI escape sequences from a string in python

How to take a substring with the endpoint being a carriage return and/or line feed?

How do I take a substring where I don't know the length of the thing I want, but I know that the end of it is a CR/LF?
I'm communicating with a server trying to extract some information. The start point of the substring is well defined, but the end point can be variable. In other scripting languages, I'd expect there to be a find() command, but I haven't found one in PowerShell yet. Most articles and SE questions refer to Get-Content, substring, and Select-String, with the intent to replace a CRLF rather than just find it.
The device I am communicating with has a telnet-like command structure. It starts out with it's model as a prompt. You can give it commands and it responds. I'm trying to grab the hostname from it. This is what a prompt, command, and response look like in a terminal:
TSS-752>hostname
Host Name: ThisIsMyHostname
TSS-752>
I want to extract the hostname. I came across IndexOf(), which seems to work like the find command I am looking for. ":" is a good start point, and then I want to truncate it to the next CRLF.
NOTE: I have made my code work to my satisfaction, but in the interest of not receiving anymore downvotes (3 at the time of this writing) or getting banned again, I will not post the solution, nor delete the question. Those are taboo here. Taking into account the requests for more info from the comments has only earned me downvotes, so I think I'm just stuck in the SO-Catch-22.
You could probably have found the first 20 examples in c# outlining this exact same approach, but here goes with PowerShell examples
If you want to find the index at which CR/LF occurs, use String.IndexOf():
PS C:\> " `r`n".IndexOf("`r`n")
2
Use it to calculate the length parameter argument for String.Substring():
$String = " This phrase starts at index 4 ends at some point`r`nand then there's more"
# Define the start index
$Offset = 4
# Find the index of the end marker
$CRLFIndex = $string.IndexOf("`r`n")
# Check that the end marker was actually found
if($CRLFIndex -eq -1){
throw "CRLF not found in string"
}
# Calculate length based on end marker index - start index
$Length = $CRLFIndex - $Offset
# Generate substring
$Substring = $String.Substring($Offset,$Length)

Call custom vim completetion menu with Information from Perl-Script

I wrote a script analyzing perl-files (totally without PPI, because it will be used on Servers where the admins don't want PPI to be installed and so on and so forth, but let's not talk about that).
Now, let's say I have this code:
my $object = MySQL->new();
my $ob2 = $object;
$ob2->
(Where MySQL is one of our modules).
My script correctly identifies that $ob2 is a MySQL-Object and sees where it came from, and then returns a list of found subs in that module.
My idea was, that, since I use vim for editing, this could be a really cool way for "CTRL-n"-Completetion.
So, when...
$ob2->[CTRL-n]
It shows the CTRL-n-Box which opens my Perl-Script and gives it a few parameters (I would need: The line that I am actually on, the cursor position and the whole file as it is in vim).
I already found things like vim-perl, which allows me to write something like
if has('perl')
function DefPerl()
perl << EOF
use MyModule;
return call_to_my_function(); # returns all the methods from the object for example
EOF
endfunction
call DefPerl()
endif
But somehow this does not get executed (I tried writing something to a file with a system call just for the sake of testing)...
So, in short:
Does anyone here know how to achieve that? Calling a perl-function from vim by pressing CTRL-n with the full file-code and the line vim is actually in and the position, and then opening a completetion-menu with the results it got from the perl-script?
I hope someone knows what I mean here. Any help would be appreciated.
The details and tips for invoking embedded Perl code from Vim can be found in this Vim Tips Wiki article. Your attempts are already pretty close, but to return stuff from Perl, you need to use Vim's Perl API:
VIM::DoCommand "let retVal=". aMeaningfullThingToReturn
For the completion menu, your Perl code needs to return a List of Vim objects that adhere to the format as described by :help complete-items. And :help complete-functions shows how to trigger the completion. Basically, you define an insert-mode mapping that sets 'completefunc' and then trigger your function via <C-x><C-u>. Here's a skeleton to get your started:
function! ExampleComplete( findstart, base )
if a:findstart
" Locate the start of the keyword.
let l:startCol = searchpos('\k*\%#', 'bn', line('.'))[1]
if l:startCol == 0
let l:startCol = col('.')
endif
return l:startCol - 1 " Return byte index, not column.
else
" Find matches starting with a:base.
let l:matches = [{'word': 'example1'}, {'word': 'example2'}]
" TODO: Invoke your Perl function here, input: a:base, output: l:matches
return l:matches
endif
endfunction
function! ExampleCompleteExpr()
set completefunc=ExampleComplete
return "\<C-x>\<C-u>"
endfunction
inoremap <script> <expr> <Plug>(ExampleComplete) ExampleCompleteExpr()
if ! hasmapto('<Plug>(ExampleComplete)', 'i')
imap <C-x><C-z> <Plug>(ExampleComplete)
endif