Kotlin Comparison between BufferedReader::readText and String always false - kotlin

I read stdin and stderr from the command-line using:
fun runCommand(vararg commands: String): Pair<String, String> {
val proc = Runtime.getRuntime().exec(commands)
val stdIn = BufferedReader(InputStreamReader(proc.inputStream))
val stdErr = BufferedReader(InputStreamReader(proc.errorStream))
val p = Pair(stdIn.use(BufferedReader::readText).trim(), stdErr.use(BufferedReader::readText).trim())
stdIn.close();
stdErr.close();
return p;
}
This gives me a Pair of <String, String> with the output of stdin and stderr.
However, no matter how I try to compare these Strings to another String, the comparison always returns false.
Things I've tried:
runCommand("nordvpn", "account").first.compareTo("You are not logged in.")
runCommand("nordvpn", "account").first == "You are not logged in."
runCommand("nordvpn", "account").first.equals("You are not logged in.")
Might this have something to do with the encoding?
Or am I just reading the output incorrectly?
Any help would be appreciated!

Thanks to #gidds' comment I was able to find that for some reason the output of the command (stdout) had "-CR SP SP CR" (- CarriageReturn Space Space CarriageReturn" prepended, which I removed with a simple String.drop(5).
Edit: After some more thinking, I assume that the aforementioned charts were responsible for making the output of the command in the terminal colored (yellow)

Related

How to get rid of \r\n from a string?

I recently had to upgrade to Jython 2.7.2. I send in a Java map instance into my python script.
Previously my python script would print out the key, value in the map as in the below format
message: Community: public
This same string now appears as
u'message': u'Community:\t\tpublic\r
I managed to get rid of the u' prefix by doing the following
encode(encoding = 'UTF-8', errors = 'strict')
But am still left with the \t\r in the string
'message': 'Community:\t\tpublic\r
and it feels very clumsy to manually remove these from the string. Is there any good utility method that would help me to preserve the pre 2.7.7 handling of strings?
Normally the character \r comes from a windows' file and the easiest way to get rid of them is just use replace
mystring = u'asd\r'
mystring = mystring.replace("\r", "")
print(repr(mystring))
Gives the output:
u'asd'
Why not use the toString() method and then replace the unwanted characters?
Sample code:
import java.util.HashMap as HashMap
import re
def test_2():
my_map = HashMap()
inner_map = HashMap()
inner_map.put("community", "public")
my_map.put("message", inner_map)
print re.sub(r"[{}]*", "", my_map.toString()).replace("=", ": ")
if __name__ == '__main__':
test_2()
Output:
message: community: public

first `readLine` is skipped inside a `case - of` control flow in Nim-lang

I have the following code.
import lib
var stat = false
when isMainModule:
while stat != true:
echo("Option: ")
var opt = readChar(stdin)
case opt
of 'q':
stat = true
of 'n':
echo("Salu: ")
var ss = readLine(stdin)
echo("Nam: ")
var nn = readLine(stdin)
let k = prompt("Rust")
else: discard
What I am trying to achieve is, prompting and receiving user input one after another for two variables. Upon choosing n I am expecting Salu first and once user input is supplied then Nam.
However, what I receive when I execute the following nim code by issuing the following command is, nim c -r src/mycode.nim
~~> nim c -r src/cmdparsing.nim
...
...
...
CC: stdlib_system.nim
CC: cmdparsing.nim
Hint: [Link]
Hint: operation successful (48441 lines compiled; 2.338 sec total; 66.824MiB peakmem; Debug Build) [SuccessX]
Hint: /home/XXXXX/Development/nim_devel/mycode/src/mycode [Exec]
Option:
n
Salu:
Nam:
Salu is being echoed, but readLine doesn't wait for my input and immediately echoes Nam. But, stacked readLine commands from the prompt procedure appears one after the other for receiving user input.
I was wondering what is that I am missing to understand here. Could someone enlighten me?
Code for prompt lives in lib.nim which is as follows,
proc prompt*(name: string): bool =
echo("Salutation: ")
var nn = readLine(stdin)
echo(nn&"."&name)
echo("Diesel")
var dd = readLine(stdin)
echo(dd)
return true
You do a readChar to get the opt value, and then you input two chars: n and \n. The first is the opt value, the second gets buffered or retained in the stdin waiting for further reading. The next time you try to read a line, the \n that's still hanging is interpreted as a new line, and immediately assigned to ss. You don't see anything because the line is empty except for the newline char.
E.g.
var opt = readChar(stdin)
case opt
of 'n':
var ss = readLine(stdin)
echo ss
else:
discard
Compile and run, but in the input write something like "ntest". n fires the first branch of case, test (the remainder of stdin) is assigned to ss, and echoed.
You have two options to solve the problem:
Read a line instead of a char, and store only the first char with something like var opt = readLine(stdin)[0].
Use the rdstdin module:
import rdstdin
var ss = readLineFromStdin("Salu:")

How to write a string to clipboard (Windows OS) with a Kotlin/Native application?

I'm very new to Kotlin and making a command line .exe, on Windows using Kotlin/Native. The application should read from a text file and print on screen, line by line. When it reaches the last line of the file, it should put it in the clipboard.
aFile.txt looks something like this:
one
two
three
...
...
the last line
and the code read.kt (Kotlin/Native) I have so far is this:
import kotlinx.cinterop.*
import platform.posix.*
fun main(args: Array<String>) {
if (args.size != 1) {
println("Usage: read.exe <file.txt>")
return
}
val fileName = args[0]
val file = fopen(fileName, "r")
if (file == null) {
perror("cannot open input file $fileName")
return
}
try {
memScoped {
val bufferLength = 64 * 1024
val buffer = allocArray<ByteVar>(bufferLength)
do {
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
if (nextLine == null || nextLine.isEmpty()) break
print("${nextLine}")
} while (true)
}
} finally {
fclose(file)
}
}
The code above prints each line on the screen, but how do I write the string "the last line" in the computer's clipboard? I'm looking for a native (not Java) solution if that's possible.
Thank you very much.
Update:
Obviously, this is not the solution I was looking for, but I don't understand yet what are they talking about here (https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setclipboarddata).
As a temporary fix, I was able to get what I needed using system(), echo and clip with code like this:
system("echo ${nextLine} | clip")
print("${nextLine}")
Try the following:
import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.StringSelection
fun setClipboard(s: String) {
val selection = StringSelection(s)
val clipboard: Clipboard = Toolkit.getDefaultToolkit().systemClipboard
clipboard.setContents(selection, selection)
}
In Windows, you can work with the Clipboard through WinAPI, as you can see there. The reference says, that you got to use functions from the winuser.h header. This header is included in windows.h, as far as I know, so it is in your platform.windows.* package. You can approve it by checking Kotlin/Native repository files.
To clarify, what I meant, I wrote this small example of platform.windows.* usage. You can add this function to your code, and call it when you got to copy some string.
import platform.windows.*
fun toClipboard(lastLine:String?){
val len = lastLine!!.length + 1
val hMem = GlobalAlloc(GMEM_MOVEABLE, len.toULong())
memcpy(GlobalLock(hMem), lastLine.cstr, len.toULong())
GlobalUnlock(hMem)
val hwnd = HWND_TOP
OpenClipboard(hwnd)
EmptyClipboard()
SetClipboardData(CF_TEXT, hMem)
CloseClipboard()
}

How to test the passing of arguments in Golang?

package main
import (
"flag"
"fmt"
)
func main() {
passArguments()
}
func passArguments() string {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
usernameToString := *username
return usernameToString
}
Passing an argument to the compiled code:
./args -user=bla
results in:
Your username is "bla"
the username that has been passed is displayed.
Aim: in order to prevent that the code needs to be build and run manually every time to test the code the aim is to write a test that is able to test the passing of arguments.
Attempt
Running the following test:
package main
import (
"os"
"testing"
)
func TestArgs(t *testing.T) {
expected := "bla"
os.Args = []string{"-user=bla"}
actual := passArguments()
if actual != expected {
t.Errorf("Test failed, expected: '%s', got: '%s'", expected, actual)
}
}
results in:
Your username is "root".Your username is "root".--- FAIL: TestArgs (0.00s)
args_test.go:15: Test failed, expected: 'bla', got: 'root'
FAIL
coverage: 87.5% of statements
FAIL tool 0.008s
Problem
It looks like that the os.Args = []string{"-user=bla is not able to pass this argument to the function as the outcome is root instead of bla
Per my comment, the very first value in os.Args is a (path to) executable itself, so os.Args = []string{"cmd", "-user=bla"} should fix your issue. You can take a look at flag test from the standard package where they're doing something similar.
Also, as os.Args is a "global variable", it might be a good idea to keep the state from before the test and restore it after. Similarly to the linked test:
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
This might be useful where other tests are, for example, examining the real arguments passed when evoking go test.
This is old enough but still searched out, while it seems out dated.
Because Go 1.13 changed sth.
I find this change helpful, putting flag.*() in init() and flag.Parse() in Test*()
-args cannot take -<test-args>=<val> after it, but only <test-args>, otherwise the test-args will be taken as go test's command line parameter, instead of your Test*'s

How can I print to Stderr in Go without using log

How can I write a message to Stderr without using log?
A comment in this SO post shows how to do it with log: log.Println("Message"), but what if I don't want a timestamp?
Is the following good Go?
os.Stderr.WriteString("Message")
If you don't want timestamps, just create a new log.Logger with flag set to 0:
l := log.New(os.Stderr, "", 0)
l.Println("log msg")
EDIT:
Is the following good Go?
os.Stderr.WriteString("Message")
This is acceptable, and you can also use fmt.Fprintf and friends to get formatted output:
fmt.Fprintf(os.Stderr, "number of foo: %d", nFoo)
Using the fmt package, you can choose to write to stderr this way:
import "fmt"
import "os"
func main() {
fmt.Fprintln(os.Stderr, "hello world")
}
The Go builtin functions print and println print to stderr. So if you simply want to output some text to stderr you can do
package main
func main() {
println("Hello stderr!")
}
Documentation: https://golang.org/pkg/builtin/#print
os.Stderr is an io.Writer, so you can use it in any function which accepts an io.Writer. Here are a few examples:
str := "Message"
fmt.Fprintln(os.Stderr, str)
io.WriteString(os.Stderr, str)
io.Copy(os.Stderr, bytes.NewBufferString(str))
os.Stderr.Write([]byte(str))
It all depends on how exactly you have the string you want to print (i.e. if you want to format it first, if you have it as an io.Reader, if you have it as a byte slice...). And there can be a lot more ways.
By default the logger flags are set to Ldate | Ltime. You can change the logger format to any of the following (from the golang log documentation):
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
LstdFlags = Ldate | Ltime // initial values for the standard logger
For example, flags Ldate | Ltime (or LstdFlags) produce,
2009/01/23 01:23:23 message
While flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
You can also set the default logger to not print anything by setting the flag to 0:
log.SetFlags(0)
use SetOutput function, set output stream to os.Stdout
import (
"log"
"os"
)
func init() {
log.SetOutput(os.Stdout)
}
func main() {
log.Println("Gene Story SNP File Storage Server Started.")
}