Expect script create list and append to it - list

I'm currently trying to create a list into an expect script and to fill it later
I can declare and initialize the list as follow
#!/usr/bin/expect
set matchList [list test1 test2]
foreach elem $matchList {
puts $elem
}
Which gives the following result
$ ./tmp.expect
test1
test2
However I can't find a way to correctly append a new string to the list
I have tried several syntax without being able to find the proper way
set matchList [list $matchList test3]
Considers that 'test1 test2' is the first element and 'test3' the second
$ ./tmp.expect
test1 test2
test3
set matchList [list [foreach elem $matchList { puts $elem } ] test3]
Set the third element as an empty string and 'test3' is the fourth element
$ ./tmp.expect
test1
test2
test3
set matchList [list [foreach elem $matchList { puts $elem } ]test3]
By removing the space after the foreach block The list is correctly filled. However it seems a bit overkill to do such a simple task.
$ ./tmp.expect
test1
test2
test3
Does anybody knows how to correctly fill a list element by element into an expect script ?

The proper way to add an element to the end of a list in Tcl is to use lappend; the first argument is the name of a variable containing a list, and the second and subsequent arguments are values to append:
lappend matchList test3
That works even when values have metacharacters embedded within them.

Related

AppleScript : Copy all items of a list in the clipboard

I'm extracting a list of data from a database on a website,
How can I go set the results of items in my list to the clipboard, excluding the first result with is just a wrong link
How can I use this script in Chrome instead of Safari?
set dataINeedList to my getInputByClass2("sortable dataPersonId", 1)
-- to get the tenth value, use this --> item 10 of allData
to getInputByClass2(theClass) -- this return a list of values
tell application "Safari"
set r to do JavaScript "var outPut=[]; var arr=document.getElementsByClassName('" & theClass & "');for (var i in arr) {outPut.push(arr[i].innerHTML)};outPut;" in document 1
end tell
return strings of r --- this remove all 'Missing Value' from a list of strings
end getInputByClass2
set listSize to count of dataINeedList ## number of dataINeed founds
set theResult to item 2 of dataINeedList
##repeat with theItem in dataINeedList ## not working
## set the clipboard to theItem ##
##end repeat ##
basically, it's like this:
set x to {"a", "b", "c"}
set the clipboard to items 2 thru -1 of x

How to avoid backslashitis?

I have the following code:
proc list_backslash {} {
array unset options
array set options {
-inputs {vdd}
-outputs {vss}
}
set inputs { vdd2 vdd dvdd }
set outputs { vss2 vss dvss }
set updateOptions [ list \
-inputs $inputs \
-outputs $outputs ]
array set options $updateOptions
foreach {k v} [array get options] {
puts "$k => $v"
}
}
Since I have a lot of key-value pairs in updateOptions, there is a severe backslashitis! Is there a better way to do code updateOptions? I tried subst + braces {} and realized it does not preserve the list structure thus dooming it.
Generally speaking, if you need to continue a line you have to use a quoting mechanism of some kind with Tcl. Otherwise, the command call ends when the line ends. The [brackets] can include multiple statements too; it's legal, but really not recommended.
But that does mean that sometimes you've got awkward alternatives. Perhaps you'll be best off with doing this:
set updateOptions {
-inputs $inputs
-outputs $outputs
}
foreach {key value} $updateOptions {
set options($key) [subst $value]
}
The array set command isn't especially efficient until you get to huge numbers of options (many thousands) when the code is inside a procedure.
Or if you've got Tcl 8.6, dict map is perhaps better:
array set options [dict map {key value} $updateOptions {subst $value}]
Be aware that subst is not a particularly efficient command in Tcl 8.6 except when used with a literal argument. That's because with variable arguments, it compiles them to bytecode at runtime.
option a) Put it all on one line.
option b) Structure the code as:
set options(-inputs) $inputs
set options(-outputs) $outputs
option c) Learn to like backslashes.

Create list from list items

I am trying to crate a new array/list from an existing list of items. I am wanting to check if the item exist first, if it does not, create it then add a value to it. If it already exist just append a value. I also need a way to get the length of the total.
set Area {23401 23402 23403}
foreach Item $Area {
set ElExist [info exist ${Item}lst]
if {$ElExist == 0} {
set ${Item}lst {};
lappend ${Item}lst $TotalRecords
} else {
lappend ${Item}lst $TotalRecords
}
set CurrentOptinon [llength ${Item}lst]
}
If I was writing that code, I'd do it like this:
set Area {23401 23402 23403}
foreach Item $Area {
upvar 0 ${Item}lst lst
lappend lst $TotalRecords
set CurrentOptinon [llength $lst]
}
This will behave the same as your code, but it's so much shorter. Here's the tricks in use:
lappend creates a variable if it didn't already exist.
upvar 0 makes a local alias to a variable. So much simpler.
The alias removes the need for magic with llength, but otherwise you could have done:
set CurrentOptinon [llength [set ${Item}lst]]
The $ syntax is in many ways just a short-cut for a call to the single-argument version of set, which reads the named variable. Except if you write set then you can use substitutions in your variable name. As a rule of thumb, if you're extensively using variable names in variables without aliasing, you're probably doing something wrong (unless you really do need the name).
You're using weird variable names. Much better would be an array.
set Area {23401 23402 23403}
foreach Item $Area {
lappend lst($Item) $TotalRecords
set CurrentOptinon [llength $lst($Item)]
}
However, this is likely to require you to change code elsewhere.

How to add a static list to a list?

When adding a global variable to a list, does vim add this variable as a dynamic list?
input:
g:ListTotal = []
let g:mylist = ['hi','2','','']
call add(g:ListTotal, g:mylist)
echo g:ListTotal --> ['hi','2','',''] => ok
Then in a script g:mylist is changed p.e.
let g:mylist[0] = 'hello'
echo g:mylist --> = ['hello','2','',''] => ok
adding again this list to g:ListTotal:
call add(g:ListTotal, g:mylist)
:echo g:ListTotal -->
Output::
[['hello','2','',''],['hello','2','','']]
Expected output:
[['hi','2','',''],['hello','2','','']]
Does vim dynamically update lists when they're added to another list?
How can I add a list statically to another list?
I believe list variables are just pointers to the list so adding to list just add that pointer which is why changing looks like it changes both.
If you want a unique list you can copy the list.
call add(g:ListTotal, copy(g:mylist))
Or
call add(g:ListTotal, deepcopy(g:my list))
Read :h copy() and :h deepcopy().

How to remove element from List<string[]> and put it at the end of the list?

I have a
List<string[]> list which contains this data:
SEC Code (list[0][0])
Status (list[0][1])
ALL (list[1][0])
None (list[1][1])
The data is like this:
SEC Code ALL
Status None
I want to remove "SEC Code" and "ALL" and put them at the end of the list. I tried list.Remove, but it works for
List<string> and not for List<string[]>.
I tried list.Remove, but it works for List<string> and not for List<string[]>.
This is because list.Remove compares items for equality using the Equals(object) which arrays do not override. In order for an array to be considered equal to another array from the Equals(object)'s point of view, it must be the same array instance.
In order to remove "SEC Code" and "ALL" from an inner array you need to build a new array that is shorter by one item, like this:
var toRemove = new HashSet<string> {"SEC Code", "ALL"};
var newList = list.Select(array =>
array.Where(item => !toRemove.Contains(item)).ToArray()
).ToList();
The code above produces a list of string arrays from which all "SEC Code" and "ALL" strings have been removed.