Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Address #27 from fsprojects/Projekt #32

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ Target "AssemblyInfo" (fun _ ->
Attribute.Description summary
Attribute.Version release.AssemblyVersion
Attribute.FileVersion release.AssemblyVersion
Attribute.InternalsVisibleTo "Projekt.Tests" ]
Attribute.InternalsVisibleTo "Projekt.Tests"
Attribute.Company "fsprojects" ]

let getProjectDetails projectPath =
let projectName = System.IO.Path.GetFileNameWithoutExtension(projectPath)
Expand Down
2 changes: 1 addition & 1 deletion paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ nuget NUnit
nuget NUnit.Runners
nuget FAKE
nuget SourceLink.Fake
nuget UnionArgParser
nuget CommandLineParser prerelease

github fsharp/FAKE modules/Octokit/Octokit.fsx
4 changes: 2 additions & 2 deletions paket.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
NUGET
remote: https://nuget.org/api/v2
specs:
CommandLineParser (2.0.223-beta)
FAKE (3.35.2)
FSharp.Compiler.Service (0.0.90)
FSharp.Formatting (2.9.9)
Expand All @@ -21,9 +22,8 @@ NUGET
Octokit (0.13.0)
Microsoft.Net.Http
SourceLink.Fake (0.5.0)
UnionArgParser (0.8.7)
GITHUB
remote: fsharp/FAKE
specs:
modules/Octokit/Octokit.fsx (38dcc9d8c61d6868601fe848d8eff765e74935f0)
modules/Octokit/Octokit.fsx (f8684a9a3ccd1e0e78b77925a2aa2c259f6787dc)
Octokit
196 changes: 99 additions & 97 deletions src/Projekt/Args.fs
Original file line number Diff line number Diff line change
@@ -1,111 +1,113 @@
module Projekt.Args

open Projekt.Types
open System.IO
open Nessos.UnionArgParser

type private Args =
| Template of string
| [<AltCommandLine("-fxv")>] FrameworkVersion of string
| Organisation of string
| Direction of string
| Repeat of int
| Link of string
| Compile of bool
with
interface IArgParserTemplate with
member s.Usage =
match s with
| Template _ -> "init -- specify the template (library|console) [default: library]"
| Direction _ -> "movefile -- specify the direction (down|up)"
| Repeat _ -> "movefile -- specify the distance [default: 1]"
| FrameworkVersion _ -> "init -- specify the framework version (4.0|4.5|4.5.1) [default: 4.5]"
| Organisation _ -> "init -- specify the organisation"
| Link _ -> "addfile -- specify an optional Link attribute"
| Compile _ -> "addfile -- should the file be compiled or not [default: true]"
module Args =
open CommandLine
open CommandLine.Text

let private templateArg (res : ArgParseResults<Args>) =
match res.TryGetResult(<@ Template @>) with
| Some (ToLower "console") -> Console
| Some (ToLower "library") -> Library
| None -> Library
| _ -> failwith "invalid template argument specified"
[<Verb("init", HelpText = "create a new project")>]
type InitOptions =
{ [<Value(0, Required = true, MetaName = "project path")>] Path : string
[<Option(Default = "library")>] Template : string
[<Option(Default = "4.5")>] FrameworkVersion : string
[<Option>] Organization : string option }
with
member x.ToOperation =
match x.Path with
| FullPath p ->
let template = x.Template |> Template.Create |> Some
let frmwkVersion = x.FrameworkVersion |> FrameworkVersion.Create |> Some
(ProjectInitData.create
p
template
frmwkVersion
x.Organization) |> Init

let private frameworkVersionArg (res : ArgParseResults<Args>) =
match res.TryGetResult(<@ FrameworkVersion @>) with
| Some "4.0" -> V4_0
| Some "4.5" -> V4_5
| Some "4.5.1" -> V4_5_1
| None -> V4_5
| _ -> failwith "invalid framework version argument specified"
| _ -> failwith "not given a full path"
[<Usage(ApplicationAlias = "projekt")>]
static member Examples
with get () =
seq {
yield Example("normal usage", {Path = @"c:\code\projekt\"; Template = ""; FrameworkVersion = ""; Organization = None})
yield Example("make an exe project", {Path = @"c:\code\projekt\"; Template = "console"; FrameworkVersion = ""; Organization = None})
yield Example("target .net 4.0", {Path = @"c:\code\projekt\"; Template = ""; FrameworkVersion = "4.0"; Organization = None})
}

let private parseDirection s =
match s with
| ToLower "up" -> Up
| ToLower "down" -> Down
| _ -> failwith "invalid direction specified"
[<Verb("reference", HelpText = "reference another dependency in this project")>]
type private ReferenceOptions =
{ [<Value(0, Required = true, MetaName = "project path")>] ProjectPath : string
[<Value(1, Required = true, MetaName = "reference path")>] ReferencePath : string }
with
member x.ToOperation =
match x.ProjectPath, x.ReferencePath with
| FullPath project, FullPath reference ->
{ ProjPath = project
Reference = reference }
|> Reference
| _,_ -> failwith "one or both paths were invalid"

let private parser = UnionArgParser.Create<Args>()

let private (|Options|) (args : string list) =
let results = parser.Parse(List.toArray args)
results

let (|FullPath|_|) (path : string) =
try
Path.GetFullPath path |> Some
[<Verb("movefile", HelpText = "Move a file within a project")>]
type private MoveFileOptions =
{ [<Value(0, Required = true, MetaName = "project path")>] ProjectPath : string
[<Value(1, Required = true, MetaName = "file path")>] FilePath : string
[<Option(Required = true)>] direction : string
[<Option(Default = 1)>] repeat : int }
with
| _ -> None

let commandUsage = "projekt (init|reference|movefile|addfile|delfile|version) /path/to/project [/path/to/(file|project)]"
member x.ToOperation =
match x.ProjectPath, x.FilePath, Direction.Create x.direction with
| FullPath project, FullPath file, dir ->
{ ProjPath = project
FilePath = file
Direction = dir
Repeat = x.repeat }
|> MoveFile
| _,_,_ -> failwith "invalid paths or direction"

let parse (ToList args) : Result<Operation> =
try
match args with
| [] ->
parser.Usage commandUsage
|> Failure
[<Verb("addfile", HelpText = "Add a file to a project")>]
type private AddFileOptions =
{ [<Value(0, Required = true, MetaName = "project path")>] ProjectPath : string
[<Value(1, Required = true, MetaName = "file path")>] FilePath : string
[<Option>] link : string option
[<Option(Default = true)>] compile : bool }
with
member x.ToOperation =
match x.ProjectPath, x.FilePath with
| FullPath project, FullPath file ->
{ ProjPath = project
FilePath = file
Link = x.link
Compile = x.compile }
|> AddFile
| _,_ -> failwith "invalid paths"

| ToLower "version" :: _ ->
Success Version
[<Verb("delfile", HelpText = "Delete a file from a project")>]
type private DelFileOptions =
{ [<Value(0, Required = true, MetaName = "project path")>] ProjectPath : string
[<Value(1, Required = true, MetaName = "file path")>] FilePath : string }
with
member x.ToOperation =
match x.ProjectPath, x.FilePath with
| FullPath project, FullPath file ->
// typing needed here because of the duplication between MoveFileData and DelFileData records
// TODO: maybe consolidate?
({ ProjPath = project
FilePath = file } : DelFileData)
|> DelFile
| _,_ -> failwith "invalid paths"

| ToLower "init" :: FullPath path :: Options opts ->
let template = templateArg opts
let fxv = frameworkVersionArg opts
let org =
match opts.TryGetResult(<@ Organisation @>) with
| Some org -> org
| None -> "MyOrg"
Init (ProjectInitData.create (path, template, fxv, org)) |> Success

| ToLower "addfile" :: FullPath project :: FullPath file :: Options opts ->
let compile = opts.GetResult(<@ Compile @>, true)
AddFile { ProjPath = project
FilePath = file
Link = opts.TryGetResult <@ Link @>
Compile = compile }
|> Success

| [ToLower "delfile"; FullPath project; FullPath file] ->
DelFile { ProjPath = project; FilePath = file }
|> Success

| ToLower "movefile" :: FullPath project :: FullPath file :: Options opts
when opts.Contains <@ Direction @> ->
let private parser = CommandLine.Parser.Default

let direction = opts.PostProcessResult(<@ Direction @>, parseDirection)
MoveFile { ProjPath = project
FilePath = file
Direction = direction
Repeat = opts.GetResult(<@ Repeat @>, 1)}
|> Success

| [ToLower "reference"; FullPath project; FullPath reference] ->
Reference { ProjPath = project; Reference = reference } |> Success
let parse args =
let parsed = parser.ParseArguments<InitOptions, ReferenceOptions, MoveFileOptions, AddFileOptions, DelFileOptions>(args)
// tried to get fancy here with a statically resolved type param to invoke the ToOperation member on the individal option cases, but I couldn't get it to work....

| _ -> Failure (parser.Usage (sprintf "Error: '%s' is not a recognized command or received incorrect arguments.\n\n%s" args.Head commandUsage))
with
| :? System.ArgumentException as e ->
let lines = e.Message.Split([|'\n'|])
let msg = parser.Usage (sprintf "%s\n\n%s" lines.[0] commandUsage)
Failure msg
parsed.Return<InitOptions, ReferenceOptions, MoveFileOptions, AddFileOptions, DelFileOptions, Result<Operation>>(
(fun (init : InitOptions) -> init.ToOperation |> Success),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are the parens needed here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are, since this call is a C#-style method call which needs the whole batch of tupled arguments . If I remove the parens and the separating commas the call doesn't compile.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you leave the commas in you can remove the parens - minor detail tho :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly no :( I tried that earlier to no avail.
image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah well :)

On Mon, 3 Aug 2015 at 16:17 Chester Husk III [email protected]
wrote:

In src/Projekt/Args.fs
#32 (comment):

  •    | _ -> Failure (parser.Usage (sprintf "Error: '%s' is not a recognized command or received incorrect arguments.\n\n%s" args.Head commandUsage))
    
  • with
  • | :? System.ArgumentException as e ->
  •        let lines = e.Message.Split([|'\n'|])
    
  •        let msg = parser.Usage (sprintf "%s\n\n%s" lines.[0] commandUsage)
    
  •        Failure msg
    
  •    parsed.Return<InitOptions, ReferenceOptions, MoveFileOptions, AddFileOptions, DelFileOptions, Result<Operation>>(
    
  •        (fun (init : InitOptions) -> init.ToOperation |> Success),
    

Sadly no :( I tried that earlier to no avail.
[image: image]
https://cloud.githubusercontent.com/assets/573979/9040587/c1d6dfc6-39c8-11e5-99fb-4785bd81c1f2.png


Reply to this email directly or view it on GitHub
https://github.com/fsprojects/Projekt/pull/32/files#r36095400.

(fun (ref : ReferenceOptions) -> ref.ToOperation |> Success),
(fun (mv : MoveFileOptions) -> mv.ToOperation |> Success),
(fun (add : AddFileOptions) -> add.ToOperation |> Success),
(fun (del : DelFileOptions) -> del.ToOperation |> Success),
(fun errs -> errs |> Seq.map (fun e -> e.ToString()) |> String.concat ";" |> Failure)
)

1 change: 1 addition & 0 deletions src/Projekt/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ open System.Runtime.CompilerServices
[<assembly: AssemblyVersionAttribute("0.0.2")>]
[<assembly: AssemblyFileVersionAttribute("0.0.2")>]
[<assembly: InternalsVisibleToAttribute("Projekt.Tests")>]
[<assembly: AssemblyCompanyAttribute("fsprojects")>]
do ()

module internal AssemblyVersionInformation =
Expand Down
16 changes: 5 additions & 11 deletions src/Projekt/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ open System.Xml.Linq

[<EntryPoint>]
let main argv =
let op =
match Args.parse argv with
let newOp =
match Args.Args.parse argv with
| Success op -> op
| Failure msg ->
eprintfn "%s" msg
Exit

| Failure _ -> Exit

let save (el : XElement) (path: string) =
try
el.Save path
Expand All @@ -32,7 +30,7 @@ let main argv =
if Directory.Exists cur then cur
else eprintfn "Error: project template directory not found at '%s'" cur; exit 1

match op with
match newOp with
| Init data ->
match Template.init templatesDir data with
| Success _ -> 0
Expand All @@ -55,10 +53,6 @@ let main argv =
Project.addReference path reference
|> saveOrPrintError path

| Version ->
printfn "projekt %s" AssemblyVersionInformation.Version
0

| _ ->
1

Loading