Two Radio Groups in NSIS dialogue - nsis

I have a dialogue page in an NSIS installer on which I want to have 2 radio button groups, with 3 radio buttons in each group.
Each group is independent, and a selection is required in both groups.
I have the following code, which shows 2 groups being created with 3 buttons each, but when the installer runs all 6 buttons are grouped as 1 group which mean I can only select 1 from 6, rather than 1 from 3 buttons in each group.
Function settingsTypePageCreate
nsDialogs::Create 1018
pop $0
; Radio Group 1
${NSD_CreateGroupBox} 0 0 100% 40u "Select Method for specifying file locations"
Pop $1
${NSD_CreateRadioButton} 0 10% 100% 15u "Use Environment Variable."
pop $2
${NSD_CreateRadioButton} 0 25% 100% 15u "Use central config file."
pop $3
${NSD_CreateRadioButton} 0 40% 100% 15u "Use default %USERPROFILE%."
pop $4
; Radio Group 2
${NSD_CreateGroupBox} 0 60% 100% 40u "Select location folder"
Pop $5
${NSD_CreateRadioButton} 0 70% 100% 15u "%APPDATA%"
pop $6
${NSD_CreateRadioButton} 0 80% 100% 15u "%USERPROFILE%"
pop $7
${NSD_CreateRadioButton} 0 90% 100% 15u "PROGRAMDATA"
pop $8
nsDialogs::Show
FunctionEnd
Also, I cannot find anywhere a description of how the position and size parameters for NSD_Create. I'm having to do it by trial and error.

The WS_GROUP style is used to create grouped controls:
WS_GROUP Specifies the first control of a group of controls in which the user can move from one control to the next with the arrow keys. All controls defined with the WS_GROUP style FALSE after the first control belong to the same group. The next control with the WS_GROUP style starts the next group (that is, one group ends where the next begins).
!include nsDialogs.nsh
Function settingsTypePageCreate
nsDialogs::Create 1018
pop $0
; Radio Group 1
${NSD_CreateGroupBox} 0 0 100% 50u "Select Method for specifying file locations"
Pop $0
${NSD_CreateRadioButton} 5u 12u 70% 12u "Use Environment Variable."
pop $2
${NSD_AddStyle} $2 ${WS_GROUP}
${NSD_CreateRadioButton} 5u 24u 70% 12u "Use central config file."
pop $3
${NSD_CreateRadioButton} 5u 36u 70% 12u "Use default %USERPROFILE%."
pop $4
; Radio Group 2
${NSD_CreateGroupBox} 0 60u 100% 50u "Select location folder"
Pop $0
${NSD_CreateRadioButton} 5u 72u 70% 12u "%APPDATA%"
pop $6
${NSD_AddStyle} $6 ${WS_GROUP}
${NSD_CreateRadioButton} 5u 84u 70% 12u "%USERPROFILE%"
pop $7
${NSD_CreateRadioButton} 5u 96u 70% 12u "PROGRAMDATA"
pop $8
nsDialogs::Show
FunctionEnd
Page Custom settingsTypePageCreate
Page InstFiles
The measurements are described in the nsDialogs documentation:
Each of the measurements that the macros take can use one of three unit types - pixels, dialog units or percentage of the dialog's size. It can also be negative to indicate it should be measured from the end. To use dialog units, the measurement must be suffixed with the letter u. To use percentage, the measurement must be suffixed with the percentage sign - %. Any other suffix, or no suffix, means pixels.
Dialog units allow creation of dialogs that scale well when different fonts or DPI is used. Its size in pixels is determined at runtime based on the font and the DPI.

Related

Using BASH to annotate Intervals

I have a very large text file with intervals of 500 (let's call it the main file.) It looks something like this:
Line1 0 500
Line1 500 1000
Line1 1000 1500
I have a second file that has different annotations at various intervals (let's call it the secondary file.)
Annotation1 379 498
Annotation2 1002 1048
....
I want to create a third file that annotates the main file with the secondary file, to look something like this:
Line1 0 500 Annotation1
Line1 500 1000 NA
Line1 1000 1500 Annotation2
In the situation of overlaps, I would prefer that the first annotation that fits the interval is placed.
Any help would be greatly appreciated!
awk 'NR==FNR{a[$2]=$1;next}{for(i in a)if(i-$2>=0 && $3-i>0)$0=$0 OFS a[i]}1' 2.txt 1.txt
Brief explanation,
NR==FNR{a[$2]=$1;next: in 2.txt, record $2 as the key and $1 as the value into array a
Scan array a to see if any key is between the range for each record in 1.txt.
Using awk:
$ awk 'NR==FNR{
min[$1]=$2
max[$1]=$3
next
}{
for(i in min){
if($2<=min[i] && $3>=max[i]){
print $0,i
next
}
}
print $0,"NA"
}' file2 file1
Line1 0 500 Annotation1
Line1 500 1000 NA
Line1 1000 1500 Annotation2
The first block statement stores the minimum, maximum and annotation values of the second file into the arrays min and max.
The second block statement loops through the array to find the annotation to print based on the max and min value of the current line. If the range doesn't match, the NA string is displayed.

remove lines with similar keyword if they appear in consecutive lines

I have got a text file of following format
sam has got grade B
score for him is 70
bob has got grade A
score for him is 90
score for him is 60
ronny has got grade B
score for him is 75
tony has got grade A
score for him is 91
As we see line 4 and line 5 both have score and the grade line is missing before line 5.
one way I could think of
grep 'grade' file.txt -A 1
However this would filter only lines where grade is missing. There could be few lines where grade is there but score is missing.
Is there any other better command in unix/linux with which we can remove such consecutive lines which either have two lines containing grade or score.
Here is my awk solution,
awk '{ if (prev != $2 $3 $4) {print $0} ; prev = $2 $3 $4 ; }' file.txt
Note that this solution has a minor bug which is if there are multiple similar lines at the end, it will output one extra line at the end which can be easily removed.
awk by default use spaces to separate words in each line and name them $1, $2, $3, etc for each word in order. prev = $2 $3 $4; will save the second + third + fourth word in variable prev. if there are consecutive lines in your case, $2, $3, $4 will be the same as those in previous line. If they are not the same, print $0 will print the whole line.
Not Bash command line, but if you want to get rid of two consecutive lines having either both 'grade' or 'score', you can open vim and run
:%s/^score.*\zs\nscore.*$//
To eliminate lines that begin with 'score' following a line that begins with 'score', and
:%s/grade.*\zs\n.*grade.*$//
To eliminate lines that have 'grade' in them following a line with 'grade in it.

I do not understand the break command

in:
#!/bin/sh
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done
the output is:
1 0
1 5
and then script stops.
how ever if the break command's argument (2) is removed, the output is:
1 0
1 5
3 0
3 5
What i am asking is why 3 0 and 3 5 are printed, when the script is conditioned not to break? script didn't print 2 0 and 2 5, and 3 0 and 3 5 should signal a break as well...
The optional argument to break tells it which loop to break out of. If the argument is omitted, it breaks out of the innermost loop. With an argument n it breaks out of the nth enclosing loop.
So break 2 breaks out of the for var1 loop, because it's the 2nd enclosing loop. If you change it to break, it just breaks out of the for var2 loop, so it goes to the next iteration of for var1.
To summarize the comments, there were two issues:
Why is 3 0 printed after a break, but not after break 2?
This was because the condition ([ $var1 -eq 2 -a $var2 -eq 0 ]) checked for equality rather than -ge, greater or equal. With -ge there will be no echos where both numbers are greater.
The break 2 instead exited both loops, thereby giving the same effect in this particular case. If the loop had been for var1 in 1 2 0, break 2 would have also prevented 0 0 from showing up since both loops would have been stopped.
Why is 2 5 not printed after a brake?
This is because the entire inner loop stops on a break, so no other iterations will have their chance to echo. To instead skip the current iteration and immediately try the next one, use continue.
Just a simple break breaks out of one loop - the inner for loop in your case.
However, if you use an additional integer in the break statement, as in break 2, then breaks out of the specified number of loops - that is two for loops in your case. Since there are no more than two nested loops and there is no more code after the outermost loop, it is effectively the same as ending the script.

How to get CPU Utilization number from top?

How would I get the number for CPU Utilization from running the top command on a specific user?
Pipe top to awk and add up the CPU utilization column:
top -b -n 1 -u username | awk 'NR>7 { sum += $9; } END { print sum; }'
That awk command says "For rows (from top) greater than row 7, add up the number in field 9 $9 and store it in variable sum. Once you have gone through all of the rows in the piped top command, print out the value in variable sum".
If the -u flag isn't working on your system, you can just stick the username search with the NR>7 condition:
top -b -n 1 | awk 'NR>7 && $2=="root" { sum += $9 } END { print sum }'
If you wanted to print the percent used for each user listed in top, you could chuck that second condition and switch sum to be an array:
top -b -n 1 | awk 'NR>7 {users[$2]+=($9)} END {for(user in users){print user,users[user]}}'
One last thing. I believe that the percent cpu may need to be divided by the number of cores in your system. Like... I believe it might be possible to see a number greater than 100 pop up here.

How can I change the order of columns and concatenate certain columns in a csv file?

I've been trying to figure this out for a while, but I have a csv file that has 13 columns. I want to concatenate columns 1, 2 and 3 (having the output be "column 3, column 1 column 2"). I then want to have the columns organized 4,7,(new concatenated column),6,9,10,11,12,13,5,8. I have found a way to use python to organize the columns, but I can't figure out how to concatenate the three fields and input that into the new csv file. Does anyone have any idea how to do this? I don't really care if it's in bash or python, or really anything. I'm fairly new to Linux scripting, so I'm not partial to any specific language.
One way using GNU awk:
awk 'BEGIN { OFS=FS=","; X = "\"" } { print $4, $7, X$3, $1 $2X $6, $9, $10, $11, $12, $13, $5, $8 }' file.txt

Resources