Fork me on GitHub

Code Snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#if INTERACTIVE
#r "System.Data.Services.Client"
#r "FSharp.Data.TypeProviders"
#endif

open System
open System.Net
open System.Data.Services.Client
open Microsoft.FSharp.Data

[<Literal>]
let url = @"https://demo.crm4.dynamics.com/XRMServices/2011/OrganizationData.svc/"

[<Literal>] // "%TMP%/odata/OrganizationData.csdl"
let csdl = __SOURCE_DIRECTORY__  + @"/odata/OrganizationData.csdl" 

type Xrm = 
    TypeProviders.ODataService<
        ServiceUri = url,
        LocalSchemaFile = csdl,
        ForceUpdate = false>

let ctx = Xrm.GetDataContext()

// To be used when writing JavaScript with OData
ctx.DataContext.SendingRequest.Add (
    fun eventArgs -> printfn "-Url: %A" eventArgs.Request.RequestUri)
ctx.DataContext.SendingRequest.Add (
    fun eventArgs -> printfn "-Query: %s" eventArgs.Request.RequestUri.Query)

// Remember to "pipe" to a Sequence, in order to evaluate the Linq Query:
query { for a in ctx.AccountSet do
        where (a.AccountNumber = "42")
        select (a.AccountNumber, a.AccountId)
        skip 5
        take 1} 
|> Seq.map id

Code output:

val url : string =
  "https:demo.crm4.dynamics.com/XRMServices/2011/OrganizationData.svc/"
val csdl : string =
  "C:\Users\rsm\AppData\Local\Temp\odata\OrganizationData.csdl"
type Xrm =
  class
    static member GetDataContext : unit -> Xrm.ServiceTypes.SimpleDataContextTypes.demoContext
     + 1 overload
    nested type ServiceTypes
  end
val ctx : Xrm.ServiceTypes.SimpleDataContextTypes.demoContext
val it : unit = ()
-Uri: https:demo.crm4.dynamics.com/XRMServices/2011/OrganizationData.svc/AccountSet()?$filter=AccountNumber eq '42'&$skip=5&$top=1&$select=AccountNumber,AccountId
-Query: $filter=AccountNumber eq '42'&$skip=5&$top=1&$select=AccountNumber,AccountId
val it : seq<string * Guid> = seq []

Remark:

The reason LocalSchemaFile = csdl and ForceUpdate = false are set to static values are because Microsoft still doesn’t allow us to use OData from a server side context (we still need to login to CRM Online with a browser that supports JavaScript). If anybody have a hint on how to access the CSDL service from a .NET application, please write a comment below.

The point is that even though there is no data returned in the .NET application from CRM Online, it doesn’t matter as we just want to use the queries (nicely written in Linq with intellisense and type-safety) outputted from fun eventArgs -> printfn "-Query: %s" eventArgs.Request.RequestUri.Query for our JavaScript code in combination with the official SDK.REST.js library:

1
2
3
4
5
6
7
8
9
SDK.REST.retrieveMultipleRecords(
  "Account",
  "$filter=AccountNumber eq '42'&$skip=5&$top=1&$select=AccountNumber,AccountId", // query
  function (results) {
    // Do stuff
  },
  errorHandler,
  onCompleteHandler
);

The current way it’s done (and built on @deprecated technologies) is just not very handy (and has never been) as it requires to expand your current CRM tenant with a 3rd party managed solution:

CRM 2011 OData Query Designer

References:

Code Snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
let NOT = function | 1 -> 0 | _ -> 1
let AND x y = match x,y with | (1,1) -> 1 | _ -> 0
let OR  x y = match x,y with | (0,0) -> 0 | _ -> 1
let XOR x y = match x,y with | (1,1) | (0,0) -> 0 | _ -> 1
let NAND x y = (x,y) ||> AND |> NOT
let NOR  x y = (x,y) ||> OR  |> NOT
let XNOR x y = (x,y) ||> XOR |> NOT

let HALFADDER x y = (x,y) ||> AND,(x,y) ||> XOR
let FULLADDER x y z =
  let c,s   = (x,y) ||> HALFADDER
  let c',s' = (z,s) ||> HALFADDER
  (c,c') ||> OR, s'

let itb n =
  System.Convert.ToString(0+n, 2).PadLeft(32,'0')
  |> Seq.map string |> Seq.map int |> Seq.toList

let bti (ls:int list) =
  ls |> List.map string |> List.reduce (+)
     |> fun x -> System.Convert.ToInt32(x,2)

let add x y =
  (x |> itb , y |> itb)
  ||> List.zip
  |> List.rev
  |> List.fold(
    fun (c,zs) (x,y) -> (x,y,c) |||> FULLADDER |> fun (c',z) -> c',z::zs) (0,[])
  |> fun (x,ys) -> ys |> bti

// Eight cases:
(0,0,0) |||> FULLADDER;;
(1,0,0) |||> FULLADDER;;
(0,1,0) |||> FULLADDER;;
(1,1,0) |||> FULLADDER;;
(0,0,1) |||> FULLADDER;;
(1,0,1) |||> FULLADDER;;
(0,1,1) |||> FULLADDER;;
(1,1,1) |||> FULLADDER;;

// Examples taken from 'Domino Addition - Numberphile'
(42,17) ||> add;;
(55,27) ||> add;

Code output:

val NOT : _arg1:int -> int
val AND : x:int -> y:int -> int
val OR : x:int -> y:int -> int
val XOR : x:int -> y:int -> int
val NAND : x:int -> y:int -> int
val NOR : x:int -> y:int -> int
val XNOR : x:int -> y:int -> int
val HALFADDER : x:int -> y:int -> int * int
val FULLADDER : x:int -> y:int -> z:int -> int * int
val itb : n:int -> int list
val bti : ls:int list -> int
val add : x:int -> y:int -> int

> val it : int * int = (0, 0)
> val it : int * int = (0, 1)
> val it : int * int = (0, 1)
> val it : int * int = (1, 0)
> val it : int * int = (0, 1)
> val it : int * int = (1, 0)
> val it : int * int = (1, 0)
> val it : int * int = (1, 1)

> val it : int = 59
> val it : int = 82

References:

Code Snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
type SeqMonad() =
  member t.Bind(m,f) = Seq.concat(Seq.map f m)
  member t.Return v = seq{ yield v }
let seqMonad = SeqMonad()

let permutations ls = 
  let rec insertions x = function
    | []             -> [[x]]
    | (y :: ys) as l -> (x::l)::(List.map (fun x -> y::x) (insertions x ys))
  let rec permutations' = function
    | []      -> seq [ [] ]
    | x :: xs -> Seq.concat (Seq.map (insertions x) (permutations' xs))
  ls |> permutations'

let md5 s =
  System.BitConverter
    .ToString(
      System.Security.Cryptography.MD5
        .Create()
        .ComputeHash(buffer = System.Text.Encoding.UTF8.GetBytes(s = s)))
    .Replace("-", System.String.Empty)
    .ToLower()

let factorial n = 
  let rec fact acc = function | 0 -> acc | i -> fact (acc * i) (i - 1)
  (1,n) ||> fact

let unitTestPermutations () = 
  "FooBar" 
  |> Seq.toList
  |> fun xs -> xs |> permutations |> Seq.length,
               xs |> Seq.length   |> factorial
  |> fun (x,y) -> x = y

let unitTestMD5 () =  
  // [ mon@mbai7 tmp ] md5 -s "FooBar"
  // MD5 ("FooBar") = f32a26e2a3a8aa338cd77b6e1263c535
  "FooBar" |> md5 |> fun x -> x = "f32a26e2a3a8aa338cd77b6e1263c535"

(unitTestPermutations() && unitTestMD5()) |> function 
  | true -> () 
  | false -> failwith "Must be n! permuations per string"

let cache file =
  use reader = System.IO.File.OpenText(file)
  let rec cache' acc = function
    | true -> acc
    | false -> cache' (acc |> Set.add(reader.ReadLine())) reader.EndOfStream
  cache' Set.empty reader.EndOfStream

let root     = __SOURCE_DIRECTORY__
let wordList = System.IO.Path.Combine(root,"wordlist.txt")
let anagram  = @"poultry outwits ants"
let hash     = @"4624d200580677270a54ccff86b9610e"
let words    = anagram.Split(char " ")
let cached   = wordList |> cache

words |> Array.map(fun x  -> x  |> Seq.toList |> permutations)
      |> Array.map(fun xs -> xs |> Seq.map(fun ys -> ys |> List.map string))
      |> Array.map(fun xs -> xs |> Seq.map(fun ys -> ys |> List.reduce(+)))
      |> Array.map(fun xs -> xs |> Seq.filter(fun x -> (x,cached) ||> Set.contains))
      |> fun xs -> xs.[0],xs.[1],xs.[2]
      |> fun (xs,ys,zs) -> seqMonad{let! x = xs
                                    let! y = ys
                                    let! z = zs
                                    return (x,y,z)}
      |> Seq.map(fun (x,y,z) -> x + " " + y + " " + z)
      |> Seq.map(fun x -> x |> md5, x)
      |> Seq.filter(fun (x,y) -> x = hash)
      |> Seq.map(fun (x,y) -> y)
      |> Seq.truncate 1
      |> fun x -> x |> printfn "%A"

Code output:

type SeqMonad =
  class
    new : unit -> SeqMonad
    member Bind : m:seq<'b> * f:('b -> #seq<'d>) -> seq<'d>
    member Return : v:'a -> seq<'a>
  end
val seqMonad : SeqMonad
val permutations : ls:'a list -> seq<'a list>
val md5 : s:string -> string
val factorial : n:int -> int
val unitTestPermutations : unit -> bool
val unitTestMD5 : unit -> bool
val cache : file:string -> Set<string>
val root : string = "/Users/mon/tmp"
val wordList : string = "/Users/mon/tmp/wordlist.txt"
val anagram : string = "poultry outwits ants"
val hash : string = "4624d200580677270a54ccff86b9610e"
val words : string [] = [|"poultry"; "outwits"; "ants"|]
val cached : Set<string> =
  set
    ["a"; "a's"; "ab's"; "abaci"; "aback"; "abacus"; "abacus's"; "abacuses";
     "abaft"; ...]

Code result:

> seq []
> val it : unit = ()

References:

Code Snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
let bitlength (x:bigint) =
  let xs  = x.ToByteArray()
  let n   = xs |> Array.length
  let msb = xs.[n-1]
  let rec bitlength' a = function
    | 0uy  -> a
    | msb' -> (a+1,msb' >>> 1) ||> bitlength'
  ((n-1)*8,msb) ||> bitlength'

let split (x:bigint) m =
  let y = x >>> m
  y,(x - (y <<< m))

let karatsuba x y =
  let r = 1 <<< 10
  let leq x y = (x |> bitlength) <= y
  let rec karatsuba' = function
    | (x',y') when (x',r) ||> leq || (y',r) ||> leq -> (x' * y')
    | (x',y') ->
      let n = (x' |> bitlength, y' |> bitlength) ||> max
      let m = n >>> 1
      let h1,l1 = (x',m) ||> split
      let h2,l2 = (y',m) ||> split 
      let z0 = (l1,l2)       |> karatsuba'
      let z1 = (l1+h1,l2+h2) |> karatsuba'
      let z2 = (h1,h2)       |> karatsuba'   
      (z2 <<< (2 * m)) + ((z1 - z0 - z2) <<< m) + z0
  (x,y) |> karatsuba'

let fib n = // tail-recursive with two accs
  let rec fib' a1 a2 = function
    | 0 -> 0I
    | 1 -> a1 + a2
    | i -> fib' a2 (a1 + a2) (i - 1)
  fib' 1I 0I n

let fibfast n =
  let inline inner x y i =
    let a = x * (2I * y - x)
    let b = y * y + x * x
    match i % 2 = 0 with | true -> (a,b) | false -> (b, a+b)
  let rec fibfast' k = function
    | 0 -> k (0I,1I)
    | i -> fibfast' (fun (x,y) -> k((x,y,i) |||> inner)) (i >>> 1)
  (id,n) ||> fibfast' |> fst

let fibfastkarat n =
  let inline inner x y i =
    let a = (x,((2I,y) ||> karatsuba) - x) ||> karatsuba
    let b = ((y,y) ||> karatsuba) + ((x,x) ||> karatsuba)
    match i % 2 = 0 with | true -> (a,b) | false -> (b, a+b)
  let rec fibfastkarat' k = function
    | 0 -> k (0I,1I)
    | i -> fibfastkarat' (fun (x,y) -> k((x,y,i) |||> inner)) (i >>> 1)
  (id,n) ||> fibfastkarat' |> fst

Code output:

> val bitlength : x:bigint -> int
> val split : x:bigint -> m:int32 -> bigint * System.Numerics.BigInteger
> val karatsuba : x:bigint -> y:bigint -> System.Numerics.BigInteger
> val fib : n:int -> System.Numerics.BigInteger
> val fibfast : n:int -> System.Numerics.BigInteger
> val fibfastkarat : n:int -> System.Numerics.BigInteger

Correctness test:

1
2
3
4
5
let correctness =
  ((10. ** 6. |> int |> fib),
   (10. ** 6. |> int |> fibfast),
   (10. ** 6. |> int |> fibfastkarat))
  |> fun (x,y,z) -> x = y && x = z;;

Correctness output:

> val correctness : bool = true

Performance test:

1
2
3
4
5
6
7
8
9
let duration f =
  let t = System.Diagnostics.Stopwatch()
  t.Start()
  let x = f()
  x,t.ElapsedMilliseconds |> float

duration(fun _ -> 10. ** 6. |> int |> fib)          |> snd;;
duration(fun _ -> 10. ** 6. |> int |> fibfast)      |> snd;;
duration(fun _ -> 10. ** 6. |> int |> fibfastkarat) |> snd;;

Performance output:

> val duration : f:(unit -> 'a) -> 'a * float
> val it : float = 198480.0
> val it : float = 4623.0
> val it : float = 1082.0

References:

rename.fsx:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// -------------------------------------------------------------------------------
// Initial rename of library and project script
// -------------------------------------------------------------------------------

// Bind operator
let (>>=) m f = Option.bind f m

// Args function that parses command line arguments
let getArg argv key =
  let arg = Array.tryFind(fun (a:string) -> a.StartsWith(key)) argv
  match arg with
  | Some x -> x.Replace(key, "") |> Some
  | None -> None

// Thread-safe console logger
let ts () = System.DateTime.Now.ToString("o")           // ISO-8601
let cw (s:string) = System.Console.WriteLine(s)         // Threadsafe console writer
let cew (s:string) = System.Console.Error.WriteLine(s)  // Threadsafe console error writer
type LogLevel = Info | Warning | Error
let log level x y =
  let msg = sprintf "%s - %A: %A (%A)" (ts()) level x y
  match level with
  | LogLevel.Error -> cew msg
  | LogLevel.Info | LogLevel.Warning -> cw msg

// Generic process executer (needed for "git mv source target")
let executeProcess exe args dir =
  try
    let psi = new System.Diagnostics.ProcessStartInfo(exe,args) 
    psi.CreateNoWindow <- true        
    psi.UseShellExecute <- false
    psi.RedirectStandardOutput <- true
    psi.RedirectStandardError <- true
    psi.WorkingDirectory <- dir
    let p = System.Diagnostics.Process.Start(psi)
    let o = new System.Text.StringBuilder()
    let e = new System.Text.StringBuilder()
    p.OutputDataReceived.Add(fun x -> o.AppendLine(x.Data) |> ignore)
    p.ErrorDataReceived.Add(fun x -> e.AppendLine(x.Data) |> ignore)
    p.BeginErrorReadLine()
    p.BeginOutputReadLine()
    p.WaitForExit()
    (p.ExitCode, o.ToString(), e.ToString()) |> Some
  with ex -> log LogLevel.Error (exe,args,dir) ex; None

// Scaffold & Template
let scaffold = "FSharp.ProjectScaffold"
let template = "FSharp.ProjectTemplate"

// The name of the library (will replace "FSharp.ProjectScaffold")
let lib = 
  ((fsi.CommandLineArgs,"lib=") ||> getArg, "FSharp.Foo")
  ||> defaultArg

// The name of the project (will replace "FSharp.ProjectTemplate")
let proj =
  ((fsi.CommandLineArgs,"proj=") ||> getArg, "FSharp.Bar")
  ||> defaultArg

// Folder & file helper functions
let root = __SOURCE_DIRECTORY__
let recursively = System.IO.SearchOption.AllDirectories
let pattern filter = "*" + filter + "*"
let pattern' filter = "*" + filter
let dirs path filter =
  System.IO.Directory.EnumerateDirectories(path,filter,recursively)
let files path filter =
  System.IO.Directory.EnumerateFiles(path,filter,recursively)
let rev (s:string) =
  s |> Seq.toArray |> Array.fold(fun a x -> (x |> string) + a) ""
let replaceFirst input from to' =
  let r = new System.Text.RegularExpressions.Regex(from)
  r.Replace(input = input,replacement = to', count = 1)
let isGit =
  let exe  = "git"
  let args = sprintf "status"
  let git  = (exe,args,root) |||> executeProcess
  git |> function | Some (x,y,z) -> x = 0 | None -> false
let renameGit path path' =
  let exe  = "git"
  let args = sprintf "mv \"%s\" \"%s\"" path path'
  (exe,args,root) |||> executeProcess, path, path'
let renameDirs path path' =
  System.IO.Directory.Move(path,path') |> ignore
  (0,"","") |> Some,path,path'
let renameFiles path path' =
  System.IO.File.Move(path,path') |> ignore
  (0,"","") |> Some,path,path'
let rename' path path' =
  match isGit with
  | true -> (path,path') ||> renameGit
  | false ->
    match System.IO.File.GetAttributes(path) with
    | System.IO.FileAttributes.Directory -> (path,path') ||> renameDirs 
    | _ -> (path,path') ||> renameFiles
let rename (path:string) from to' =
  let from' = from  |> rev
  let to''  = to'   |> rev
  let path' = (path |> rev, from', to'') |||> replaceFirst |> rev
  (path,path') ||> rename'
let rollback xs = xs |> List.iter(fun (x,y) -> (y,x) ||> rename' |> ignore)

// File content helper functions
let utf8 = System.Text.UTF8Encoding.UTF8
let readLines path = System.IO.File.ReadLines(path,utf8)
let writeLines path (contents:string seq)  =
  System.IO.File.WriteAllLines(path,contents,utf8)
let copy from to' =
  System.IO.File.Copy(from,to',true)
let delete path = System.IO.File.Delete(path)
let extensions = [ ".sln"; ".fs"; ".fsx"; ".fsproj"; ".nuspec"; ".md" ]

// Rename files or directories
let renameIO from to' fn atomic' =
  try
      (root,from |> pattern) ||> fn
      |> Seq.map(fun x -> (x,from,to') |||> rename)
      |> Seq.fold(fun (i,acc) (x,y,z) ->
                  let i' =
                    match x with
                    | Some (a,b,c) -> a
                    | None -> 1
                  (i+i',(y,z)::acc)) (0,[])
      |> fun (x,y) ->
        match x with
        | 0 -> (y,atomic') ||> List.append |> Some
        | _ -> atomic' |> rollback; None
  with ex -> log LogLevel.Error (atomic',from,to') ex; None

// Update files content
let updateContent exts atomic' =
  try
    exts
    |> Seq.map(fun x -> (root,x |> pattern') ||> files)
    |> Seq.fold(fun a x -> (x,a) ||> Seq.append) Seq.empty
    |> Seq.filter(fun x -> not (x.Contains "rename.fsx"))
    |> Seq.fold(fun a x ->
                let x' = x + "_"
                x |> readLines
                  |> Seq.map(fun y -> y.Replace(scaffold,lib)
                                       .Replace(template,proj))
                  |> writeLines x'
                (x,x')::a) []
    |> Seq.iter(fun (x,y) -> (y,x) ||> copy; y |> delete)
    |> Some
  with ex ->
    let git =
      match isGit with
      | false -> (0,"","") |> Some // Not really rollback but ...
      | true ->
        let exe  = "git"
        let args = sprintf "checkout -- *"
        (exe,args,root) |||> executeProcess
    atomic' |> rollback
    log LogLevel.Error (exts,git) ex; None

// Rename with atomicity "git mv file2 file1"
[] |> Some >>= (renameIO scaffold lib dirs)
           >>= (renameIO template proj dirs)
           >>= (renameIO scaffold lib files)
           >>= (renameIO template proj files)

// Update content
           >>= (updateContent extensions)

rename.cmd:

@echo off
:: Add the paths for the F# SDK 3.x (from higher version to lower)
set FSHARPSDK=^
C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0\;^
C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0\

cls
:: Execute the script "only" with the first "fsianycpu.exe" found
for %%i in (fsianycpu.exe) do "%%~$FSHARPSDK:i" rename.fsx %*

pause

rename.sh:

#!/bin/bash
#workaround to handle different path for fsi
export FSHARPI=`which fsharpi`
cat - > fsharpi <<"EOF"
#!/bin/bash
$FSHARPI $@
EOF
chmod +x fsharpi
fsharpi rename.fsx $@
rm fsharpi

Git clone FSharp.ProjectScaffold

[ mon@mbai7 rename ] git clone git@github.com:fsprojects/FSharp.ProjectScaffold.git
Cloning into 'FSharp.ProjectScaffold'...
remote: Reusing existing pack: 674, done.
remote: Total 674 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (674/674), 593.40 KiB | 375.00 KiB/s, done.
Resolving deltas: 100% (342/342), done.
Checking connectivity... done.
[ mon@mbai7 rename ] cd FSharp.ProjectScaffold/

Grep for FSharp.ProjectScaffold and FSharp.ProjectTemplate:

[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectScaffold" .
./build.fsx:let solutionFile  = "FSharp.ProjectScaffold"
./build.fsx:let gitName = "FSharp.ProjectScaffold"
./docs/content/index.fsx:  [content]: https://github.com/fsprojects/FSharp.ProjectScaffold/tree/master/docs/content
./docs/content/index.fsx:  [gh]: https://github.com/fsprojects/FSharp.ProjectScaffold
./docs/content/index.fsx:  [issues]: https://github.com/fsprojects/FSharp.ProjectScaffold/issues
./docs/content/index.fsx:  [readme]: https://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/README.md
./docs/content/index.fsx:  [license]: https://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/LICENSE.txt
./docs/tools/generate.fsx:let website = "/FSharp.ProjectScaffold"
./docs/tools/generate.fsx:let githubLink = "http://github.com/fsprojects/FSharp.ProjectScaffold"
./docs/tools/generate.fsx:  [ "project-name", "FSharp.ProjectScaffold"
./docs/tools/generate.fsx:    "project-nuget", "http://nuget.com/packages/FSharp.ProjectScaffold" ]
./nuget/FSharp.ProjectTemplate.nuspec:    <licenseUrl>http://github.com/fsprojects/FSharp.ProjectScaffold/blob/master/LICENSE.txt</licenseUrl>
./nuget/FSharp.ProjectTemplate.nuspec:    <projectUrl>http://fsprojects.github.com/FSharp.ProjectScaffold</projectUrl>
./nuget/FSharp.ProjectTemplate.nuspec:    <iconUrl>https://raw.github.com/fsharp/FSharp.ProjectScaffold/master/nuget/logo.png</iconUrl>
./README.md:FSharp.ProjectScaffold
./README.md:      <td><a href="FSharp.ProjectScaffold.sln">FSharp.ProjectScaffold.sln</a></td>
./README.md:<a href="http://fsprojects.github.io/FSharp.ProjectScaffold" target="_blank">Sample API documents available here.</a>
./RELEASE_NOTES.md:* Changed name from fsharp-project-scaffold to FSharp.ProjectScaffold
./rename.fsx:let scaffold = "FSharp.ProjectScaffold"
./rename.fsx:// The name of the library (will replace "FSharp.ProjectScaffold")
./tests/FSharp.ProjectTemplate.Tests/Tests.fs:module FSharp.ProjectScaffold.Tests
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectTemplate" .
./build.fsx:let project = "FSharp.ProjectTemplate"
./docs/content/index.fsx:      The F# ProjectTemplate library can be <a href="https://nuget.org/packages/FSharp.ProjectTemplate">installed from NuGet</a>:
./docs/content/index.fsx:      <pre>PM> Install-Package FSharp.ProjectTemplate</pre>
./docs/content/index.fsx:#r "FSharp.ProjectTemplate.dll"
./docs/content/index.fsx:open FSharp.ProjectTemplate
./docs/content/tutorial.fsx:#r "FSharp.ProjectTemplate.dll"
./docs/content/tutorial.fsx:open FSharp.ProjectTemplate
./docs/tools/generate.fsx:let referenceBinaries = [ "FSharp.ProjectTemplate.dll" ]
./FSharp.ProjectScaffold.sln:Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.ProjectTemplate", "src\FSharp.ProjectTemplate\FSharp.ProjectTemplate.fsproj", "{7E90D6CE-A10B-4858-A5BC-41DF7250CBCA}"
./FSharp.ProjectScaffold.sln:																									 	 nuget\FSharp.ProjectTemplate.nuspec = nuget\FSharp.ProjectTemplate.nuspec
./FSharp.ProjectScaffold.sln:Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.ProjectTemplate.Tests", "tests\FSharp.ProjectTemplate.Tests\FSharp.ProjectTemplate.Tests.fsproj", "{E789C72A-5CFD-436B-8EF1-61AA2852A89F}"
./nuget/FSharp.ProjectTemplate.nuspec:    <file src="..\bin\FSharp.ProjectTemplate.dll" target="lib/net40" />
./README.md:        A good way to get started is to rename the project included in this sample (FSharp.ProjectTemplate). 
./rename.fsx:let template = "FSharp.ProjectTemplate"
./rename.fsx:// The name of the project (will replace "FSharp.ProjectTemplate")
./src/FSharp.ProjectTemplate/AssemblyInfo.fs:[<assembly: AssemblyTitleAttribute("FSharp.ProjectTemplate")>]
./src/FSharp.ProjectTemplate/AssemblyInfo.fs:[<assembly: AssemblyProductAttribute("FSharp.ProjectTemplate")>]
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj:    <RootNamespace>FSharp.ProjectTemplate</RootNamespace>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj:    <AssemblyName>FSharp.ProjectTemplate</AssemblyName>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj:    <Name>FSharp.ProjectTemplate</Name>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj:    <DocumentationFile>bin\Debug\FSharp.ProjectTemplate.xml</DocumentationFile>
./src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj:    <DocumentationFile>..\..\bin\FSharp.ProjectTemplate.xml</DocumentationFile>
./src/FSharp.ProjectTemplate/Library.fs:namespace FSharp.ProjectTemplate
./src/FSharp.ProjectTemplate/Script.fsx:open FSharp.ProjectTemplate
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:    <RootNamespace>FSharp.ProjectTemplate.Tests</RootNamespace>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:    <AssemblyName>FSharp.ProjectTemplate.Tests</AssemblyName>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:    <Name>FSharp.ProjectTemplate.Tests</Name>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:    <DocumentationFile>bin\Release\FSharp.ProjectTemplate.Tests.xml</DocumentationFile>
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:    <ProjectReference Include="..\..\src\FSharp.ProjectTemplate\FSharp.ProjectTemplate.fsproj">
./tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj:      <Name>FSharp.ProjectTemplate</Name>
./tests/FSharp.ProjectTemplate.Tests/Tests.fs:open FSharp.ProjectTemplate

Rename FSharp.ProjectScaffold and FSharp.ProjectTemplate:

[ mon@mbai7 FSharp.ProjectScaffold ] cp ../rename.* .
‘../rename.cmd’ -> ‘./rename.cmd’
‘../rename.fsx’ -> ‘./rename.fsx’
‘../rename.sh’ -> ‘./rename.sh’
[ mon@mbai7 FSharp.ProjectScaffold ] chmod +x rename.sh 
[ mon@mbai7 FSharp.ProjectScaffold ] ./rename.sh lib=Stermon.Foo proj=Stermon.Bar

Grep for FSharp.ProjectScaffold and FSharp.ProjectTemplate (again):

[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectScaffold" .
./rename.fsx:let scaffold = "FSharp.ProjectScaffold"
./rename.fsx:// The name of the library (will replace "FSharp.ProjectScaffold")
[ mon@mbai7 FSharp.ProjectScaffold ] grep -R "FSharp.ProjectTemplate" .
./rename.fsx:let template = "FSharp.ProjectTemplate"
./rename.fsx:// The name of the project (will replace "FSharp.ProjectTemplate")

Build FSharp.ProjectScaffold:

[ mon@mbai7 FSharp.ProjectScaffold ] chmod +x build.sh 
[ mon@mbai7 FSharp.ProjectScaffold ] ./build.sh 
Installing 'FAKE 2.15.2'.
Successfully installed 'FAKE 2.15.2'.
fsharpi build.fsx
Building project with version: LocalBuild
Shortened DependencyGraph for Target All:
<== All
<== RunTests
<== Build
<== AssemblyInfo
<== RestorePackages
      <== Clean

The resulting target order is:
 - Clean
 - RestorePackages
 - AssemblyInfo
 - Build
 - RunTests
 - All
Starting Target: All (==> RunTests)
Starting Target: RunTests (==> Build)
Starting Target: Build (==> AssemblyInfo)
Starting Target: AssemblyInfo (==> RestorePackages)
Starting Target: RestorePackages (==> Clean)
Starting Target: Clean 
Deleting contents of bin
Deleting contents of temp
Finished Target: Clean

...

Execution Runtime: mono-3.5
***** Stermon.Foo.Tests.hello returns 42
42

Tests run: 1, Errors: 0, Failures: 0, Inconclusive: 0, Time: 0.0387905 seconds
  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0

Finished Target: RunTests
Finished Target: All
Killing all processes that are created by FAKE and are still running.

---------------------------------------------------------------------
Build Time Report
---------------------------------------------------------------------
Target            Duration
------            --------
Clean             00:00:00.0043722
RestorePackages   00:00:02.4633336
AssemblyInfo      00:00:00.0062624
Build             00:00:05.3281672
RunTests          00:00:01.1349369
All               00:00:00.0000441
Total:            00:00:08.9734871
Status:           Ok
---------------------------------------------------------------------

Stermon.Foo and Stermon.Bar:

[ mon@mbai7 FSharp.ProjectScaffold ] ll . bin/ src/ tests/
.:
total 64K
-rw-r--r--  1 mon staff 1.2K Apr 25 18:20 LICENSE.txt
-rw-r--r--  1 mon staff  16K Apr 25 18:45 README.md
-rw-r--r--  1 mon staff  374 Apr 25 18:45 RELEASE_NOTES.md
-rw-r--r--  1 mon staff 3.2K Apr 25 18:45 Stermon.Foo.sln
-rw-r--r--  1 mon staff 1.7K Apr 25 18:48 TestResults.xml
drwxr-xr-x  5 mon staff  170 Apr 25 18:48 bin/
-rw-r--r--  1 mon staff  182 Apr 25 18:20 build.cmd
-rw-r--r--  1 mon staff 5.6K Apr 25 18:45 build.fsx
-rwxr-xr-x  1 mon staff  398 Apr 25 18:20 build.sh*
drwxr-xr-x  6 mon staff  204 Apr 25 18:20 docs/
drwxr-xr-x  3 mon staff  102 Apr 25 18:45 lib/
drwxr-xr-x  5 mon staff  170 Apr 25 18:45 nuget/
drwxr-xr-x 10 mon staff  340 Apr 25 18:48 packages/
-rw-r--r--  1 mon staff   39 Apr 25 18:44 rename.cmd
-rw-r--r--  1 mon staff 5.2K Apr 25 18:44 rename.fsx
-rwxr-xr-x  1 mon staff   59 Apr 25 18:44 rename.sh*
drwxr-xr-x  3 mon staff  102 Apr 25 18:41 src/
drwxr-xr-x  2 mon staff   68 Apr 25 18:48 temp/
drwxr-xr-x  3 mon staff  102 Apr 25 18:41 tests/

bin/:
total 12K
-rwxr-xr-x 1 mon staff 4.0K Apr 25 18:48 Stermon.Bar.dll*
-rw-r--r-- 1 mon staff  276 Apr 25 18:48 Stermon.Bar.dll.mdb
-rw-r--r-- 1 mon staff  196 Apr 25 18:48 Stermon.Bar.xml

src/:
total 0
drwxr-xr-x 7 mon staff 238 Apr 25 18:48 Stermon.Bar/

tests/:
total 0
drwxr-xr-x 7 mon staff 238 Apr 25 18:48 Stermon.Bar.Tests/

Git status:

[ mon@mbai7 FSharp.ProjectScaffold ] git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	renamed:    FSharp.ProjectScaffold.sln -> Stermon.Foo.sln
	renamed:    nuget/FSharp.ProjectTemplate.nuspec -> nuget/Stermon.Bar.nuspec
	renamed:    src/FSharp.ProjectTemplate/AssemblyInfo.fs -> src/Stermon.Bar/AssemblyInfo.fs
	renamed:    src/FSharp.ProjectTemplate/Library.fs -> src/Stermon.Bar/Library.fs
	renamed:    src/FSharp.ProjectTemplate/Script.fsx -> src/Stermon.Bar/Script.fsx
	renamed:    src/FSharp.ProjectTemplate/FSharp.ProjectTemplate.fsproj -> src/Stermon.Bar/Stermon.Bar.fsproj
	renamed:    tests/FSharp.ProjectTemplate.Tests/FSharp.ProjectTemplate.Tests.fsproj -> tests/Stermon.Bar.Tests/Stermon.Bar.Tests.fsproj
	renamed:    tests/FSharp.ProjectTemplate.Tests/Tests.fs -> tests/Stermon.Bar.Tests/Tests.fs
	renamed:    tests/FSharp.ProjectTemplate.Tests/packages.config -> tests/Stermon.Bar.Tests/packages.config

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   README.md
	modified:   RELEASE_NOTES.md
	modified:   Stermon.Foo.sln
	deleted:    bin/README.md
	modified:   build.fsx
	modified:   build.sh
	modified:   docs/content/index.fsx
	modified:   docs/content/tutorial.fsx
	modified:   docs/output/README.md
	modified:   docs/tools/generate.fsx
	modified:   lib/README.md
	modified:   nuget/README.md
	modified:   nuget/Stermon.Bar.nuspec
	modified:   packages/README.md
	modified:   src/Stermon.Bar/AssemblyInfo.fs
	modified:   src/Stermon.Bar/Library.fs
	modified:   src/Stermon.Bar/Script.fsx
	modified:   src/Stermon.Bar/Stermon.Bar.fsproj
	deleted:    temp/README.md
	modified:   tests/Stermon.Bar.Tests/Stermon.Bar.Tests.fsproj
	modified:   tests/Stermon.Bar.Tests/Tests.fs

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	rename.cmd
	rename.fsx
	rename.sh

References: