2 people like it.

Generate template definition

Instead of writing template instanciation by hand, this generate a Templates.fs file with all templates given a directory tree containing .html files.

 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: 
#r "./packages/FSharp.Management/lib/net40/FSharp.Management.dll"
#r @"./packages/FSharp.Core.Fluent-4.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1/FSharp.Core.Fluent-4.0.dll"
open System
open System.Linq
open FSharp.Core.Fluent.SeqExtensions
open FSharp.Management
open System.IO
 
let [<Literal>] solutionFolder = __SOURCE_DIRECTORY__ + "/./"
 
type fs = FileSystem< solutionFolder >
type templatesFolder = fs.WebApplication.Views
 
let rec getAllDescendants(directory: DirectoryInfo) =
  seq {
    let items = directory.GetFileSystemInfos()
    let subDirectories = items.OfType<DirectoryInfo>()
    yield! items
    for subdir in subDirectories do
      yield! getAllDescendants(subdir)
    }
let getDirectoryDescendants(directory: DirectoryInfo) = getAllDescendants(directory).OfType<DirectoryInfo>()
let getFilesDescendants(directory: DirectoryInfo) = getAllDescendants(directory).OfType<FileInfo>()
 
let getNamespaceForFolder (folder: DirectoryInfo) =
  let templatesFolderPath = ((new DirectoryInfo(templatesFolder.Path)).FullName)
  let folderFullName = folder.FullName
  if folderFullName.StartsWith(templatesFolderPath) then
    let splits =
      folderFullName.Substring(templatesFolderPath.Length).Split([|Path.DirectorySeparatorChar|], StringSplitOptions.RemoveEmptyEntries)
    printfn "%A" splits
    splits
  else
    [||]
 
let generate (baseFolder: DirectoryInfo) (baseNamespace: string array) (filename:string) =
  let titleCase = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase
  use underlying = new StreamWriter(filename)
  use writer = new System.CodeDom.Compiler.IndentedTextWriter(underlying)
  let write, indent, deindent =
    (fun (t:string) -> writer.WriteLine(t))
    , (fun () -> writer.Indent <- 1 + writer.Indent)
    , (fun () -> writer.Indent <- -1 + writer.Indent)
  let writef format = FSharp.Core.Printf.kprintf write format
 
  let files =
    getFilesDescendants baseFolder
    |> Seq.groupBy (fun f -> f.Directory)
    |> Seq.map (fun (d, files) -> getNamespaceForFolder d, files |> Seq.map (fun f -> f,f.Name) |> Seq.toArray)
    |> Seq.toArray
    |> Array.groupBy fst
    |> Array.map (fun (g, files) -> g, files |> Array.map snd |> Array.concat)
 
  for (ns, files) in files do
    let ns =
      Seq.concat [baseNamespace;ns]
      |> Seq.map titleCase
      |> String.concat "."
    writef "namespace %s" ns
    indent()
    write "open WebSharper.UI.Next.Templating"
    for (f, n) in files do
      let n =
        let splits = n.Split('.')
        splits
        |> Seq.truncate (splits.Length - 1)
        |> Seq.map titleCase
        |> String.concat ""
      writef @"type %s = Template< @""%s"" >" n f.FullName
    deindent()
  underlying.Flush()
  writer.Dispose()
 
let folder = DirectoryInfo(templatesFolder.Path)
generate folder [|"Templates"|] (fs.WebApplication.Code.``Templates.fs``)
namespace System
namespace System.Linq
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Core

--------------------
namespace Microsoft.FSharp.Core
namespace FSharp.Core.Fluent
module SeqExtensions

from FSharp.Core.Fluent
namespace FSharp.Management
namespace System.IO
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val solutionFolder : string

Full name: Script.solutionFolder
type fs = FileSystem<...>

Full name: Script.fs
type FileSystem

Full name: FSharp.Management.FileSystem
type templatesFolder = obj

Full name: Script.templatesFolder
val getAllDescendants : directory:DirectoryInfo -> seq<FileSystemInfo>

Full name: Script.getAllDescendants
val directory : DirectoryInfo
Multiple items
type DirectoryInfo =
  inherit FileSystemInfo
  new : path:string -> DirectoryInfo
  member Create : unit -> unit + 1 overload
  member CreateSubdirectory : path:string -> DirectoryInfo + 1 overload
  member Delete : unit -> unit + 1 overload
  member EnumerateDirectories : unit -> IEnumerable<DirectoryInfo> + 2 overloads
  member EnumerateFileSystemInfos : unit -> IEnumerable<FileSystemInfo> + 2 overloads
  member EnumerateFiles : unit -> IEnumerable<FileInfo> + 2 overloads
  member Exists : bool
  member GetAccessControl : unit -> DirectorySecurity + 1 overload
  member GetDirectories : unit -> DirectoryInfo[] + 2 overloads
  ...

Full name: System.IO.DirectoryInfo

--------------------
DirectoryInfo(path: string) : unit
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val items : FileSystemInfo []
DirectoryInfo.GetFileSystemInfos() : FileSystemInfo []
DirectoryInfo.GetFileSystemInfos(searchPattern: string) : FileSystemInfo []
DirectoryInfo.GetFileSystemInfos(searchPattern: string, searchOption: SearchOption) : FileSystemInfo []
val subDirectories : Collections.Generic.IEnumerable<DirectoryInfo>
(extension) Collections.IEnumerable.OfType<'TResult>() : Collections.Generic.IEnumerable<'TResult>
val subdir : DirectoryInfo
val getDirectoryDescendants : directory:DirectoryInfo -> Collections.Generic.IEnumerable<DirectoryInfo>

Full name: Script.getDirectoryDescendants
val getFilesDescendants : directory:DirectoryInfo -> Collections.Generic.IEnumerable<FileInfo>

Full name: Script.getFilesDescendants
Multiple items
type FileInfo =
  inherit FileSystemInfo
  new : fileName:string -> FileInfo
  member AppendText : unit -> StreamWriter
  member CopyTo : destFileName:string -> FileInfo + 1 overload
  member Create : unit -> FileStream
  member CreateText : unit -> StreamWriter
  member Decrypt : unit -> unit
  member Delete : unit -> unit
  member Directory : DirectoryInfo
  member DirectoryName : string
  member Encrypt : unit -> unit
  ...

Full name: System.IO.FileInfo

--------------------
FileInfo(fileName: string) : unit
val getNamespaceForFolder : folder:DirectoryInfo -> string []

Full name: Script.getNamespaceForFolder
val folder : DirectoryInfo
val templatesFolderPath : string
type Path =
  static val DirectorySeparatorChar : char
  static val AltDirectorySeparatorChar : char
  static val VolumeSeparatorChar : char
  static val InvalidPathChars : char[]
  static val PathSeparator : char
  static member ChangeExtension : path:string * extension:string -> string
  static member Combine : [<ParamArray>] paths:string[] -> string + 3 overloads
  static member GetDirectoryName : path:string -> string
  static member GetExtension : path:string -> string
  static member GetFileName : path:string -> string
  ...

Full name: System.IO.Path
val folderFullName : string
property FileSystemInfo.FullName: string
String.StartsWith(value: string) : bool
String.StartsWith(value: string, comparisonType: StringComparison) : bool
String.StartsWith(value: string, ignoreCase: bool, culture: Globalization.CultureInfo) : bool
val splits : string []
String.Substring(startIndex: int) : string
String.Substring(startIndex: int, length: int) : string
property String.Length: int
field Path.DirectorySeparatorChar
type StringSplitOptions =
  | None = 0
  | RemoveEmptyEntries = 1

Full name: System.StringSplitOptions
field StringSplitOptions.RemoveEmptyEntries = 1
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val generate : baseFolder:DirectoryInfo -> baseNamespace:string array -> filename:string -> unit

Full name: Script.generate
val baseFolder : DirectoryInfo
val baseNamespace : string array
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
val filename : string
val titleCase : (string -> string)
namespace System.Globalization
Multiple items
type CultureInfo =
  new : name:string -> CultureInfo + 3 overloads
  member Calendar : Calendar
  member ClearCachedData : unit -> unit
  member Clone : unit -> obj
  member CompareInfo : CompareInfo
  member CultureTypes : CultureTypes
  member DateTimeFormat : DateTimeFormatInfo with get, set
  member DisplayName : string
  member EnglishName : string
  member Equals : value:obj -> bool
  ...

Full name: System.Globalization.CultureInfo

--------------------
Globalization.CultureInfo(name: string) : unit
Globalization.CultureInfo(culture: int) : unit
Globalization.CultureInfo(name: string, useUserOverride: bool) : unit
Globalization.CultureInfo(culture: int, useUserOverride: bool) : unit
property Globalization.CultureInfo.CurrentCulture: Globalization.CultureInfo
property Globalization.CultureInfo.TextInfo: Globalization.TextInfo
Globalization.TextInfo.ToTitleCase(str: string) : string
val underlying : StreamWriter
Multiple items
type StreamWriter =
  inherit TextWriter
  new : stream:Stream -> StreamWriter + 6 overloads
  member AutoFlush : bool with get, set
  member BaseStream : Stream
  member Close : unit -> unit
  member Encoding : Encoding
  member Flush : unit -> unit
  member Write : value:char -> unit + 3 overloads
  static val Null : StreamWriter

Full name: System.IO.StreamWriter

--------------------
StreamWriter(stream: Stream) : unit
StreamWriter(path: string) : unit
StreamWriter(stream: Stream, encoding: Text.Encoding) : unit
StreamWriter(path: string, append: bool) : unit
StreamWriter(stream: Stream, encoding: Text.Encoding, bufferSize: int) : unit
StreamWriter(path: string, append: bool, encoding: Text.Encoding) : unit
StreamWriter(path: string, append: bool, encoding: Text.Encoding, bufferSize: int) : unit
val writer : CodeDom.Compiler.IndentedTextWriter
namespace System.CodeDom
namespace System.CodeDom.Compiler
Multiple items
type IndentedTextWriter =
  inherit TextWriter
  new : writer:TextWriter -> IndentedTextWriter + 1 overload
  member Close : unit -> unit
  member Encoding : Encoding
  member Flush : unit -> unit
  member Indent : int with get, set
  member InnerWriter : TextWriter
  member NewLine : string with get, set
  member Write : s:string -> unit + 12 overloads
  member WriteLine : unit -> unit + 14 overloads
  member WriteLineNoTabs : s:string -> unit
  ...

Full name: System.CodeDom.Compiler.IndentedTextWriter

--------------------
CodeDom.Compiler.IndentedTextWriter(writer: TextWriter) : unit
CodeDom.Compiler.IndentedTextWriter(writer: TextWriter, tabString: string) : unit
val write : (string -> unit)
val indent : (unit -> unit)
val deindent : (unit -> unit)
val t : string
CodeDom.Compiler.IndentedTextWriter.WriteLine() : unit
   (+0 other overloads)
TextWriter.WriteLine(value: decimal) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: uint64) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: uint32) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: obj) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: int64) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: int) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: float32) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(value: float) : unit
   (+0 other overloads)
CodeDom.Compiler.IndentedTextWriter.WriteLine(buffer: char []) : unit
   (+0 other overloads)
property CodeDom.Compiler.IndentedTextWriter.Indent: int
val writef : (Printf.StringFormat<'a,unit> -> 'a)
val format : Printf.StringFormat<'a,unit>
module Printf

from Microsoft.FSharp.Core
val kprintf : continutation:(string -> 'Result) -> format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.Printf.kprintf
val files : (string [] * (FileInfo * string) []) []
module Seq

from Microsoft.FSharp.Collections
val groupBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'Key * seq<'T>> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.groupBy
val f : FileInfo
property FileInfo.Directory: DirectoryInfo
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val d : DirectoryInfo
val files : seq<FileInfo>
property FileInfo.Name: string
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val groupBy : projection:('T -> 'Key) -> array:'T [] -> ('Key * 'T []) [] (requires equality)

Full name: Microsoft.FSharp.Collections.Array.groupBy
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val g : string []
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val concat : arrays:seq<'T []> -> 'T []

Full name: Microsoft.FSharp.Collections.Array.concat
val ns : string []
val files : (FileInfo * string) []
val ns : string
val concat : sources:seq<#seq<'T>> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.concat
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
val concat : sep:string -> strings:seq<string> -> string

Full name: Microsoft.FSharp.Core.String.concat
val n : string
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
val truncate : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.truncate
property Array.Length: int
StreamWriter.Flush() : unit
TextWriter.Dispose() : unit
val folder : DirectoryInfo

Full name: Script.folder
Raw view Test code New version

More information

Link:http://fssnip.net/7Ox
Posted:8 years ago
Author:Gauthier Segay
Tags: script , utility , websharper