Confusion about the composition of the `cmd` parameter used in Deno.run() - deno

I tried to use Deno as a replacement for shell script, but got stuck.
I attempted to use Deno/Typescript to carry out the equivalent job as this:
docker run \
-d \
-v pgdata:/var/lib/postgresql/data \
--name pg \
-e POSTGRES_PASSWORD=123456 \
--rm \
-p 5432:5432 \
postgres
ts code looks like this:
function runCmd(s: string[]): Deno.Process {
return Deno.run({ cmd: s, stdout: "piped", stderr: "piped" })
}
function runPg() {
const cmd = [
"docker",
`run -d -v ${VOLUME}:/var/lib/postgresql/data --name pg -e POSTGRES_PASSWORD=${PASSWORD} --rm -p 5432:5432 postgres`
];
return runCmd(cmd);
}
add execution bit to this ts file and run it in terminal:
after this, I tried
function runPg() {
const cmd = [
"docker",
"run",
`-d -v ${VOLUME}:/var/lib/postgresql/data --name pg -e POSTGRES_PASSWORD=${PASSWORD} --rm -p 5432:5432 postgres`
];
return runCmd(cmd);
}
move out subcommand run from command options.
I got this:
I guess that Deno.run doesn't simply concatenate the passed-in string of command particles, but I cannot find enough information on this subject in order to fix the issue.
I haven't gone through the rust source code on this API, but I thought it's better to ask for help before trying the hard way.

You need to specify each part of the command as a separate string in the cmd array:
function runPg() {
const cmd = [
"docker",
"run",
"-d",
"-v",
`${VOLUME}:/var/lib/postgresql/data`,
"--name",
"pg",
"-e",
`POSTGRES_PASSWORD=${PASSWORD}`,
"--rm",
"-p",
"5432:5432",
"postgres"
];
return runCmd(cmd);
}
This will send run as the first argument to docker instead of sending run -d … as the first argument.
You can also build your command as a single string and then use split(" ") as long as no arguments contain spaces.

a follow up on my trial-n-error journey on this top.
While reading a book about unix shell programming, it points out a way to help the shell differentiate the space in identifier and the space as delimiter. When one tries to cat a file named a b (there is a space in between), the command should be cat a\ b or, using quotes, cat 'a b'.
This gives me an idea why my command does not work in Deno. See, each item in the cmd string list is an identifier, when I mix up delimiter-space with identifiers, the command is interpreted in the wrong way.
For example.
If I'd like to cat a file named a b. In Deno.run, I need to use { cmd: ["cat", "a b"] }.
If I'd like to cat two files named a and b. In Deno.run, I need to use { cmd: ["cat", "a", "b"] }.
Just remember that space in a command particle counts as a part of that term.

Related

Using kislyuk/yq returns syntax error, unexpected INVALID_CHARACTER with additional /0 at the end

I am using kislyuk/yq - The more often talked about version, which is a wrapper over jq, written in Python using the PyYAML library for YAML parsing
The version is yq 2.12.2
My jq is jq-1.6
I'm using ubuntu and bash scripts to do my parsing.
I wrote this as bash
alias=alias1
token=abc
yq -y -i ".tokens += { $alias: { value: $token }}" /root/.github.yml
I get the following error
jq: error: abc/0 is not defined at <top-level>, line 1:
.tokens += { alias1: { value: abc }}
I don't get it. Why would there be a /0 at the end?
The problem is abc is not interpreted as a literal string, when the double quotes are expanded by the shell. The underlying jq wrapper tries to match with abc as a standard built-in or a user-defined function which it was not able to resolve to, hence the error.
A JSON string (needed for jq) type needs to be quoted with ".." to be consistent with the JSON grammar. One way would be to pass the arg via command line with the --arg support
yq -y -i --arg t "$token" --arg a "$alias" '.tokens += { ($a): { value: $t } }' /root/.github.yml
Or have a quoting mess like below, which I don't recommend at all
yq -y -i '.tokens += { "'"$alias"'": { value: "'"$token"'" }}' /root/.github.yml

In snakemake, how do you use wildcards with scatter-gather processes?

I am trying to use snakemake's scatter-gather functionality to parallelize a slow step in my workflow. However, I cannot figure out how to apply it in situations where I am using wildcards. For example, I have defined the wildcard library in rule all, however, this does not seem to apply to the scatter function in ScatterIntervals:
import re
SCATTER_COUNT = 100
scattergather:
split=SCATTER_COUNT
rule all:
input:
expand("{library}_output.txt", library=["FC19271512", "FC19271513"])
rule ScatterIntervals:
input:
"{library}_baits.interval_list"
output:
temp(scatter.split("tmp/{library}_baits.scatter_{scatteritem}.interval_list"))
params:
output_prefix = (
lambda wildcards, output:
re.sub("\.scatter_\d+\.interval_list", "", output[0])
),
scatter_count = SCATTER_COUNT
shell:
"""
python ScatterIntervals.py \
-i {input} \
-o {params.output_prefix} \
-s {params.scatter_count}
"""
rule ProcessIntervals:
input:
bam = "{library}.bam",
baits = "tmp/{library}_baits.scatter_{scatteritem}.interval_list"
output:
temp("tmp/{library}_output.scatter_{scatteritem}.txt")
shell:
"""
python ProcessIntervals.py \
-b {input.bam} \
-l {input.baits} \
-o {output}
"""
rule GatherIntervals:
input:
gather.split("tmp/{library}_output.scatter_{scatteritem}.txt")
output:
"{library}_output.txt"
run:
inputs = "-i ".join(input)
command = f"python GatherOutputs.py {inputs} -o {output[0]}"
shell(command)
WildcardError in line 16 of Snakefile:
No values given for wildcard 'library'.
Evidently this works like expand, in that you can quote the wildcards that aren't scatteritem if you want DAG resolution to deal with them:
temp(scatter.split("tmp/{{library}}_baits.scatter_{scatteritem}.interval_list"))
The same logic applies for gather.split.

How to Run a Shell Command in a zsh-theme?

So, I have Oh My Zsh up and running, and I'm creating my own new zsh-theme. In it, I wish to grab the external IP address from https://api.myip.com - and I'm using curl & grep to grab it. Works fine when I enter it at the command prompt, but when embedded in my zsh-theme file it gives me an error:
zsh: no matches found: ((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]).){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])
(23) Failed writing body
Jacobs-MacBook-Pro-2.local jacobjackson ttys002 0 [ ] 10/29/20 18:32:46 PM
Here is my zsh-theme:
PROMPT='%F{white}%M %n %y %j $(curl -s https://api.myip.com | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])') %F{green}%2c%F{blue} [%f '
RPROMPT='$(git_prompt_info) %F{blue}] %F{green}%W %* %F{yellow}%D{%p}%f'
ZSH_THEME_GIT_PROMPT_PREFIX="%F{yellow}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%f"
ZSH_THEME_GIT_PROMPT_DIRTY=" %F{red}*%f"
ZSH_THEME_GIT_PROMPT_CLEAN=""
And here is the command sequence that grabs the IP address:
curl -s https://api.myip.com | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])'
Try this:
# Function name that's compatible with
# http://zsh.sourceforge.net/Doc/Release/User-Contributions.html#Prompt-Themes
# in case you ever want to build a full prompt theme.
# -s to prevent curl from outputting a progress bar.
# Use a service that simply outputs your IP, so you
# don't have to parse anything.
prompt_jacobjackson_precmd() {
psvar[1]=$( curl -s ifconfig.co )
}
# precmd hooks ru just before each new prompt.
autoload -Uz add-zsh-hook
add-zsh-hook precmd prompt_jacobjackson_precmd
# %1v inserts the 1st element of the psvar array. See
# http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Conditional-Substrings-in-Prompts
PS1='%1v > '
I decided to use some of Marlon Richert's ideas as well a few from the zsh-theme 'bureau.' :)
get_space () {
local STR=$1$2
local zero='%([BSUbfksu]|([FB]|){*})'
local LENGTH=${#${(S%%)STR//$~zero/}}
local SPACES=""
(( LENGTH = ${COLUMNS} - $LENGTH - 1))
for i in {0..$LENGTH}
do
SPACES="$SPACES "
done
echo $SPACES
}
_1LEFT="%F{white}$(curl -s https://api.myip.com | jq .ip -r) %F{green}\$(dirs -c; dirs)"
_1RIGHT="%F{yellow}%j jobs %F{cyan}\$(~/systemstatus.sh)"
actionjackson_precmd () {
_1SPACES=`get_space $_1LEFT $_1RIGHT`
#print
print -rP "$_1LEFT$_1SPACES$_1RIGHT"
}
setopt prompt_subst
PROMPT='%F{yellow}%n%F{white}#%F{green}%M $_LIBERTY%f '
RPROMPT='$(actionjackson_git_prompt) %F{green}%W %* %F{yellow}%D{%p}%f'
autoload -U add-zsh-hook
add-zsh-hook precmd actionjackson_precmd

zsh: print time next to command on execute

I want to configure zsh to append the time each command started next to the line command was executed on. For example:
# before I press ENTER
$ ./script
# after I press enter
$ ./script [15:55:58]
Running script...
I came up with the following config (which also colors the timestamp yellow):
preexec () {
TIME=`date +"[%H:%M:%S] "`
echo -e "$1 %{$fg[yellow]%}\033[1A\033[1C${TIME}$reset_color"
}
But it breaks and prints { and % characters on basic commands such as cat and echo. It also breaks on password prompts (macOS terminal). For example with echo:
$ echo "hello" [15:55:58]
hello"hello" %{%}
How can I fix this config?
Thank you.
You inspired me and based on your script I wrote mine. I have tested this on zsh 5.4.smth.
preexec () {
local TIME=`date +"[%H:%M:%S] "`
local zero='%([BSUbfksu]|([FK]|){*})'
local PROMPTLEN=${#${(S%%)PROMPT//$~zero/}}
echo "\033[1A\033[$(($(echo -n $1 | wc -m)+$PROMPTLEN))C $fg[blue]${TIME}$reset_color"
}
In your ~/.zshrc file, put:
function preexec() {
timer=${timer:-$SECONDS}
}
function precmd() {
if [ $timer ]; then
timer_show=$(($SECONDS - $timer))
export RPROMPT="%F{cyan}${timer_show}s %F{$black%}"
unset timer
fi
}
And that should give you something like this:

zsh function case condition parse error near `)'

I'm following this blog to setup a zsh function to switch aws cli profiles
: https://mads-hartmann.com/2017/04/27/multiple-aws-profiles.html
This is the zsh function in the blog:
function aws-switch() {
case ${1} in
"")
clear)
export AWS_PROFILE=""
;;
*)
export AWS_PROFILE="${1}"
;;
esac
}
#compdef aws-switch
#description Switch the AWS profile
_aws-switch() {
local -a aws_profiles
aws_profiles=$( \
grep '\[profile' ~/.aws/config \
| awk '{sub(/]/, "", $2); print $2}' \
| while read -r profile; do echo -n "$profile "; done \
)
_arguments \
':Aws profile:($(echo ${aws_profiles}) clear)'
}
_aws-switch "$#"
I added these lines to my ~/.zshrc, when I run source ~/.zshrc
It gives /.zshrc:4: parse error near `)'
I read the zsh function doc but still not very good at understanding the syntax and how could I fix this.
Have a look at the zsh man page (man zshmisc):
case word in [ [(] pattern [ | pattern ] ... ) list (;;|;&|;|) ] ... esac
As you see, you have to separate multiple pattern by |:
case $1 in
|clear)
....

Resources