Go-Sublime-build configuration - go

Im having issues trying to set up go to run the current file from Sublime text 2.
Here's what I have in my go.sublime-build file
{
"cmd": [ "go", "run", "${file}" ]
}
When I try to run build on a go source file, I get the error
[Error 6] The handle is invalid
[cmd: [u'go run', u'C:\\Users\\gprasant\\Documents\\GitHub\\programming_pearls\\src\\go\\quicksort.go']]
[dir: C:\Users\gprasant\Documents\GitHub\programming_pearls\src\go]
Is there any way to get this fixed ? Or is there another plugin in Sublime text for Go development?

Installing GoSublime should get this working for you. After installing and restarting ST2: do ctrl-B, type "run" and hit enter.

I got by with
{
"cmd": "go run $file",
"shell" : true
}

In ST3: it is changed to be:
{
"shell_cmd": "go run ${file}"
}

On my mac, I needed the following code in:
/Users/your_user_name/Library/Application Support/Sublime Text 2/Packages/User/go.sublime-build
go.sublime-build
{
"cmd": ["go run '${file}'"],
"selector": "source.go",
"path": "/usr/local/go/bin",
"shell": true
}
"cmd" line quoting is to correctly handle file paths with spaces.
"shell" line is needed since commenting it out breaks it.
"path" line is needed because the basic shell, doesn't have access to my .zshrc file include the export GOPATH statement defining the go path.
After that any .go file should build and run with command+B, leaving the stdout message in a console built into sublime text 2.

what about:
{
"cmd": ["go", "run", "${file}"],
"path": "/user/local/go/bin"
}
I like GoSublime, just hate to type run each time when click Command + B

SublimeText 2
build-system for golang, making F4/shift-F4 work (next error/prev error)
1st, create a file: ~/gosublime_build.sh
GOPATH=~/go
export GOPATH
echo "GOPATH:$GOPATH"
if [ "$3." = "RUN." ]
then
EXENAME=${1##*/}
EXENAME=$GOPATH/bin/$EXENAME
echo $EXENAME
$($EXENAME)
echo "code: $?"
exit
fi
echo "go build $2"
cd /usr/local/go/bin
./go build -o ~/temp.go.compiled $2
if [ $? -eq 0 ]
then
cd $1
echo "Project: " $1
/usr/local/go/bin/go install
echo "go install exit code: $?"
else
echo "go build exit code: $?"
fi
2nd:
chmod 777 ~/gosublime_build.sh
3rd: create a new sublime2 build-system for "go" (Tools/Build System/New)
{
"cmd": ["~/gosublime_build.sh $file_path $file"]
,"shell": true
,"selector": "source.go"
,"file_regex": "([\\w/_-]+[.]{1}[\\w./_-]+?):([0-9]+):?([0-9]+)?(.*)?"
}
4th: select your new build-system (Tools/Build System)
5th: build with Ctrl-B, F4/Shift-F4: next/prev error
If anybody knows how to instruct the go compiler to inform FULL PATH of file and line for each error, this process can be simplified

Related

Indirect reference to hashmap in bash

I am writing a script to install packages from .deb files, but first, I would like to check if each package is already installed. I have a config file that contains the information for the packages as hashmaps, like this:
declare -A package_a=(
[name]="utility-blah"
[ver]="1.2"
[arch]="amd64"
)
declare -A package_b=(
[name]="tool-bleh"
[ver]="3.4"
[arch]="all"
)
#and so on and so forth
My install script sources the config file, and I would like it to iterate over the packages, checking if they are installed, and installing them if they are not, like this:
source packages.config
declare -a packageList=("package_a" "package_b" "package_d")
for package in ${packageList[#]}; do
# Check if the specific version is installed already
if apt show ${package[name]}=${package[ver]}; then
echo ${package[name]} ${package[ver]} is already installed.
else
echo Installing ${package[name]}
sudo apt install path/to/files/${package[name]}_${package[ver]}_${package[arch]}.deb
fi
done
How can I have package point to the hashmap containing the information about the package and use it in the following commands?
I'm using Bash 4.4.20 on Ubuntu 18.04
One idea using a nameref:
source packages.config
declare -a packageList=("package_a" "package_b" "package_d")
for pkg in "${packageList[#]}"; do # change variable name
declare -n package="${pkg}" # declare nameref; rest of code remains the same ...
# Check if the specific version is installed already
if apt show ${package[name]}=${package[ver]}; then
echo ${package[name]} ${package[ver]} is already installed.
else
echo Installing ${package[name]}
sudo apt install path/to/files/${package[name]}_${package[ver]}_${package[arch]}.deb
fi
done
Or (as M. Nejat Aydin and Benjamin W. have pointed out) the declare -n can go before the while loop, eg:
declare -n package
for package in "${packageList[#]}"; do
# Check if the specific version is installed already
if apt show ${package[name]}=${package[ver]}; then
echo ${package[name]} ${package[ver]} is already installed.
else
echo Installing ${package[name]}
sudo apt install path/to/files/${package[name]}_${package[ver]}_${package[arch]}.deb
fi
done
Simple test:
declare -n package
for package in ${packageList[#]}; do
echo "${!package} : ${package[name]}"
done
This generates:
package_a : utility-blah
package_b : tool-bleh
package_d :
This kind of input data is better suited for JSON rather than using bash associative arrays and indirection.
Lets say you have a packages.json:
{
"packages": [
{
"package": "package_a",
"name": "utility-blah",
"ver": "1.2",
"arch": "amd64"
},
{
"package": "package_b",
"name": "utility-bleh",
"ver": "3.4",
"arch": "all"
},
{
"package": "apache2",
"name": "Apache2 http server",
"ver": "2.4.52-1ubuntu4.1",
"arch": "all"
}
]
}
Such simple POSIX-shell script is able to process it as you need:
#! /bin/sh
# Fields are tab-delimited, records end with newline
IFS=$(printf '\t')
# Parses json input into record lines
jq -r '.packages[]|(.package + "\t" + .name + "\t" + .ver)' packages.json |
# Iterates records, reading fields
while read -r package name ver; do
{
# Query package for installed status and version
# formatted into two fields
dpkg-query -W --showformat='${db:Status-Abbrev}\t${Version}' "${package}" || :
} 2>/dev/null | {
# Reads status and installed version
read -r status installed_ver _
# If status is installed 'ii ' and installed version matches'
if [ "${status}x" = 'ii x' ] && [ "${ver}x" = "${installed_ver}x" ]; then
printf '%s %s is already installed.\n' "${name}" "${ver}"
else
printf 'Installing %s.\n' "${name}"
fi
}
done
Example output:
nstalling utility-blah.
nstalling utility-bleh.
Apache2 http server 2.4.52-1ubuntu4.1 is already installed.

Set environment variables then run script in Jenkins Scripted Pipeline

I am new to Jenkins, Groovy and pipelines. I have created a simple pipeline stage like so:
//working build but not setting env variables
node('build-01') {
stage('Building') {
echo "[*] Starting build (id: ${env.BUILD_ID}) on ${env.JENKINS_URL}"
try {
sh 'ls -l'
//ls shows the damn file
sh '. setup-target'
} catch(all) {
sh "echo 'Failed to run setup-target script with error: ' ${all}"
}
}
}
This works. But I want to modify/add environment variables to the session running this script (this script is a bash file with the correct shebang line on top). So I did:
node('build-01') {
withEnv(["CMAKE_INSTALL_DIR=${WORKSPACE}", "SDK_INSTALL_DIR=${WORKSPACE}"]){
stage('Building') {
echo "[*] Starting build (id: ${env.BUILD_ID}) on ${env.JENKINS_URL}"
try {
sh 'ls -l'
//ls shows the damn file
sh '. setup-target'
} catch(all) {
sh "echo 'Failed to run setup-target script with error: ' ${all}"
}
}
}
}
This errors out with:
/home/jenkins-sw/ci/workspace/myWorkSpace#tmp/durable-6d30b48d/script.sh: line 1: .: setup-target: file not found
and
Failed to run setup-target script with error: hudson.AbortException: script returned exit code 1
But the environment variables are set, I check this by doing a sh 'printenv' right below the ls -l line. Interestingly ls -l does show the script.
What am I missing?
UPDATE
The following:
node('build-01') {
withEnv(["CMAKE_INSTALL_DIR=${WORKSPACE}", "SDK_INSTALL_DIR=${WORKSPACE}"]){
stage('Building') {
echo "[*] Starting build (id: ${env.BUILD_ID}) on ${env.JENKINS_URL}"
try {
sh 'ls -l'
//ls shows the damn file
sh './setup-target'
} catch(all) {
sh "echo 'Failed to run setup-target script with error: ' ${all}"
}
}
}
}
results in:
/home/jenkins-sw/ci/workspace/myWorkSpace#tmp/durable-6d30b48d/script.sh: line 1: ./setup-target: Permission denied
Interesting. How is withEnv effecting permissions? What?! And if I chmod that file to have permissions, i get a new error, something related to "missing workspace".
I figured it out. I was cloning directly into the workspace and then setting my environment variables to point to the workspace as well. I modified both those things. I now create a dir in my workspace and clone into it and I also set my environment variables to directories inside my workspace. Like so:
node('build-01') {
withEnv(["CMAKE_INSTALL_DIR=${WORKSPACE}/cmake_install", "SDK_INSTALL_DIR=${WORKSPACE}/sdk"]){
stage('Building') {
echo "[*] Starting build (id: ${env.BUILD_ID}) on ${env.JENKINS_URL}"
try {
sh 'ls -l'
//ls shows the damn file
dir('path/to/checkout/') {
sh '. ./setup-target'
}
} catch(all) {
sh "echo 'Failed to run setup-target script with error: ' ${all}"
}
}
}
}
This works.
My guess would be that either CMAKE_INSTALL_DIR or SDK_INSTALL_DIR are on the path.
Instead of sh '. setup-target' you should sh './setup-target'.

Make build UNSTABLE if text found in console log using jenkinsfile (jenkins pipeline)

I am trying to login into an instance and check if the file test.txt is not empty, then echo .. make build unstable using the jenkins pipeline (jenkinsfile)But that's not working.
I have this:
post {
always {
sh "ssh ubuntu#$Ip 'if [ -s test.txt ] ; then echo some text && cat test.txt'"
currentBuild.result = 'UNSTABLE'
}
}
Instead of doing above, can I parse through the console log of the latest build to find something eg: some text and if that's found I want to make the build unstable
You need to return standard out from the script:
String stdOut = sh returnStdout: true, script: "ssh ubuntu#$Ip 'if [ -s test.txt ] ; then echo some text && cat test.txt'"
if (stdOut == "") {
currentBuild.status = 'UNSTABLE'
}
Or, you could use returnStatus to return the exit code of the script. The documentation for the sh step can be found here

How to suppress output in Sublime Text cmd?

How can I suppress the output in Sublime Text Build System output?
I tried this but it says Error: unrecognized or incomplete command line.
{
"cmd": ["ipconfig", ">nul 2>&1"],
"name": "ipconfig",
"shell": "true"
}
{
"name": "ipconfig",
"shell_cmd": "ipconfig >nul 2>&1"
}
I always use shell_cmd because you can just write the command like you would on the command line instead of trying to figure out the multiple arguments nonsense in the array. This worked for me.

Sublime build system to open file at local server address

For a website I'm developing with the help of a local server (running at http://127.0.0.1:4000), I try to write a build system for my Sublime Text project settings.
I have access to these variables (provided by Sublime Text):
$file: Stores the absolute path to the file on disk:C:\Users\User\dev\repos\base\dir\index.html
$project_path: Stores the location of the project file (usually the root of the project):C:\Users\User\dev\repos\base
Now what I want is the content of $file but instead of the $project_path I want http://127.0.0.1:4000/~base. For that task I tried the following with Bash cmd.exe:
CALL SET result=%file:%project_path%=http://127.0.0.1:4000\~base\% && echo %result%
This gives the desired result, however I can't seem to be able to apply it to the build system inside Sublime Text.
For now, I try to generate the correct address and output it via cmd.exe:
{
"build_systems":
[
{
"name": "Preview in browser",
"selector": "text.html",
"windows":
{
"shell": true,
"cmd": [
"start", "cmd", "/k",
"CALL SET result=$file:$project_path=http://127.0.0.1:4000\\~base\\ && echo $result"
]
}
}
]
}
Result:
> echo %result%
C:\Users\Philipp\dev\repos\base\dir\index.html:C:\Users\Philipp\dev\repos
\base=http://127.0.0.1:4000\~base\
So the substitution is not working when doing it in the build system, but in cmd.exe it does. I'm confused.
You can do something like this:
{
"build_systems":
[
{
"name": "Preview in browser",
"selector": "text.html",
"windows":
{
"shell_cmd": "CALL SET filePath=$file && CALL SET result=%filePath:$project_path=http://127.0.0.1:4000\\~base% && CALL C:/Progra~2/Google/Chrome/Application/chrome.exe %result%"
}
}
]
}
The problem was with windows replacement and variable asignation rather than with sublime builds.
As it has been said in chat and comments multiple CALL are necessary to use the real value variable because if not used windows will expand their value at parse time before the wanted value is asigned at execution time. In addition, shell_cmd can be used to run a unique command in shell.

Resources