Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: NuGet Pragma #1220

Open
wekempf opened this issue Feb 23, 2017 · 59 comments
Open

Feature Request: NuGet Pragma #1220

wekempf opened this issue Feb 23, 2017 · 59 comments

Comments

@wekempf
Copy link

wekempf commented Feb 23, 2017

Using scriptcs -install seems a bit of a hack, to be honest. This results in having to maintain multiple files. Cake and other Roslyn based tools allow you to reference NuGet packages within the script itself. It would be great if scriptcs worked the same way.

#r SomeLocalAssembly
#n SomeNuGetPackage

The #n directive would install the NuGet package(s) to a local folder (probably packages) and then reference it(them).

While making this suggestion, I'll make another. Instead of using a generic "scriptcs_packages.config" file, use a "scriptname_packages.config" file. This would allow your scripts to be in the same directory without having conflicts with the packages used (i.e. each script can use their own NuGet package versions, and restore only has to work with that scripts packages). Or, work more like the new CSPROJ and require version numbers with the #n and don't use any config file.

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@wekempf
Copy link
Author

wekempf commented Feb 24, 2017

For large multi-script projects external dependencies may make sense. I want to use scriptcs like a replacement for LinqPad, though, and in scenarios like that working with multiple files is more of a PITA than any sort of help. So, I'm glad you're receptive to the idea. :) Makes sense to me to support both modes, though that may lead to some confusion?

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@wekempf
Copy link
Author

wekempf commented Feb 24, 2017

Personally, I'd go with precedence script > script_packages.config > scriptcs_packages.config. Yes, both of the first two modes mean you only load the packages you need.

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@wekempf
Copy link
Author

wekempf commented Feb 24, 2017

I'm fine with that. I can't imagine why you'd use more than one "mode" here, so it mostly won't make a difference in practice (though obviously you have to take a stance in the implementation). I wasn't meaning to suggest I prefer precedence, only that if you used precedence I preferred that order. What ever is easiest to deal with in the implementation should be fine.

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@wekempf
Copy link
Author

wekempf commented Feb 24, 2017

Thinking about it... there's precedence even if you only use one mode. So, if there's a #r it should only use pragmas. If there's no pragmas, but a scriptname_packages.config it should use that. If there's neither it should use scriptcs_config.packages if it exists.

I wouldn't mind helping... except my plate is pretty full at the moment. Can't really commit to it right now. :(

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@wekempf
Copy link
Author

wekempf commented Feb 24, 2017

LOL. Yep, I get it. And while I'd love this feature sooner than later, I don't expect you or anyone else to do what I can't (i.e. drop everything else and get this done). If time opens up and this feature hasn't been tackled by someone yet, I'll giver her a go.

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@glennblock
Copy link
Contributor

glennblock commented Feb 24, 2017 via email

@forki
Copy link

forki commented Feb 25, 2017

Just for reference: fsharp/fslang-suggestions#542 (comment)

This is now a very active topic in F# language design.
We already have a prototype. Paket is also generating csx files for loading. It would be cool if we could create something that's working in both scripting environments

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017 via email

@glennblock
Copy link
Contributor

Interesting @forki so reading through sounds like #r NuGet:foo.1.0 is another consideration and would allow support for other package managers.

@forki
Copy link

forki commented Feb 25, 2017

yes we will make the FSharp.Compiler.Service pluggable.
But tbh Paket is the only tool that you will find that is ready for such things and allows to generate load scripts (see https://fsprojects.github.io/Paket/paket-generate-load-scripts.html#Generating-load-scripts-for-all-NuGet-packages). As I said it already create csx load scripts which loads dlls even from transitive dependencies.

As the following pic shows we already have IDE support:

image

This works since we put it into the FSharp.Compiler.Service, so every tool that uses that will automatically work. So we will see support in VS Code via ionide, in VS, in FAKE, ...

A WIP PR can be found at dotnet/fsharp#2483

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017 via email

@forki
Copy link

forki commented Feb 25, 2017

all I'm saying is: it's basically there for you to use ;-)

@glennblock
Copy link
Contributor

Coo. @forki how are you handling semver ranges, is there a way to specify version constraints programatically?

Also. of we take a hard dependency on Paket over NuGet, is there anything we lose? (Sorry not very familiar with Paket).

@forki
Copy link

forki commented Feb 25, 2017 via email

@forki
Copy link

forki commented Feb 25, 2017 via email

@glennblock
Copy link
Contributor

I prefer options as well, but maybe we only include Paket out of the box IF it solves all the use cases. Is there a delta, are there things that Paket cannot support for example? Will it work for pure C# script projects? I know we have some support for Paket today in scriptcs, but not sure to what degree.

@glennblock
Copy link
Contributor

@forki in terms of ranges I meant in the declarative syntax?

@forki
Copy link

forki commented Feb 25, 2017

You can use everything from https://fsprojects.github.io/Paket/dependencies-file.html

so it could look like this:

#r "paket: NUnit ~> 2.6.3"
#r "paket: DotNetZip >= 1.9"
....
using NUnit;

And Paket will make sure that you get a sound resolution and all packages + transitive dependencies are loaded into the script.

Will it work for pure C# script projects

Paket is not bound to F#. Tbh most of paket's users are C# users.

@glennblock
Copy link
Contributor

OK, and is there a delta of capability? Or is it all net positive above what NuGet offers?

@forki
Copy link

forki commented Feb 25, 2017

we don't do things like running powershell scripts on install - which we consider wrong
But most things work as expected. Especially from scripting perspective

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017

@forki that's ok, we don't run Powershell scripts either, though we do have the ability to include C# scripts in the package and even to author packages that are pure script.

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017

For reference see Script Libraries

@forki
Copy link

forki commented Feb 25, 2017

we're currently trying to extract that bit into another dll. Maybe we can put that on nuget eventually

@glennblock
Copy link
Contributor

That would be great, but what is the time scale of "eventually" :-) ?

@glennblock
Copy link
Contributor

@forki I am happy initially to take a source dependency if it gets us what we need.

@forki
Copy link

forki commented Feb 25, 2017

we started with this 2 days ago. It will take some time to get it really really working. But I guess after we settled on language design we can probably start to push alpha packages.

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017 via email

@glennblock
Copy link
Contributor

@forki one question I have is what is to gain from generating a load script? Is the main goal to improve startup time?

@forki
Copy link

forki commented Feb 25, 2017

Try to reference a meta package like FsLab which consists of many many tools and libraries and creates a full data science environment in your scripting environment.

It's important to load all the libs in a sound order otherwise things crash. Paket's heuristic does that for you.

@smoothdeveloper
Copy link

@glennblock generating load script has been useful to paket users that want to script in F# (or C# but scriptcs already has some support via packages.config as I'm reading) today using nuget packages.

That feature was implemented for practical reason and generating scripts sounded like a simple solution to work across all tooling with plain #r / #load directives.

In a future release of F# / F# tooling, we'd like to go the extra step of backing this support in a more transparent / out of box way.

@adamralph
Copy link
Contributor

What I'd really like to see is a common approach to this across fsi.exe, scriptcs, csi.exe, etc.

@smoothdeveloper
Copy link

@adamralph I think currently what paket generates works in scriptcs/csi as well as fsi (for assembly references pulled from nuget dependency graph), it just works based on #r and #load.

@forki
Copy link

forki commented Feb 25, 2017 via email

@adamralph
Copy link
Contributor

Is it worth opening a dialog with Roslyn to see what they would be willing to do in csi.exe?

@adamralph
Copy link
Contributor

BTW, there's open conversation at https://gitter.im/dotnet-scripting/general

@wekempf
Copy link
Author

wekempf commented Feb 25, 2017 via email

@glennblock
Copy link
Contributor

@adamralph I thought when we talked to Roslyn we were thinking around overload #load and that it was the responsibility of different hosts to implement it.

Sounds like with the F# direction the overloading is of #r or adding specific directives for nuget, paket, etc.

@glennblock
Copy link
Contributor

@forki, @smoothdeveloper and I have just been chatting on gitter and have agreed to try to work on this together (and we'd welcome your help).

I created this branch for us to work out of: https://github.com/scriptcs/scriptcs/tree/paket-directive

@smoothdeveloper
Copy link

@forki I intend to look at your visualfsharp branch and try to spit the paket logic (part not tied to F# compiler) into at least a file, and maybe a project, then work with @glennblock to add that in their solution (bypass nuget package for now as we are pretty much experimenting on all sides).

ScriptCS could be the first scripting environment (after the FAKE for .net core branch) to have inline paket support 😄

@glennblock
Copy link
Contributor

glennblock commented Feb 25, 2017

For scriptcs, having looked over the code a bit, I think this is fairly straight forward to plug in as a POC, but it we will be more work to get the "right" design for scriptcs.

We already pick up all #r references in all files as part of our pre-processing step. Right now we do validation at the time we see the directive that the reference is a valid path. So that logic will have to change if the #r starts with "paket:" or whatever. Then I need to change where references are handled so that it can pass them off to paket (using the new code). We agreed that the path of least resistance for the new code would be to add an F# project to scriptcs that will contain this code This would be the MVP

The further design would be to make #r extensible and allow plugging in other handlers, but we can worry about that later.

@smoothdeveloper
Copy link

smoothdeveloper commented Feb 26, 2017

I've made PR: #1221 first thing needed is to update build scripts to call the paket invocations I'm describing in the PR.

@glennblock I've made you a collaborator on my fork so you can push directly there if that's convenient.

Currently on F# side, we haven't decided final syntax, but it might be safer for now to use #r with some protocol prefix rather than top level directives:

our current code works with #r "paket:nuget NugetPackageName"

@glennblock
Copy link
Contributor

Making some progress (hacking together right now). Here is a package getting installed from the REPL.

screen shot 2017-02-27 at 2 02 17 am

@wekempf
Copy link
Author

wekempf commented Feb 27, 2017

+1 Really like where this is going.

@adamralph
Copy link
Contributor

One thing I'm not understanding right now is why "paket" appears in the syntax (also true of the F# proposal). I want to use a NuGet package. Why do I care whether Paket is downloading it behind the scenes, or NuGet.Core, or hand-rolled code playing with the HTTP API. Should I expect a specific behaviour because I state "paket"?

@smoothdeveloper
Copy link

@adamralph I think the idea is you could also have "nuget: " or other handlers.

When it relates to big package graph, transitive dependencies, choosing paket or nuget makes a difference, right now the branch is for handling paket case (with paket semantics) but more could be added if needed.

It is possible in future we will support #load "paket: paket file dependency" as well (check paket github file dependencies: https://fsprojects.github.io/Paket/github-dependencies.html).

If scriptcs decides to rely on paket but hide that to users, you can preprocess directives and pass it to our handler with the correct prefix behind the scene.

@glennblock
Copy link
Contributor

@wekempf making progress here, see screenshots below. If you want to try it out, you can clone the paket-directive branch. You'll need to have MSBuild tools 2015 installed as well.

REPL

screen shot 2017-03-05 at 2 52 23 pm

Script

screen shot 2017-03-05 at 3 58 10 pm

@adamralph
Copy link
Contributor

Is it worth also having a common syntax which doesn't specify a package provider, in which case the script runner uses its default, e.g.

#r "nuget newtonsoft.json"

That way we can have a common syntax which works across all runners, without requiring all of them to support packet: , nuget: , etc. The provider can still be specified optionally, for those runners which support that particular provider.

@peder
Copy link

peder commented Jun 15, 2017

I've dug through dozens of issues related to this one in the F#, Roslyn, and OmniSharp repos. What is the status of referencing NuGet packages in VSCode with scriptcs? I've seen animated gifs of this working in F#, but does an option currently exist for C# devs? I can't find a wiki page or any blog posts suggesting that it currently is possible, but there are pull requests and dozens of issues on the topic, so I'm hoping someone can speak to the overall status of Intellisense with NuGet packages from VSCode.

@andmos
Copy link
Contributor

andmos commented Jul 27, 2017

@peder the support for referencing NuGet packages in generalized C# scripts got merged to Omnisharp after work from @seesharper. See this pull-request. Might be what you are looking for?

@fakhrulhilal
Copy link

RosylynPad has nice syntax to refers nuget package. It would be nice to use this syntax. So we can use this editor to build some scripts. It's lighter than VS. I wish by using this, so the ScriptCS would find the package in nuget's package cache instead of its own package management. Saving some storage, integrating with other package usage. So, instead of scriptcs -install [package], it would be better to use this nuget install [package]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants