I am making making a command line application to learn swift and OOP programming. My code works fine in the Xcode debugger (I see the input and output just fine), however when I archive and export my project, I for some reason cannot see the output of the print function.
Here is an example of what I mean.
Debugging in Xcode:
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 0
Username: User
Password: Pass
User: User sucsessully added to the system
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 1
User
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 0
Username: User2
Password: Pass
User: User2 sucsessully added to the system
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 1
User
User2
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 2
Delete user: User2
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 1
User
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
Option: 3
Program ended with exit code: 0
Now when I run the archived exported command line application in terminal:
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
0
User
Pass
Option: Username: Password: User: User sucsessully added to the system
Welcome to the login system
-----------------------------
Add a user [0]
List users [1]
Delete user [2]
Quit System [3]
-------------------------------
3
As you can see, the program registers my input and sometimes prints.
I have tried to take away the terminator: "" away from the print function to see if that is the issue and it printed just fine. This seems to be an issue with the terminator argument. I have also tried to replace the "" to " " for the terminator argument and it still doesn't work.
Why is it I cannot output to the console with the terminator argument?
Here is the code:
import Foundation
var running:Bool = true
let loginSystem = LoginSystem()
repeat
{
print("Welcome to the login system")
print("-----------------------------\n")
print("Add a user [0]")
print("List users [1]")
print("Delete user [2]")
print("Quit System [3]")
print("-------------------------------")
printToConsole("Option: ")
let option = input().intValue
//Add a user
if option == 0
{
print("Username: ", terminator: " ")
let username = input()
print("Password: ", terminator: " ")
let password = input()
print("User: \(username) sucsessully added to the system")
loginSystem.addUser(username, password: password, uid: 0, guid: 0)
//List users
} else if option == 1 {
let users = loginSystem.getUsers()
printArray(users)
//Delete user
} else if option == 2 {
printToConsole("Delete user: ")
let user = input()
loginSystem.deleteUser(user)
//Quit
} else if option == 3 {
running = false
}
clear()
} while running
print("")
printArray(theArray: [AnyObject]):
func printArray(theArray:[AnyObject])
{
for item in theArray
{
print("\(item)")
}
}
clear()
func clear()
{
let clearCommand = "if [ -n \"$STY\" ]; then clear; fi"
system(clearCommand)
}
input()
func input() -> String {
let keyboard = NSFileHandle.fileHandleWithStandardInput()
let inputData = keyboard.availableData
let strData = NSString(data: inputData, encoding: NSUTF8StringEncoding)!
return strData.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
}
intVal
extension String
{
var intValue:Int
{
return Int(self)!
}
}
try
repeat
{
fflush(stdout)
print("Welcome to the login system")
Related
Does anybody use the Elmish routing for a multi-page app (SAFE Stack in my case) as specified by Maxime Mangel here on StackOverflow , but with a login page?
Do you, at the same time, use the accessibility (Anonymous/LoggedIn) philosophy as specified here in the Elmish Book?
If so, you probably use different coding than in the Elmish Book (as I do), but in any case you probably need to have login results available in the main page (Main.fs) to implement the accessibility logic. The Elmish Book uses (in Login.fs) a function with an active pattern let (|UserLoggedIn|_|) = ... and this function is called from the main or home page (see here).
But it wouldn't work in my app.
So my question is:
How do you transfer login results from the login page (Login.fs) into the main page (Main.fs)?
You can easily spot my login results here in the code:
Login.fs //client
let update (msg: Msg) (model: Model) : Model * Cmd<Msg> =
match msg with
| SetUsrInput value -> { model with InputUsr = value }, Cmd.none
| SetPswInput value -> { model with InputPsw = value }, Cmd.none
| SendUsrPswToServer ->
let buttonClickEvent = SharedLoginValues.create model.InputUsr model.InputPsw
let cmd = Cmd.OfAsync.perform getLoginApi.login buttonClickEvent GetLoginResults
model, cmd
| GetLoginResults value ->
let result =
match value with
| SharedApi.UsernameOrPasswordIncorrect -> { model with User = ApplicationUser.Anonymous}
| SharedApi.LoggedIn user -> { model with User = ApplicationUser.LoggedIn user}
result, Cmd.ofMsg AskServerForSecurityTokenFile
Meanwhile, I use a workaround with reaching login results that I save on the server. Although the accesibility logic works as expected, the workaround seems to be cumbersome - I already have the login results in the login page so why reaching them twice...
Here, it is my code for the accesibility logic in Main.fs that should use the login results. By the way, the code is, to my big surprise, much simpler than that in the Elmish Book.
Main.fs //client
let private setRoute (optRoute: RouterM.Route option) model =
let model =
let applicationUser =
//model.GetSecurityTokenFile -> this is the workaround
// - results from the login page should be matched here instead
match model.GetSecurityTokenFile with
| true -> LoggedIn model.user
| false -> Anonymous
let currentRoute =
//model.GetSecurityTokenFile -> this is the workaround
// - results from the login page should be matched here instead
match model.GetSecurityTokenFile with
| true -> optRoute
| false -> Some RouterM.Route.Home //or to a login page
{
model with CurrentRoute = currentRoute
User = applicationUser
}
Well, just 2x match and that's really all. Or have I missed anything here?
match optRoute with
//...some code
| Some (RouterM.Route.CMSRozcestnik cmsRozcestnikId) ->
match model.User with
| Anonymous ->
let (homeModel, homeCmd) = Home.init () //or Login.init
{ model with ActivePage = Page.Home homeModel }, cmd2 HomeMsg homeCmd AskServerForDeletingSecurityTokenFile
| LoggedIn user ->
let (cmsRozcestnikModel, cmsRozcestnikCmd) = CMSRozcestnik.init cmsRozcestnikId
{ model with ActivePage = Page.CMSRozcestnik cmsRozcestnikModel }, Cmd.map CMSRozcestnikMsg cmsRozcestnikCmd
| _ -> let (homeModel, homeCmd) = Home.init () //or Login.init
{ model with ActivePage = Page.Home homeModel }, cmd2 HomeMsg homeCmd AskServerForDeletingSecurityTokenFile
If needed, the entire code is here on GitHub:
https://github.com/MiroslavHustak/SAFE-Stack-simple-multipage-website-with-CMS-
I have received an answer to my question from Maxime Mangel via F# Slack.
Look at the section "Make the child communicate with the parent" in the link below and pay attention to the message ExternalMsg. Then just implement the code into your system. It worked with my code. If interested, you can look at the code on GitHub (the link is in the question).
https://medium.com/#MangelMaxime/my-tips-for-working-with-elmish-ab8d193d52fd
I'm using the Perl6 Terminal::Print module for a console based application.
It's working well - however, now I need to prompt the user for a string of text.
What's a good way to do this?
Here is an example of using Terminal::Print::RawInput to get a filename as user input:
use v6;
use Terminal::Print;
use Terminal::Print::RawInput;
my $screen = Terminal::Print.new;
# saves current screen state, blanks screen, and hides cursor
$screen.initialize-screen;
$screen.print-string(9, 23, "Enter filename: ");
my $in-supply = raw-input-supply;
my $filename;
react {
whenever $in-supply -> $c {
done if $c.ord ~~ 3|13; # Enter pressed or CTRL-C pressed
my $char = $c.ord < 32 ?? '' !! $c;
$filename ~= $char;
print $char;
}
}
sleep .1;
$screen.shutdown-screen;
say "Filename entered: '$filename'";
EDIT: Just got the same behavior on 3.4
EDIT2: If I remove the disableLosslessIntegers from the connection the issue goes away, but the all integer numbers come back as {low: 20, high:0} type structures which breaks my entire application
The following code works fine on neo4j 3.3 using the 1.7.2 neo4j-driver for node:
import {v1 as neo4j} from 'neo4j-driver';
const url: string = process.env.COREDB_URL || '';
const user: string = process.env.COREDB_USERNAME || '';
const password: string = process.env.COREDB_PASSWORD || '';
const driver = neo4j.driver(url, neo4j.auth.basic(user, password), {disableLosslessIntegers: true});
let connection = driver.session()
async function go() {
let res = await connection.run(`create (b:Banana {tag: 'test'}) return b,id(b) as id`, {});
let b = res.records[0].get('b').properties
console.log('b',b)
let id = res.records[0].get('id')
console.log('id',id)
res = await connection.run(`MATCH (u) where id(u)=$id return u as id`, {id: id});
console.log(res.records)
let id2 = res.records[0].get('id').properties;
console.log('id2',id2)
}
go().then(() => console.log('done')).catch((e) => console.log(e.message))
it gives the following output:
> node tools\test-id.js
b { tag: 'test' }
id 1858404
[ Record {
keys: [ 'id' ],
length: 1,
_fields: [ [Node] ],
_fieldLookup: { id: 0 } } ]
id2 { tag: 'test' }
done
Under 3.5.1 it does not work. The second statement returns no records:
> node tools\test-id.js
b { tag: 'test' }
id 1856012
[]
Cannot read property 'get' of undefined
BTW, the reason I need to do the get by id right after the create is that I am using an apoc trigger to add things to the node after creation, and apoc triggers apparently run after the object is created and returned, so I need the second get to see the transformed node.
But, for this distilled example I removed the trigger from my DB to ensure that it was not causing the issue
I'm trying to improve my home automation with the Fibaro HC2.
The building is divided into several sections and I want to create a list of devices with the name of the section. With the Fibaro API I only get the Section ID, but not the name. With json.encode I get the contents of this table:
[
{
"Id":4,
"sortOrder":3,
"name":"basement"
},
{
"id":5,
"sortOrder":2,
"name":"GROUND FLOOR"
},
{
"id":6,
"sortOrder":4,
"name":"FIRST FLOOR"
},
{
"id":7,
"sortOrder":1,
"name":"OUTSIDE"
}
]
sortOrder does not matter. What I have done:
local jS = json.encode (sections)
for i = 1, #sections do
local jS = json.encode (sections [i])
s = string.gsub (jS, ', "sortOrder":% d', "")
print (s)
end
This is the output:
{ "Id": 4, "name": "BASEMENT"}
{ "Id": 5, "name": "GROUND FLOOR"}
{ "Id": 6, "name": "FIRST FLOOR"}
{ "Id": 7, "name": "OUTSIDE"}
I have no idea if that makes sense. I would like to have a function that stores the name in a variable:
function getSectionNamebyID (secID)
if secId == "4" then sectionname = "BASEMENT" end
if secId == "5" then sectionname = "GROUNDFLOOR" end
--...
return sectionname
end
A very nice tutorial on how to read all devices etc. in fibaro and store that table of information as a json string value in a global variable.
The most interesting part is the script which is implemented as a lua scene in fibaro. Just create a global variable with the name "HomeTable" and run the scene manually to store all devices/scenes etc. in one variable:
--[[
%% autostart
%% properties
%% events
%% globals
--]]
local debug = true --set to false to stop debug messages
-- HOME TABLE FOR ANYTHING IN ADDITION TO DEVICES, VDs, iOS DEVICES
-- EDIT TO YOUR NEEDS OR KEEP BLANK: jsonHome = {}
jsonHome = {
scene = {
HueSceneStart=43,
AlexaSceneStart=67,
},
users = {
--admin=2,frank=1564,sylvia=1565
},
}
-- NO USER EDITS NEEDED BELOW
local function log(str) if debug then fibaro:debug(str); end; end
devices=fibaro:getDevicesId({visible = true, enabled = true}) -- get list of all visible and enabled devices
log("Fill hometable with "..#devices.." devices")
-- FILL THE HOMETABLE WITH ALL VDs, DEVICES AND iOS DEVICES
for k,i in ipairs(devices) do
deviceName=string.gsub(fibaro:getName(i), "%s+", "") -- eliminate spaces in devicename
-- Uncomment this to eliminate all non-alphanumeric characters in devicename
-- deviceName=string.gsub(fibaro:getName(i), "%W", "")
if fibaro:getType(i) == "virtual_device" then -- Add VDs to Hometable
if jsonHome.VD == nil then -- Add VD to the table
jsonHome.VD = {}
end
jsonHome.VD[deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
elseif fibaro:getType(i) == "iOS_device" then -- Add iOS devices to Hometable
if jsonHome.devices == nil then -- Add iOS devices to the table
jsonHome.devices = {}
end
jsonHome.devices[deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName)
else -- Add all other devices to the table
roomID = fibaro:getRoomID(i)
if roomID == 0 then
roomname = "Unallocated"
else
roomname=string.gsub(fibaro:getRoomName(roomID), "%s+", "") -- eliminate spaces in roomname
-- Uncomment this to eliminate all non-alphanumeric characters in roomname
-- roomname=string.gsub(fibaro:getRoomName(roomID), "%W", "")
end
if jsonHome[roomname] == nil then -- Add room to the table
jsonHome[roomname] = {}
end
jsonHome[roomname][deviceName]=i
log("i="..i..", type="..fibaro:getType(i)..", device="..deviceName..", room="..roomname)
end
end
jHomeTable = json.encode(jsonHome) -- ENCODES THE DATA IN JSON FORMAT BEFORE STORING
fibaro:setGlobal("HomeTable", jHomeTable) -- THIS STORES THE DATA IN THE VARIABLE
log("global jTable created:") -- STANDARD DEBUG LINE TO DISPLAY A MESSAGE
log(jHomeTable)
After running it, you can use it by following example. In my case the room name was "Workingroom" and the name of the device was "Shutter":
--[[
%% properties
%% events
%% globals
--]]
local ht = json.decode(fibaro:getGlobalValue("HomeTable"))
fibaro:call(ht.Workingroom.Shutter, "open")
I need to parse a text (output from a svn command) in order to retrieve a number (svn revision).
This is my code. Note that I need to retrieve all the output stream as a text to do other operations.
def proc = cmdLine.execute() // Call *execute* on the strin
proc.waitFor() // Wait for the command to finish
def output = proc.in.text
//other stuff happening here
output.eachLine {
line ->
def revisionPrefix = "Last Changed Rev: "
if (line.startsWith(revisionPrefix)) res = new Integer(line.substring(revisionPrefix.length()).trim())
}
This code is working fine, but since I'm still a novice in Groovy, I'm wondering if there were a better idiomatic way to avoid the ugly if...
Example of svn output (but of course the problem is more general)
Path: .
Working Copy Root Path: /svn
URL: svn+ssh://svn.company.com/opt/svnserve/repos/project/trunk
Repository Root: svn+ssh://svn.company.com/opt/svnserve/repos
Repository UUID: 516c549e-805d-4d3d-bafa-98aea39579ae
Revision: 25447
Node Kind: directory
Schedule: normal
Last Changed Author: ubi
Last Changed Rev: 25362
Last Changed Date: 2012-11-22 10:27:00 +0000 (Thu, 22 Nov 2012)
I've got inspiration from the answer below and I solved using find(). My solution is:
def revisionPrefix = "Last Changed Rev: "
def line = output.readLines().find { line -> line.startsWith(revisionPrefix) }
def res = new Integer(line?.substring(revisionPrefix.length())?.trim()?:"0")
3 lines, no if, very clean
One possible alternative is:
def output = cmdLine.execute().text
Integer res = output.readLines().findResult { line ->
(line =~ /^Last Changed Rev: (\d+)$/).with { m ->
if( m.matches() ) {
m[ 0 ][ 1 ] as Integer
}
}
}
Not sure it's better or not. I'm sure others will have different alternatives
Edit:
Also, beware of using proc.text. if your proc outputs a lot of stuff, then you could end up blocking when the inputstream gets full...
Here is a heavily commented alternative, using consumeProcessOutput:
// Run the command
String output = cmdLine.execute().with { proc ->
// Then, with a StringWriter
new StringWriter().with { sw ->
// Consume the output of the process
proc.consumeProcessOutput( sw, System.err )
// Make sure we worked
assert proc.waitFor() == 0
// Return the output (goes into `output` var)
sw.toString()
}
}
// Extract the version from by looking through all the lines
Integer version = output.readLines().findResult { line ->
// Pass the line through a regular expression
(line =~ /Last Changed Rev: (\d+)/).with { m ->
// And if it matches
if( m.matches() ) {
// Return the \d+ part as an Integer
m[ 0 ][ 1 ] as Integer
}
}
}