What does a double exclamation mark (!!) in Fsharp / FAKE? - f#

I've come across the following code and can not understand what operation the double exclamation marks provide. This code-snipet is from a FAKE script used in a CICD system. Microsoft's Symbol and Operator Reference does not list this operator, nor can I find it in FAKE's API Reference.
!! (projectPackagePath + "/*.zip")
|> Seq.iter(fun path ->
trace ("Removing " + path)
ShellExec tfCommand ("delete " + path + " /noprompt")
Another example of usage
let buildLabelFiles =
!!(labelPath ## "*.txt")

The !! operator takes a file pattern and returns a collection of files matching the pattern.
For example, if you want to print all text files in the current folder, you can write:
for file in !! "*.txt" do
printfn "%s" file
If you look at the operator definition in the source code, you can see that it is just an alias for creating a IGlobbingPattern value (see the type definition) that includes files given by the specified pattern. The IGlobbingPattern type implements IEnumerable, so you can iterate over the files, but you can do a couple of other things with IGlobbingPattern such as combining two file sets using ++ or removing some files from a file set using --.

Related

UltraEdit script using saveAs("^c")

I am using an Excel macro to call up UltraEdit in order to execute a script on some files.
In the Excel macro I write the path that I want the new file to be saved in by the UltraEdit script. Up until this point all work and if I do a write of the value I read in the temporary file I see that I have the correct path.
But when I use the saveAs("^c") the file does not get saved to the path I specified, but instead gets saved to the current directory.
If I use the following code it saves the file properly. But I don't want to hard code the path:
var sPath="H:\\IPEX\\DataFiles\\IPEX_Originals_Cleaned_Files\\"
+ sTransSet
+"_"
+ sDocNum
+ "_"
+ now.getFullYear()
+ month
+ day
+ "-"
+ hours
+ minutes
+ seconds
+ ".txt";
UltraEdit.saveAs(sPath);
This is the code I am trying to fix:
UltraEdit.selectClipboard(1); // switch to user clipboard #1
var sPath=asParameterList[0]
+ sTransSet
+"_"
+ sDocNum
+ "_"
+ now.getFullYear()
+ month
+ day
+ "-"
+ hours
+ minutes
+ seconds
+ ".txt";
UltraEdit.clipboardContent=sPath;
UltraEdit.outputWindow.write("sPath Value After assign= "+sPath);
UltraEdit.saveAs("^c");
The write command shows me the following:
sPath Value After assign=
H:\\IPEX\\DataFiles\\IPEX_Originals_Cleaned_Files\\856_IPEX-155630-2_20190607-152606.txt
Instead of saving the file to directory
H:\\IPEX\\DataFiles\\IPEX_Originals_Cleaned_Files\\
it saves the file to directory
H:\IPEX\DataFiles\Boomi_IPEX_Files
which is the directory of the original file.
I agree with Alexander Pavlov and his analysis of the cause of the issue. The full qualified file name in clipboard is invalid because of having leading newline characters.
And the full qualified file name string contains additionally \\ instead of just \ as directory separator. \\ within a file path is no problem for Windows file system kernel functions in comparison to the newline character which is an invalid character for a file name or path according to Microsoft's documentation Naming Files, Paths, and Namespaces. But the full qualified file name should be nevertheless 100% correct.
These issues should be best fixed in Visual Basic macro in Excel file. In Visual Basic strings the backslash character is not an escape character like in other programming and scripting languages. Therefore the file path must be defined in Visual Basic macro with just \ and not with \\. And leading spaces/tabs/newline characters should be also removed from file path string in Excel macro before copying the full qualified file name to clipboard.
It is of course also possible to use in UltraEdit script following line before saving the new file with full qualified name in clipboard.
UltraEdit.clipboardContent = UltraEdit.clipboardContent.replace(/^\s+/,"").replace(/\\\\/g,"\\");
The first replace removes all leading whitespaces according to Unicode definition and the second replace modifies all occurrences of \\ to just \ in file name string before the fixed full qualified file name is copied back to clipboard.
But there is really no need to use a clipboard as also written by Alexander Pavlov. The invalid full qualified file name string is already stored in a JavaScript String object with the not really good name sPath. A better name for this string variable would be sFullFileName. The UltraEdit function UltraEdit.saveAs() expects a String object as parameter. So it is also possible to use in UltraEdit script:
var sFullFileName = sPath.replace(/^\s+/,"").replace(/\\\\/g,"\\");
UltraEdit.saveAs(sFullFileName);
Note: Replacing all occurrences of \\ by just \ would be wrong for full qualified file name having a UNC path which must start with two backslashes.
Your debug output prints file name on a new line. It seems filename is preceded with a new line symbol. I think it is why it does not work. Try to trim all spaces and new lines from sPath up until the first character.

Invalid '`' error when using local macro

I am following instructions from this link on how to append Stata files via a foreach loop. I think that it's pretty straightforward.
However, when I try to refer to each f in datafiles in my foreach loop, I receive the error:
invalid `
I've set my working directory and the data is in a subfolder called csvfiles. I am trying to call each file f in the csvfiles subfolder using my local macro datafiles and then append each file to an aggregate Stata dataset called data.dta.
I've included the code from my do file below:
clear
local datafiles: dir "csvfiles" files "*.csv"
foreach f of local datafiles {
preserve
insheet using “csvfiles\`f'”, clear
** add syntax here to run on each file**
save temp, replace
restore
append using temp
}
rm temp
save data.dta, replace
The backslash character has meaning to Stata: it will prevent the interpretation of any following character that has a special meaning to Stata, in particular the left single quote character
`
will not be interpreted as indicating a reference to a macro.
But all is not lost: Stata will allow you to use the forward slash character in path names on any operating system, and on Windows will take care of doing what must be done to appease Windows. Replacing your insheet command with
insheet using “csvfiles/`f'”, clear
should solve your problem.
Note that the instructions you linked to do exactly that; some of the code includes backslashes in path names, but where a macro is included, forward slashes are used instead.

status clause in open statement showing strange behavior

Hi here is my fortran code
program test
implicit none
INTEGER :: ierror
character:: filename
filename="fun"
open(unit=25,file=filename ,status="replace",action="write", &
iostat=ierror)
write(*,*)ierror
end program test
I am using Chapman's book to learn Fortran 95-2003. According to him (page 219)status='replace' clause will open a new file with the name fun . If there is any file with such name, then it is deleted. But I created the file fun in the home directory where Fortran program is stored, and then ran this program. It did create a new file with name f. The file fun was not deleted. So I don't understand this behavior.... Any help appreciated......
You have declared variable filename to have type character. Since you've not specified a length the compiler understands it to have length 1, so your assignment
filename="fun"
leads to filename having the value f. Change your declaration of the variable to
character(len=3) :: filename
or, probably better,
character(len=:), allocatable :: filename
The latter version uses modern (2003 and later I think) Fortran's automatic allocation capabilities.

How can I create cross-reference when a sigil is required for referring but not for defining?

In my DSL, I have something similar to:
x = 14
y = $x + 1
So an element is defined with just its name, but when referred to, some sigil must be added. Any whitespace between the sigil and the name is forbidden when referencing the element.
How can I do this in Xtext, while still allowing cross-reference between these elements?
Because it seems to me that I either have to use two different terminals for this - one to match x and the other to match $x - but then how would the cross-reference mechanism associate them together? Or alternatively, if I define:
ElementRef: '$' [Element|ELEMENT_NAME];
then Xtext will allow whitespace between the sigil and the name, which is illegal in my DSL. I guess an option such as "do not accept whitespace at this point" would be great, but I could not find anything in the Xtext documentation about something like that.
You have to use a datatype rule for the cross-reference token and register a value converter that strips the $ sign.
ElementRef: [Element|ReferenceID];
ReferenceID hidden(): '$' ID;
The value converter is responsible for the conversion between the abstract syntax (the ID) and the concrete syntax ($ID) for your tokens. Please refer to the docs for details.

Compilation error complaining about value not being a function

I am trying to experiment in F# for one of the utility tools we need, wherein we want to trawl through a folder of xml files and look for a particular tag. If found then insert another similar tag alongwith it. Finally, output all the filenames for which such additional tags have been inserted. But am getting a compilation error, of which I am not able to make a lot of sense.
let configFile =
Directory.GetFiles(Path.Combine("rootdir", "relativepath"), #"*.xml")
|> Seq.map(fun configFileName ->
let xmlNavigator = XPathDocument(configFileName).CreateNavigator()
let node = xmlNavigator.SelectSingleNode(#"Product/ABc[#type='xyz']")
match node with
| null -> "not configuration present"
| _ ->
let nodeAppender() = node.InsertAfter("<Risk type=""abc1"" methodology=""xyz1""/>")
let parentNode = node.SelectAncestors(XPathNodeType.Root, false)
parentNode.Current.OuterXml)
|> Seq.iter (printfn "%s")
The compilation error is as below:
This value is not a function and cannot be applied
Your string is escaped improperly. It should be:
node.InsertAfter("<Risk type=\"abc1\" methodology=\"xyz1\"/>")
EDIT: Apparently I was typing this as Brian posted his answer. Either escaping each quote char or prefixing with # as-is will work.
It would help to point out what line/column the error location is at.
At a glance, in nodeAppender, it looks like you left off the # on the string literal, which means it is five strings in a row (rather than one string with escaped quotes), which may be the cause of the error.

Resources