semver increment in shell script - sh

I am trying to implement a solution to increment a version. Here's what I have come up with:
#!/bin/sh -x
VAR=1.0.1 # retrieved from Gitlab API
case $1 in
patch)
TAG=${VAR%.*}.$((${VAR##*.} + 1))
;;
major)
TAG=$((${VAR%%.*} + 1)).0.0
;;
*)
tmp=${VAR%.*}
minor=${tmp#*.}
TAG=${VAR%%.*}.$((minor + 1)).0
;;
esac
echo $TAG
major & patch work as expected; however, I'm facing problems incrementing minor.
When bumping 1.0.1, the minor should be 1.1.0; however, my code produces 1.2.0. What am I doing wrong?
Some more info, the script is executed inside a GitlabCI pipeline.
Edit: Updated the code with the suggested answer from #jhnc

I would just:
#!/bin/sh
var=1.0.1
IFS=. read -r version minor patch <<EOF
$var
EOF
case "$1" in
patch) tag="$version.$minor.$((patch+1))"; ;;
major) tag="$((version+1)).0.0"; ;;
*) tag="$version.$((minor+1)).0"; ;;
esac
echo $tag
Works on alpine with ash.

Your computation for incrementing minor is:
TAG=${VAR%%.*}.$((${VAR##*.} + 1)).0
However, ${VAR##*.} gives the patch value, not the minor value, and thus your incorrect result.
To extract minor, you can use a temporary variable:
tmp=${VAR%.*}
minor=${tmp#*.}
TAG=${VAR%%.*}.$((minor + 1)).0
Alternatively, it may be more readable to set IFS and split the string on dots:
TAG=$(
echo "$VAR" | while IFS=. read major minor patch; do
# add sanity-checks here
case "$1" in
patch)
echo "$major.$minor.$((patch+1))"
;;
major)
echo "$((major+1).0.0"
;;
minor|*)
echo "$major.$((minor+1)).0"
;;
esac
done
)
You should probably add sanity-checks to ensure VAR is actually of form "digits dot digits dot digits".

Related

How to expand environment variables using keyboard shortcut in Fish?

In Bash, the shortcut Esc Ctrl-e can be used to expand an environment variable at the shell:
$ echo $PATH
/home/joe
$ $PATH<Press Esc Ctrl-e>
$ /home/joe
Is there a shortcut to achieve something similar in Fish?
You could do something like this
function bind_expand_all
# what are the tokens of the current command line
set tokens (commandline --tokenize)
# erase the current command line (replace with empty string)
commandline -r ""
for token in $tokens
# append the expanded value of each token followed by a space
commandline -a (eval echo $token)" "
end
# move the cursor to the end of the new command line
commandline -C (string length (commandline))
end
then
bind \e\ce bind_expand_all
And if this is your current command line (with the cursor at the underscore):
$ echo $HOME (date -u)_
when you hit AltCtrle, you get
$ echo /home/jackman Thu May 10 19:27:18 UTC 2018 _
To store that binding permanently, add it to your fish_user_key_bindings function (create it if it does not exist):
Key bindings are not saved between sessions by default. Bare bind statements in config.fish won't have any effect because it is sourced before the default keybindings are setup. To save custom keybindings, put the bind statements into a function called fish_user_key_bindings, which will be autoloaded.
https://fishshell.com/docs/2.7/commands.html#bind
A little nicer:
function bind_expand_all
set -l expanded
for token in (commandline --tokenize)
set expanded $expanded (eval echo $token)
end
set -l new (string join " " $expanded)
commandline -r $new
commandline -C (string length $new)
end

Syntax error in script

My script try execute mvn clean install in all projects but before it tried switch to dev branch and pull it.
successString="[INFO] BUILD SUCCESS";
file="mvnoutput";
red=$'\e[1;31m';
grn=$'\e[1;32m';
end=$'\e[0m';
function checkResult
if grep -Fxq "$successString" $file
then
echo -en "${grn}[${1}]Build ok${end}";
else
echo "${red}[${1}]Error in mvn clean install${end}";
exit 1;
fi;
end
function pullAndSwitchDevBranch
git checkout dev;
git pull origin dev;
end
cd api-pay-commons/;
pullAndSwitchDevBranch;
touch mvnoutput;
mvn clean install -U > mvnoutput;
checkResult PAY;
Why I received this error?
line 17: end: command not found ./script.sh: line 20: syntax
error near unexpected token git' ./script.sh: line 20: git checkout dev;'
You have used the "fish" tag, so I'm assuming you are running this with the fish shell.
If so: This is not a valid fish script. Fish is explicitly not POSIX-compatible, so you might want to read up on the syntax. (If not, then please correct your tag)
red=$'\e[1;31m';
Fish does not use var=value to set a variable. It uses set var value.
Fish also does not have the $'' style of quoting. Instead, backslash-escapes are interpreted outside of quotes.
So this would be set red \e"[1;31m". Alternatively, fish offers the set_color builtin, which prints the escape sequence for a given color. So this could be set red (set_color red) (or you could call set_color later).
then
Fish does not use if condition; then dosomething; fi. It's if condition; dosomething; end.
echo -en "${grn}[${1}]Build ok${end}";
Fish does not use "${var}". It also does not call the function arguments $1 et al.
This would be something like echo -ens "$grn" "[$argv[1]]" "Build ok" "$end".
exit 1
Fish currently does not allow exiting from functions. You'll have to return 1 and check the result from the outside.
Additionally, you're using semicolons all over the place, which is not typical style in any shell I'm aware of.
In case you are not using fish, but some POSIX-compatible shell (like bash), this is also not valid. The main (and possibly only) issue is that you are using function something; dosomething; end. In bash, that would be
function something () {
#dostuff
}
And in pure POSIX, that would be
something () {
#dostuff
}

ksh error remove from list

I am trying to remove a certain element from a list in korn shell. It's working on my linux machine but the exact same code gives me an error on a solaris11 machine. I need a code that will work for both. It's probably because of different ksh versions but I would like to find a solution that works for both.
The code is:
#!/bin/ksh
MY_LIST="HELLO HOW ARE YOU"
toDel="HOW"
MY_LIST=( "${MY_LIST[#]/$toDel}" )
echo "MY LIST AFTER REMOVING HOW IS $MY_LIST"
On Solaris I get the following error:
syntax error at line 4 : '(' unexpected
Any suggestions?
Melodie wrote: Finally, I used 'Walter A' solution
Nice I could help.
Enabling you to vote for me and close the question, I post my comment as an answer.
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`
You'll probably need to spend some time with the ksh88 man page.
Without futher explanation:
set -A my_list HELLO HOW ARE YOU # note, separate words
toDel=HOW
set -- # using positional parameters as "temp array"
for word in "${my_list[#]}"; do
[[ $word != $toDel ]] && set -- "$#" "$word"
done
set -A my_list "$#"
printf "%s\n" "${my_list[#]}"
HELLO
ARE
YOU
Finally, I used 'Walter A' solution:
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`

Organizing my papers in org-mode

I've just started using org-mode, and so far find it quite useful. I have a very large collection of technical papers in a directory tree, and I'd like to go through them and index them through org-mode. What I'd like is to have a way of going through them and look at the unannotated ones, and annotate them one by one. I imagine doing this by first making up a file of links like [[xxx.pdf][not done yet]], and then being presented with the not done ones, glancing at them and deciding how what annotations to put in. In addition I'd like to add tags. What I'd really like is to be able to make up new tags on the fly. Has anyone done anything like this in org-mode?
Victor
If you have your papers organized like this,
% ls -1 ~/References/functional-programming
The Lambda Calculus.pdf
Recursive Functions of Symbolic Expressions and Their.pdf
you can run a quick script to build an org-file. Save the following as make-org and run it from your directory of papers (sh make-org > papers.org).
#! /bin/sh
#
# make-org -- generates an org-mode file from a directory of PDFs
#
# AUTHOR:
# Jon-Michael Deldin
# USAGE:
# cd ~/path/to/papers && make-org > papers.org
#
echo "#+TITLE: Research Papers"
echo "#+STARTUP: align hidestars indent lognotedone"
echo
for f in *.pdf; do
name=${f%.*} # strip extension
path=$(echo $f | sed 's/ /%20/') # encode spaces as %20
echo "* TODO $name :unread:"
echo
echo "[[file:$path][$name]]"
echo
done
Open papers.org in Emacs, run C-u C-c C-q to realign the tags. Your file should now look like this:
In addition I'd like to add tags. What I'd really like is to be able to make up new tags on the fly.
Once you have a headline (thing with * at the beginning, you can hit C-c C-c and add any tag you want.
You may find this detailed write-up of using org-mode and RefTeX or this alternate approach useful, especially if you use LaTeX.
Heres is the modified version that works on a directory.
#! /bin/sh
#
# make-org -- generates an org-mode file from a directory of PDFs
#
# AUTHOR:
# Jon-Michael Deldin
# USAGE:
# cd ~/path/to/papers && make-org > papers.org
#
echo "#+TITLE: Research Papers"
echo "#+STARTUP: align hidestars indent lognotedone"
echo
for f in $(find . -name '*.pdf'); do
name=${f%.*} # strip extension
path=$(echo $f | sed 's/ /%20/') # encode spaces as %20
echo "* TODO $name :unread:"
echo
echo "[[file:$path][$name]]"
echo
done

What are your suggestions for an ideal Vim configuration for Perl development?

There are a lot of threads pertaining to how to configure Vim/GVim for Perl development on PerlMonks.org. My purpose in posting this question is to try to create, as much as possible, an ideal configuration for Perl development using Vim/GVim. Please post your suggestions for .vimrc settings as well as useful plugins.
I will try to merge the recommendations into a set of .vimrc settings and to a list of recommended plugins, ftplugins and syntax files.
.vimrc settings
"Create a command :Tidy to invoke perltidy"
"By default it operates on the whole file, but you can give it a"
"range or visual range as well if you know what you're doing."
command -range=% -nargs=* Tidy <line1>,<line2>!
\perltidy -your -preferred -default -options <args>
vmap <tab> >gv "make tab in v mode indent code"
vmap <s-tab> <gv
nmap <tab> I<tab><esc> "make tab in normal mode indent code"
nmap <s-tab> ^i<bs><esc>
let perl_include_pod = 1 "include pod.vim syntax file with perl.vim"
let perl_extended_vars = 1 "highlight complex expressions such as #{[$x, $y]}"
let perl_sync_dist = 250 "use more context for highlighting"
set nocompatible "Use Vim defaults"
set backspace=2 "Allow backspacing over everything in insert mode"
set autoindent "Always set auto-indenting on"
set expandtab "Insert spaces instead of tabs in insert mode. Use spaces for indents"
set tabstop=4 "Number of spaces that a <Tab> in the file counts for"
set shiftwidth=4 "Number of spaces to use for each step of (auto)indent"
set showmatch "When a bracket is inserted, briefly jump to the matching one"
syntax
vim-perl: Support for Perl 5 and Perl 6 in Vim
plugins
delimitMate provides auto-completion for quotes, parens, brackets, etc. in insert mode. It handles apostrophes more intelligently than closepairs.vim does.
perlhelp.vim: Interface to perldoc
taglist.vim: Source code browser
ftplugins
perldoc.vim: perldoc command from vim
CPAN modules
Vim::X
Debugging tools
I just found out about VimDebug. I have not yet been able to install it on Windows, but looks promising from the description.
From chromatic's blog (slightly adapted to be able to use the same mapping from all modes).
vmap ,pt :!perltidy<CR>
nmap ,pt :%! perltidy<CR>
hit ,pt in normal mode to clean up the whole file, or in visual mode to clean up the selection. You could also add:
imap ,pt <ESC>:%! perltidy<CR>
But using commands from input mode is not recommended.
" Create a command :Tidy to invoke perltidy.
" By default it operates on the whole file, but you can give it a
" range or visual range as well if you know what you're doing.
command -range=% -nargs=* Tidy <line1>,<line2>!
\perltidy -your -preferred -default -options <args>
Look also at perl-support.vim (a Perl IDE for Vim/gVim).
Comes with suggestions for customizing Vim (.vimrc), gVim (.gvimrc),
ctags, perltidy, and Devel:SmallProf beside many other things.
Perl Best Practices has an appendix on Editor Configurations. vim is the first editor listed.
Andy Lester and others maintain the official Perl, Perl 6 and Pod support files for Vim on Github: https://github.com/vim-perl/vim-perl
For tidying, I use the following; either \t to tidy the whole file, or I select a few lines in shift+V mode and then do \t
nnoremap <silent> \t :%!perltidy -q<Enter>
vnoremap <silent> \t :!perltidy -q<Enter>
Sometimes it's also useful to deparse code. As the above lines, either for the whole file or for a selection.
nnoremap <silent> \D :.!perl -MO=Deparse 2>/dev/null<CR>
vnoremap <silent> \D :!perl -MO=Deparse 2>/dev/null<CR>
.vimrc:
" Allow :make to run 'perl -c' on the current buffer, jumping to
" errors as appropriate
" My copy of vimparse: http://irc.peeron.com/~zigdon/misc/vimparse.pl
set makeprg=$HOME/bin/vimparse.pl\ -c\ %\ $*
" point at wherever you keep the output of pltags.pl, allowing use of ^-]
" to jump to function definitions.
set tags+=/path/to/tags
Here's an interesting module I found on the weekend: App::EditorTools::Vim. Its most interesting feature seems to be its ability to rename lexical variables. Unfortunately, my tests revealed that it doesn't seem to be ready yet for any production use, but it sure seems worth to keep an eye on.
Here are a couple of my .vimrc settings. They may not be Perl specific, but I couldn't work without them:
set nocompatible " Use Vim defaults (much better!) "
set bs=2 " Allow backspacing over everything in insert mode "
set ai " Always set auto-indenting on "
set showmatch " show matching brackets "
" for quick scripts, just open a new buffer and type '_perls' "
iab _perls #!/usr/bin/perl<CR><BS><CR>use strict;<CR>use warnings;<CR>
I have 2.
The first one I know I picked up part of it from someone else, but I can't remember who. Sorry unknown person. Here's how I made "C^N" auto complete work with Perl. Here's my .vimrc commands.
" to use CTRL+N with modules for autocomplete "
set iskeyword+=:
set complete+=k~/.vim_extras/installed_modules.dat
Then I set up a cron to create the installed_modules.dat file. Mine is for my mandriva system. Adjust accordingly.
locate *.pm | grep "perl5" | sed -e "s/\/usr\/lib\/perl5\///" | sed -e "s/5.8.8\///" | sed -e "s/5.8.7\///" | sed -e "s/vendor_perl\///" | sed -e "s/site_perl\///" | sed -e "s/x86_64-linux\///" | sed -e "s/\//::/g" | sed -e "s/\.pm//" >/home/jeremy/.vim_extras/installed_modules.dat
The second one allows me to use gf in Perl. Gf is a shortcut to other files. just place your cursor over the file and type gf and it will open that file.
" To use gf with perl "
set path+=$PWD/**,
set path +=/usr/lib/perl5/*,
set path+=/CompanyCode/*, " directory containing work code "
autocmd BufRead *.p? set include=^use
autocmd BufRead *.pl set includeexpr=substitute(v:fname,'\\(.*\\)','\\1.pm','i')
I find the following abbreviations useful
iab perlb print "Content-type: text/html\n\n <p>zdebug + $_ + $' + $` line ".__LINE__.__FILE__."\n";exit;
iab perlbb print "Content-type: text/html\n\n<p>zdebug <C-R>a line ".__LINE__.__FILE__."\n";exit;
iab perlbd do{print "Content-type: text/html\n\n<p>zdebug <C-R>a line ".__LINE__."\n";exit} if $_ =~ /\w\w/i;
iab perld print "Content-type: text/html\n\n dumper";use Data::Dumper;$Data::Dumper::Pad="<br>";print Dumper <C-R>a ;exit;
iab perlf foreach $line ( keys %ENV )<CR> {<CR> }<LEFT><LEFT>
iab perle while (($k,$v) = each %ENV) { print "<br>$k = $v\n"; }
iab perli x = (i<4) ? 4 : i;
iab perlif if ($i==1)<CR>{<CR>}<CR>else<CR>{<CR>}
iab perlh $html=<<___HTML___;<CR>___HTML___<CR>
You can make them perl only with
au bufenter *.pl iab xbug print "<p>zdebug ::: $_ :: $' :: $` line ".__LINE__."\n";exit;
By far the most useful are
Perl filetype pluging (ftplugin) - this colour-codes various code
elements
Creating a check-syntax-before-saving command "W"
preventing you from saving bad code (you can override with the normal 'w').
Installing he plugins are a bit dicky as the version of vim (and linux) put the plugins in different places. Mine are in ~/.vim/after/
my .vimrc below.
set vb
set ts=2
set sw=2
set enc=utf-8
set fileencoding=utf-8
set fileencodings=ucs-bom,utf8,prc
set guifont=Monaco:h11
set guifontwide=NSimsun:h12
set pastetoggle=<F3>
command -range=% -nargs=* Tidy <line1>,<line2>!
\perltidy
filetype plugin on
augroup JumpCursorOnEdit
au!
autocmd BufReadPost *
\ if expand("<afile>:p:h") !=? $TEMP |
\ if line("'\"") > 1 && line("'\"") <= line("$") |
\ let JumpCursorOnEdit_foo = line("'\"") |
\ let b:doopenfold = 1 |
\ if (foldlevel(JumpCursorOnEdit_foo) > foldlevel(JumpCursorOnEdit_foo - 1)) |
\ let JumpCursorOnEdit_foo = JumpCursorOnEdit_foo - 1 |
\ let b:doopenfold = 2 |
\ endif |
\ exe JumpCursorOnEdit_foo |
\ endif |
\ endif
" Need to postpone using "zv" until after reading the modelines.
autocmd BufWinEnter *
\ if exists("b:doopenfold") |
\ exe "normal zv" |
\ if(b:doopenfold > 1) |
\ exe "+".1 |
\ endif |
\ unlet b:doopenfold |
\ endif
augroup END