I tried with, c::Char = read(stdin, Char);
It reads character(s) from keyboard only after hitting enter but not upon every keydown/release.
Please guide me in reading keyboard input upon key press or release!
Update 1:
function quit()
print("Press q to quit!");
opt = getc1();
while true
if opt = 'q'
break;
else
continue;
end
end
end
throws error:
TypeError:non-boolean(Int64) used in boolean context.
Please help me!
This is not that simple.
You can try this more low-level solution:
function getc1()
ret = ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, true)
ret == 0 || error("unable to switch to raw mode")
c = read(stdin, Char)
ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, false)
c
end
or this more higher level one:
function getc2()
t = REPL.TerminalMenus.terminal
REPL.TerminalMenus.enableRawMode(t) || error("unable to switch to raw mode")
c = Char(REPL.TerminalMenus.readKey(t.in_stream))
REPL.TerminalMenus.disableRawMode(t)
c
end
depending on what you need (or write yet another implementation using the ideas here). The key challenge is that "normal keys", like ASCII are always processed correctly. However, the solutions differ in the way how they handle characters like 'ą' (some character that is larger UNICODE) or UP_ARROW (when you press arrow up on the keyboard) - you here have to experiment and decide what you want (or maybe it is enough for you to read UInt8 values one by one and manually reconstruct what you want?).
EDIT
The problem is with your quit function. Here is how it should be defined:
function quit()
print("Press q to quit!");
while true
opt = getc1();
if opt == 'q'
break
else
continue
end
end
end
The following example may be helpful:
import REPL
function wait_for_key( ;
io_in::IO = stdin,
io_out::IO = stdout,
prompt::String = "press any key [d]raw [n]odraw [q]uit : ",
)
print(io_out, prompt)
t = REPL.TerminalMenus.terminal
REPL.Terminals.raw!(t, true)
char = read(io_in, Char)
REPL.Terminals.raw!(t, false)
write(io_out, char)
write(io_out, "\n")
return char
end
Related
I have an endless cycle going on. How do I stop the program to output the answer? The meaning of my program: reads all characters (including enter) and outputs the sum of only numbers.
fun main() {
fun StrToSum(str: String): Long {
var sum : Long = 0
var next = ""
for (symbol in str + " ") {
if (symbol == '-') {
if ((next != "-") && (next != "")) {
sum += next!!.toLong()
}
next = symbol.toString()
} else if (symbol.isDigit()) {
next += symbol
} else if (next != "") {
if (next != "-") {
sum += next!!.toLong()
}
next = ""
}
}
return sum
}
var string: String = ""
while (1<2) { //How stop it ?
var str = readLine()!!.toString()
string += " " + str
}
println (StrToSum(string)) //answer
}
maybe there is some kind of keyboard shortcut ? I work for IntelliJ from Jetbrains
You can terminate the currently running program, but that will kill it - it won't be able to output the answer. You need to code that handling as part of your design, so you enable the user to finish and print your result.
The usual way people do this is to have some kind of cancel input, like entering an x or something:
// while (true) is a typical way to create an infinite loop
while (true) {
var str = readLine()!!.toString()
// look for the cancel token, break out of the loop if you see it
if (str.lowercase() == "x") break
string += " " + str
}
If you don't want to do that (remember you can make the cancel token anything, like the word "cancel" if you like, and put a prompt on the screen telling the user to type it to finish) then you'd have to do something like detecting other keycodes like Ctrl+Z or whatever - and I'm not sure how you'd do that from a basic command-line program reading from standard input. Maybe someone knows some tricks you could use! It's not something I've ever had to do, so I can't help you there
edit If you're happy to just look for control characters like ^D in the lines of standard input, you could do this kind of thing
if (str.firstOrNull().code == 4) break // char value for ^D
But that still requires the user to press Enter after the Ctrl+D, so the line including that character can be sent from the terminal to standard input. That's just how it works, outside of the solutions in the discussion I linked which involve OS-level interaction or building a GUI so you have access to the raw keypresses.
Zig's documentation shows different methods of error handling including bubbling the error value up the call stack, catching the error and using a default value, panicking, etc.
I'm trying to figure out how to retry functions which provide error values.
For example, in the below snippet from ziglearn, is there a way to retry the nextLine function in the event that a user enters greater than 100 characters?
fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
var line = (try reader.readUntilDelimiterOrEof(
buffer,
'\n',
)) orelse return null;
// trim annoying windows-only carriage return character
if (#import("builtin").os.tag == .windows) {
return std.mem.trimRight(u8, line, "\r");
} else {
return line;
}
}
test "read until next line" {
const stdout = std.io.getStdOut();
const stdin = std.io.getStdIn();
try stdout.writeAll(
\\ Enter your name:
);
var buffer: [100]u8 = undefined;
const input = (try nextLine(stdin.reader(), &buffer)).?;
try stdout.writer().print(
"Your name is: \"{s}\"\n",
.{input},
);
}
This should do what you want.
const input = while (true) {
const x = nextLine(stdin.reader(), &buffer) catch continue;
break x;
} else unreachable; // (see comment) fallback value could be an empty string maybe?
To break it down:
instead of try, you can use catch to do something in the case of an error, and we're restarting the loop in this case.
while loops can also be used as expressions and you can break from them with a value. they also need an else branch, in case the loop ends without breaking away from it. in our case this is impossible since we're going to loop forever until nextLine suceeds, but if we had another exit condition (like a limit on the number of retries), then we would need to provide a "fallback" value, instead of unreachable.
You can also make it a one-liner:
const input = while (true) break nextLine(stdin.reader(), &buffer) catch continue else unreachable;
Hopefully the new self-hosted compiler will be able to pick up on the fact that the else branch is not necessary, since we're going to either break with a value loop forever.
What shoud I do to execute some code (ie: MsgBox "Hello") by:
Pressing win+m
Unpressing m whithout unpressing win
Pressing p
Seems like there's a good answer already, I just wanted to input what I could think of, so here's a version of the earlier answer, but without Sends.
I'd say a solution without them is always desirable, though, of course, in something as small as this, you'll struggle to find any difference in practice.
;runs after m is released on a LWin+m press
<#m up::
Hotkey, <#p, WinMP_Callback, On ;Enable LWin+p hotkey
KeyWait, LWin ;wait for LWin to be released
if (A_PriorKey = "m")
WinMinimizeAll ;keep win+m functional
Hotkey, <#p, , Off ;disable LWin+p hotkey
return
WinMP_Callback()
{
;do stuff
;add this at the end if you dont want
;to be able to keep running this function
;on subsequent presses of p before LWin is released
;Hotkey, <#p, , Off
}
So pretty much what the difference here is toggling the LWin+p hotkey on and off and just using WinMinimizeAll instead of sending LWin+m, since they're the same thing.
Try this:
<#m:: ; "<#" means "LWin"
LWin_m := true ; assign the Boolean value "true" or "1" to this variable
KeyWait, LWin, L ; wait for LWin to be released
LWin_m := false
return
<#p::
If (LWin_m) ; If this variable has the value "true"
msgbox "Hello"
; else
; do sth else
return
EDIT:
For not losing normal win+m and win+p try this:
<#m:: ; "<#" means "LWin"
LWin_m := true ; assign the Boolean value "true" or "1" to this variable
KeyWait, LWin, L ; wait for LWin to be released
If (A_PriorKey = "m")
Send #m
LWin_m := false
return
<#p::
If (LWin_m) ; If this variable has the value "true"
msgbox "Hello"
else
Send #p
return
I am new to elixir, having hard time with updating the variables. Need some help. I have two Maps
firstMsg = %{msg: "Hello", vt: %{"p1" => 1, "p2" => 1, "p3" => 1}, from: "p3"}
state = %{ :name => "p2",
vector: %{"p1" => 0, "p2" => 0, "p3" => 0},
participants: ["p1","p3","p2"]
}
I am passing these two maps in a function, which should return me either true or false, depending on some conditions.
defmodule Testfunc do
def keep_in_pending(firstMsg, state) do
if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do
#IO.puts("Origin proc clock is 1 step ahead from rcvd process Origin clk")
checking = false #initially set this to false
for n <- state.participants do
if n != firstMsg.from do #filter the origin processes
IO.puts("#{n}: #{inspect firstMsg.vt[n]} <= #{n}: #{inspect state.vector[n]} ")
checking = cond do
(firstMsg.vt[n] <= state.vector[n]) -> false
(firstMsg.vt[n] > state.vector[n]) -> true
end
end
end
end
checking
end
end
out = Testfunc.keep_in_pending(firstMsg, state)
IO.puts("#{inspect out}")
It always gives me false (value that I initially assigned to it), and doesn't updates. I think the scope of variable is restricted to the inner "if". Can anyone give me suggestion on how to re arrange this code so that it returns me proper updated boolean value ?
So in this case it should return me true because firstMsg.vt["p1"] > state.vector["p1"].
Welcome to Elixir. You're right, it is a matter of scope, but it runs a bit deeper than that. Elixir is a language where your data is immutable. You can't set checked to false, run a loop, and set it to true somewhere in that loop. That would mutate checked. It's not that someone designed devilish scope rules to prevent this, but rather that the underlying virtual machine doesn't mutate state.
The style of programming where you set some state, then run a procedure that changes that state, relies on mutable state. When state is immutable, the alternative to a loop is instead recursion. You carry new state in every recursive call.
You're learning a functional language, and I think it will be helpful to pull apart your code into a few functions. This will both address your immediate concern, and make your code easier to understand.
def keep_in_pending(%{from: from, vt: vt}, %{vector: vector, participants: ps}) do
if vt[from] == vector[from] + 1 do
ps
|> Enum.reject(& &1 == from)
|> check_participants(vector, vt, false)
end
end
def check_participants([], _, _, bool), do: bool
def check_participants([h | t], vector, vt, bool) do
check_participants(t, vector, vt, vt[h] > vector[h])
end
I'll briefly explain it.
First, note that I've pattern matched the inputs, to pull out the interesting parts we're using in the function body. This gets rid of some of the repetitive firstMsg.from business. (Btw, snake_case your variable names.)
Second, I haven't touched the gnarly outer if-condition. I simply don't know what it means. You should perhaps extract it and give it an intention revealing name.
The real action begins when we pipe participants. You were filtering inside your list comprehension. I've filtered with Enum.reject/1 instead. Then we pipe the list into a recursive function. It's going to carry the boolean through to the end, starting off with false. It needs to check values in vt and vector, so they're also passed in.
The first rule of recursion is the first rule of recursion. No, wait. It's to think about how to terminate the recursion. We're working through a list of participants, so we'll stop when the list is empty. At that point, we have the boolean we're looking for, so just return it.
The recursive step is to pick off an item from the list (h), use it to determine a new boolean (vt[h] > vector[h]) and call the function again with the rest of the list (check_participants(t, ...)).
Hope this helps! Have fun learning functional programming!
So here is an idea: if you are trying to make a function return a boolean, just make it return a boolean, don't assign it to a variable. Assigning inside an if/case/cond will show a warning. Also, you are not reassigning the checking because variables bound inside the comprehension (for) are restricted to that scope. Your best tools in Elixir will be first pattern matching and second the pipe operator, so always try to use them.
Here is an idea to refactor that code:
defmodule Testfunc do
def keep_in_pending(firstMsg, state) do
if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do
state.participants
|> Enum.filter(fn (n) -> n != firstMsg.from end)
|> Enum.reduce(fn (n, _) ->
cond do
(firstMsg.vt[n] <= state.vector[n]) -> false
(firstMsg.vt[n] > state.vector[n]) -> true
end
end)
end
end
end
I wrote a program that will determine whether some imaginary school would have a snow day or not. I have the program working correctly I'm just having an issue.
Basically what I want is for the True/False to be Y/N. And later when I print SnowDay --tells whether there's a snow day. Then it will print either "Yes" or "No" instead of "True" or "False"
SofieAssignment : Boolean;
SnowDay : Boolean;
.
.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Get(Item => SophieAssignment);
.
.
Put(Item => "Should we have a snow day today? " & Boolean'Image (SnowDay));
Assuming I understand what you're trying to do:
(1) If you want the user to enter Y or N for SophieAssignment, there are a couple possibilities:
You can input a string and analyze the string yourself.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
declare
Answer : String := Get_Line; -- Get_Line is in Ada.Text_IO
begin
if Answer = "Y" or else Answer = "y" or else Answer = "Yes" or else
Answer = "yes" then
SophieAssignment := True;
elsif Answer = "N" or else Answer = "n" or else Answer = "No" or else
Answer = "no" then
SophieAssignment := False;
else
-- whatever you want to do for an invalid entry
end if;
end;
(This could be improved, but I'm just trying to cover the fundamental approach.) Another possibility is to define your own enumeration that has the values Y and N:
type Yes_No is (N, Y);
package Yes_No_IO is new Enumeration_IO (Yes_No); -- Enumeration_IO is in Ada.Text_IO
Answer : Yes_No;
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Yes_No_IO.Get(Item => Answer);
SophieAssignment := (Answer = Y);
Get here will set Answer to either Y or N if the user enters the enumeration name (in either case); it will raise Data_Error if something else is entered. I'd prefer the first method if you want better control over how input is handled. For the second, if the user enters "Y Z", Get will return the Y, and the Z is left in the input stream waiting for the next input operation. Also, the first method allows for multiple possible answers better than the second, although you could make it work with an enumeration like
type Yes_No is (N, No, Y, Yes);
(2) To output "Yes" or "No" based on a Boolean, you can use a function as in Keith's answer, or you can set up an array:
type Const_String_Acc is access constant String;
Yes_No_Image : constant array (Boolean) of Const_String_Acc :=
(False => new String' ("No"),
True => new String' ("Yes"));
Put(Item => "Should we have a snow day today? " & Yes_No_Image (SnowDay).all);
To print a Boolean value as "Yes" or "No", just write a function:
function Boolean_Image(B: Boolean) return String is
begin
if B then
return "Yes";
else
return "No";
end if;
end Boolean_Image;
and use it in place of Boolean'Image.
To read a value from the user as Y or y for True, or as N or n for False, just read a Character value and test it to determine which Boolean value to set. Think about how you want to respond if the character the user enters is not any of Y, y, N, or n. You can use Get_Immediate to read a single character without waiting for a newline on input.
type Snow_Day_Type is new Boolean;
function Yes return Snow_Day_Type is (Snow_Day_Type'(True));
function No return Snow_Day_Type is (Snow_Day_Type'(False));