Required argument for compiled program? - crystal-lang

Is there any way to do required argument for crystal program?
For example
./myprog ~/Music -r
Instead of
./myprog -d ~/Music -r
So my program wont run if there's no [directory] argument. Right now using "option_parser" and can only do -arguments.

There is no way to create required arguments using option_parser, but you can parse arguments and throw an error or exit if there is no argument passed you expect:
require "option_parser"
directory = nil
parser = OptionParser.new
parser.on("-d DIR", "Directory [required]") do |d|
directory = d
end
parser.parse ARGV
if directory.nil?
# directory argument was not set
# print help and exit
puts parser
exit 1
else
# ...
end

Related

How to pass a string to omnetpp simulation from the command prompt

In my .ned file I have a simple module
simple Txc1
{
parameters:
int dummy_number = default(10);
}
When I run the simulation from the command prompt by specifying dummy_number I want i.e.,
opp_run -l tictoc omnetpp.ini --**.dummy_number=15
dummy_number equals 15 in my simulation.
But when instead of integer I want to specify a string
simple Txc1
{
parameters:
string dummy_string = default("Some dummy string");
}
opp_run -l tictoc omnetpp.ini --**.dummy_string="Test"
I get the following error
Cannot evaluate parameter 'dummy_string':(omnetpp::cModule)Tictoc1: unknown parameter 'Test' -- in module (Txc1) Tictoc1.tic (id=2), during network setup
Why my string is perceived as a parameter when it is just a value and how do I circumvent the problem?
Thanks
As long as your string does not contain a space, add backslashes before quotes, i.e.:
opp_run -l tictoc omnetpp.ini --**.dummy_string=\"TestWithoutSpace\"

Python 2.7 argsparse with a path as args

I want to give my program a path to a file but it doesnot like it if there is a / included. How can I convince python that my path is only 1 argument
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+/',)
parser.add_argument('-f', action='store', dest='PathtoFile',help='PathtoFile')
print parser.parse_args()
it works without /
argsparse.py -f banana -> Namespace(PathtoFile='banana')
Any of those result in expect one argument
argsparse.py -f /home/user/banana
argsparse.py -f '/home/user/banana'
argsparse.py -f '//home//user//banana'
argsparse.py -f "/home/user/banana"
argsparse.py -f "//home//user//banana"
->
usage: argsparse.py [-h] [-f PATHTOFILE]
argsparse.py: error: argument -f: expected one argument
UPDATE: Thanks match I forgot I added / as a prefix
Change
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+/',)
to
parser = argparse.ArgumentParser(description='Change the option prefix characters',prefix_chars='-+',)
The problem is that you're using prefix_chars='-+/' - this tells argparse that those characters are what mark out the command flags.
So your code is seeing / as equivalent to - and reading it as if you'd typed:
argsparse.py -f -home/user/banana
This means that -f has not been given an argument. Remove the prefix_chars and it should work properly.

Running only changed or failed tests with CMake/CTest?

I work on a large code base that has close to 400 test executables, with run times varying between 0.001 second and 1800 seconds. When some bit of code changes CMake will rebuild intelligently only the targets that have changed, many times taking shorter than the actual test run will take.
The only way I know around this is to manually filter on tests you know you want to run. My intuition says that I would want to re-run any test suite that does not have a successful run stored - either because it failed, or because it was recompiled.
Is this possible? If so, how?
ctest command accepts several parameters, which affects on set of tests to run. E.g. ,"-R" - filter tests by name, "-L" - filter tests by label. Probably, using dashboard-related options, you may also choose tests to run.
As for generating values for these options according to changed executables, you may write program or script, which checks modification time of executables and/or parses last log file for find failed tests.
Another way for run only changed executables is to wrap tests into additional script. This script will run executable only if some condition is saticfied.
For Linux wrapper script could be implemented as follows:
test_wrapper.sh:
# test_wrapper.sh <test_name> <executable> <params..>
# Run executable, given as second argument, with parameters, given as futher arguments.
#
# If environment variable `LAST_LOG_FILE` is set,
# checks that this file is older than the executable.
#
# If environment variable LAST_LOG_FAILED_FILE is set,
# check that testname is listed in this file.
#
# Test executable is run only if one of these checks succeed, or if none of checks is performed.
check_succeed=
check_performed=
if [ -n $LAST_LOG_FILE ]; then
check_performed=1
executable=$2
if [ ! ( -e "$LAST_LOG_FILE" ) ]; then
check_succeed=1 # Log file is absent
elif [ "$LAST_LOG_FILE" -ot "$executable" ]; then
check_succeed=1 # Log file is older than executable
fi
fi
if [ -n "$LAST_LOG_FAILED_FILE" ]; then
check_performed=1
testname=$1
if [ ! ( -e "$LAST_LOG_FAILED_FILE" ) ]; then
# No failed tests at all
elif grep ":${testname}\$" "$LAST_LOG_FAILED_FILE" > /dev/null; then
check_succeed=1 # Test has been failed previously
fi
fi
if [ -n "$check_performed" -a -z "$check_succeed" ]; then
echo "Needn't to run test."
exit 0
fi
shift 1 # remove `testname` argument
eval "$*"
CMake macro for add wrapped test:
CMakeLists.txt:
# Similar to add_test(), but test is executed with our wrapper.
function(add_wrapped_test name command)
if(name STREQUAL "NAME")
# Complex add_test() command flow: NAME <name> COMMAND <command> ...
set(other_params ${ARGN})
list(REMOVE_AT other_params 0) # COMMAND keyword
# Actual `command` argument
list(GET other_params 0 real_command)
list(REMOVE_AT other_params 0)
# If `real_command` is a target, need to translate it to path to executable.
if(TARGET real_command)
# Generator expression is perfectly OK here.
set(real_command "$<TARGET_FILE:${real_command}")
endif()
# `command` is actually value of 'NAME' parameter
add_test("NAME" ${command} "COMMAND" /bin/sh <...>/test_wrapper.sh
${command} ${real_command} ${other_params}
)
else() # Simple add_test() command flow
add_test(${name} /bin/sh <...>/test_wrapper.sh
${name} ${command} ${ARGN}
)
endif()
endfunction(add_wrapped_test)
When you want to run only those tests, which executables have been changed since last run or which has been failed last time, use
LAST_LOG_FILE=<build-dir>/Testing/Temporary/LastTest.log \
LAST_FAILED_LOG_FILE=<build-dir>/Testing/Temporary/LastTestsFailed.log \
ctest
All other tests will be automatically passed.

How do I make command line arguments with a hyphen (-) show up as non-optional in python v2.7?

I have the following python script
parser = argparse.ArgumentParser(description='Process controller.py arguments')
parser.add_argument("-b", help='Build number, e.g., 1234')
args = vars(parser.parse_args())
When I run it I get...
$ python CommandLineParser.py -h
usage: CommandLineParser.py [-h] [-b B]
Process controller.py arguments
optional arguments:
-h, --help show this help message and exit
-b B Build number, e.g., 1234
How do I make the "-b" show up as a "non-optional" argument (because it's NOT!). As an added bonus, how do I rid of the uppercase "B" after it? Thanks!
You need to set required to True and metavar (it's responsible for B) to '':
parser.add_argument("-b", help='Build number, e.g., 1234', required=True, metavar='')
Actually, you will still see your required argument as optional if run your script in a help mode. This is because of a bug: argparse required arguments displayed under "optional arguments":
The argparse module lists required args as optional in the default
help message.
There are also some workarounds suggested, but I like this one more: add your own required arguments group:
required_group = parser.add_argument_group('required arguments')
required_group.add_argument("-b", help='Build number, e.g., 1234', required=True, metavar='')
Then, you will see this on a command-line:
$ python test.py -h
usage: test.py [-h] -b
Process controller.py arguments
optional arguments:
-h, --help show this help message and exit
required arguments:
-b Build number, e.g., 1234
Please use the required keyword when adding it to the argparse: http://docs.python.org/2/library/argparse.html#sub-commands
parser.add_argument("-b", help='Build number, e.g., 1234', required=True)

Perl: suppress output of backtick when file not found

In my code :
$status = `ls -l error*`;
It shows output : ls *error No such file or directory.
How can I suppress this message. I am interested in determining that the error files are generated or not. If yes, I need the list of files else ignore (without printing the message)
By running it like
$status = `ls -l error* 2> /dev/null`;
and suppressing the external command's output to standard error.
If you just need the file names (and not all the other info that ls's -l switch gives you), this can be accomplished in pure Perl with a statement like
#files = glob("error*");
if (#files == 0) {
... there were no files ...
} else {
... do something with files ...
}
and if you do need all the other info you get from ls -l ..., applying the builtin stat function to each file name can give you the same information.