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 3 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
3 changes: 2 additions & 1 deletion 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.99-alpha)
FAKE (3.35.2)
FSharp.Compiler.Service (0.0.90)
FSharp.Formatting (2.9.9)
Expand All @@ -25,5 +26,5 @@ NUGET
GITHUB
remote: fsharp/FAKE
specs:
modules/Octokit/Octokit.fsx (38dcc9d8c61d6868601fe848d8eff765e74935f0)
modules/Octokit/Octokit.fsx (8b027106c29c4e05f30fe0dc3dbf6332293e05fa)
Octokit
175 changes: 77 additions & 98 deletions src/Projekt/Args.fs
Original file line number Diff line number Diff line change
@@ -1,111 +1,90 @@
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

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 public InitOptions =
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need for the 'public' accessor

Copy link
Author

Choose a reason for hiding this comment

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

thanks, will fix.

{ [<Value(0, Required = true, MetaName = "project path")>] path : string
Copy link
Collaborator

Choose a reason for hiding this comment

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

strictly speaking it should be a single space after { and record field names should not be lined up (personally don't care so much about the last one)

Record field names should be PascalCased

Copy link
Author

Choose a reason for hiding this comment

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

also thanks!

[<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"

let private parseDirection s =
match s with
| ToLower "up" -> Up
| ToLower "down" -> Down
| _ -> failwith "invalid direction specified"
[<Verb("reference", HelpText = "reference a dll")>]
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently this verb is for referencing projects. Referencing dlls is planned: #23 (@kjnilsson you fancy it?)

Copy link
Author

Choose a reason for hiding this comment

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

I'll clean that up for sure.

type public 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 public 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 public 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
Copy link
Collaborator

Choose a reason for hiding this comment

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

this line can be shortened by putting each record field assignment on a new line.

Copy link
Author

Choose a reason for hiding this comment

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

ah, yes, of course.

| _,_ -> failwith "invalid paths"

| ToLower "version" :: _ ->
Success Version

| 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 @> ->
[<Verb("delfile", HelpText = "Delete a file from a project")>]
type public 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"

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 = CommandLine.Parser.Default.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

80 changes: 47 additions & 33 deletions src/Projekt/Projekt.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -36,30 +36,6 @@
<DocumentationFile>.\bin\Release\Projekt.xml</DocumentationFile>
<OtherFlags>--warnon:1182</OtherFlags>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Util.fs" />
<Compile Include="Types.fs" />
<Compile Include="Template.fs" />
<Compile Include="Args.fs" />
<Compile Include="XmlLinqHelpers.fs" />
<Compile Include="Project.fs" />
<Compile Include="Main.fs" />
<None Include="bootstrap.fsx" />
<None Include="paket.references" />
<None Include="paket.template" />
</ItemGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
Expand All @@ -81,16 +57,54 @@
<Target Name="BeforeBuild">
</Target>
-->
<ItemGroup>
<Templates Include="$(SolutionDir)\templates\**\*.*"/>
</ItemGroup>
<Target Name="AfterBuild">
<Copy
SourceFiles="@(Templates)"
DestinationFolder="$(OutputPath)\templates\%(Templates.RecursiveDir)"
/>
<Copy SourceFiles="@(Templates)" DestinationFolder="$(OutputPath)\templates\%(Templates.RecursiveDir)" />
Copy link
Contributor

Choose a reason for hiding this comment

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

The Templates ItemGroup has been removed so this doesn't work anymore.

Copy link
Author

Choose a reason for hiding this comment

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

Crap, this happened because the templates node caused me to be unable to build in VS2015. Do you all have this same problem?

image

(it may be a 2015 problem)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I had that problem with VS as well, but I don't normally use VS! I just tried splitting it into a separate file, so create a new Template.targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
  <Templates Include="$(SolutionDir)\templates\**\*.*" />
</ItemGroup>
</Project>

and use <Import Project="Template.targets" />. Does that trick VS?

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, that worked. So this is one of those times where I begin to realize how much I don't know. Does msbuild not evaluate the Imported elements with the same level of rigor as top-level nodes?

Copy link
Contributor

Choose a reason for hiding this comment

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

No it absolutely does, but msbuild understands the wildcard perfectly well, I was hoping that the over-eager VS check was implemented separately.

</Target>
<Import Project="..\..\.paket\paket.targets" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Util.fs" />
<Compile Include="Types.fs" />
<Compile Include="Template.fs" />
<Compile Include="Args.fs" />
<Compile Include="XmlLinqHelpers.fs" />
<Compile Include="Project.fs" />
<Compile Include="Main.fs" />
<None Include="bootstrap.fsx" />
<None Include="paket.references" />
<None Include="paket.template" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0')">
<ItemGroup>
<Reference Include="CommandLine">
<HintPath>..\..\packages\CommandLineParser\lib\net40\CommandLine.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
<When Condition="($(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6')) Or ($(TargetFrameworkIdentifier) == 'MonoAndroid') Or ($(TargetFrameworkIdentifier) == 'MonoTouch')">
<ItemGroup>
<Reference Include="CommandLine">
<HintPath>..\..\packages\CommandLineParser\lib\net45\CommandLine.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.5'">
<ItemGroup>
Expand All @@ -111,4 +125,4 @@
</ItemGroup>
</When>
</Choose>
</Project>
</Project>
Loading