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

Interactive mode #145

Merged
merged 38 commits into from
May 25, 2020
Merged

Interactive mode #145

merged 38 commits into from
May 25, 2020

Conversation

christopher-dG
Copy link
Member

@christopher-dG christopher-dG commented Mar 9, 2020

Closes #110
Closes #128
Closes #90

IMO it's not great, but it does/will work. I have an idea for a package that will make this much nicer but that's an idea for the not-immediate future.

@codecov
Copy link

codecov bot commented Mar 9, 2020

Codecov Report

Merging #145 into master will decrease coverage by 0.82%.
The diff coverage is 87.09%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #145      +/-   ##
==========================================
- Coverage   90.52%   89.70%   -0.83%     
==========================================
  Files          17       18       +1     
  Lines         359      505     +146     
==========================================
+ Hits          325      453     +128     
- Misses         34       52      +18     
Impacted Files Coverage Δ
src/PkgTemplates.jl 100.00% <ø> (ø)
src/plugins/citation.jl 60.00% <ø> (ø)
src/plugins/compat_helper.jl 100.00% <ø> (ø)
src/plugins/coverage.jl 72.72% <ø> (ø)
src/plugins/git.jl 93.87% <ø> (-0.13%) ⬇️
src/plugins/project_file.jl 87.50% <ø> (ø)
src/plugins/readme.jl 100.00% <ø> (ø)
src/plugins/src_dir.jl 100.00% <ø> (ø)
src/plugins/tagbot.jl 100.00% <ø> (ø)
src/plugins/tests.jl 94.11% <ø> (ø)
... and 8 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8f13009...8f13009. Read the comment docs.

@nickrobinson251
Copy link
Collaborator

🌺

@christopher-dG christopher-dG marked this pull request as ready for review April 14, 2020 20:12
@christopher-dG
Copy link
Member Author

This can be tried out and reviewed now! Still need to write some more tests though.

Copy link
Contributor

@omus omus left a comment

Choose a reason for hiding this comment

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

Overall looks reasonable

src/interactive.jl Show resolved Hide resolved
src/interactive.jl Outdated Show resolved Hide resolved
src/interactive.jl Show resolved Hide resolved
test/interactive.jl Outdated Show resolved Hide resolved
@christopher-dG
Copy link
Member Author

I'll add a couple of additional tests today or tomorrow and then I think this is good to go.

@christopher-dG
Copy link
Member Author

Rebased, just waiting for approval.

@ericphanson
Copy link
Contributor

ericphanson commented Apr 23, 2020

I'm excited for the new PkgTemplates! Enough so that I tried out this PR :). I ran into an error and also some other sharp edges, so I'll write some feedback here in the hopes that it can help.

The error I got is here:

julia> t = interactive_template()
┌ Warning: `interactive_template()` is deprecated, use `Template(; interactive = true)` instead.
│   caller = top-level scope at REPL[3]:1
└ @ Core REPL[3]:1
Template keywords to customize:
[press: d=done, a=all, n=none]
   [X] authors
   [ ] dir
   [X] disable_defaults
   [X] host
   [X] julia
 > [X] plugins
   [X] user
Enter value for 'authors' (Vector{String}, comma-delimited): Eric P. Hanson
Select default plugins to disable:
[press: d=done, a=all, n=none]
   [X] CompatHelper
   [X] ProjectFile
   [X] SrcDir
   [X] Git
   [X] License
   [X] Readme
   [X] Tests
 > [X] TagBot
Select Git repository hosting service:
 > github.com
   gitlab.com
   bitbucket.org
   Other
Select minimum Julia version:
   1.0
   1.1
   1.2
 > 1.3
   1.4
   1.5
   Other
Select plugins:
[press: d=done, a=all, n=none]
^  [ ] Git
   [X] GitHubActions
   [ ] GitLabCI
   [ ] License
   [ ] ProjectFile
   [ ] Readme
   [ ] SrcDir
   [ ] TagBot
   [ ] Tests
 > [ ] TravisCI
ERROR: MethodError: Cannot `convert` an object of type Type{Nothing} to an object of type Union
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:171
Stacktrace:
 [1] convert(::Type{Pair{Symbol,Union}}, ::Pair{Symbol,DataType}) at ./pair.jl:71
 [2] push!(::Array{Pair{Symbol,Union},1}, ::Pair{Symbol,DataType}) at ./array.jl:913
 [3] interactive(::Type{Codecov}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:29
 [4] iterate at ./generator.jl:47 [inlined]
 [5] _collect(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}, ::Base.EltypeUnknown, ::Base.HasShape{1}) at ./array.jl:678
 [6] collect_similar(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}) at ./array.jl:607
 [7] map(::Function, ::Array{Any,1}) at ./abstractarray.jl:2072
 [8] prompt(::Type{Template}, ::Type{T} where T, ::Val{:plugins}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:152
 [9] prompt(::Type{Template}, ::Type, ::Symbol) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:103
 [10] (::PkgTemplates.var"#120#122"{Template,Dict{Symbol,Any}})(::Pair{Symbol,UnionAll}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:40
 [11] foreach(::PkgTemplates.var"#120#122"{Template,Dict{Symbol,Any}}, ::Array{Pair{Symbol,B} where B,1}) at ./abstractarray.jl:1919
 [12] interactive(::Type{Template}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:39
 [13] Template(::Val{true}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/template.jl:76
 [14] Template(; interactive::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Users/eh540/.julia/packages/PkgTemplates/mpzm5/src/template.jl:75
 [15] interactive_template() at ./deprecated.jl:67
 [16] top-level scope at REPL[3]:1
 [17] eval(::Module, ::Any) at ./boot.jl:331
 [18] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [19] run_backend(::REPL.REPLBackend) at /Users/eh540/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [20] top-level scope at none:0

I also found it kind of confusing; for example, the default plugins show up twice, once as disable-defaults and once as enable-plugins (it seems like I should only need to check the box for "enable README" once, not twice). Also in the first round I accidentally disabled all the default plugins because I assumed it was check-to-enable, not check-to-disable; it might be better to do it always as check-to-enable and if they are enabled by default, just pre-check those boxes.

Additionally, while it's nice from a package-design point of view that now everything is implemented as a plugin, as a user I at first found stuff like SrcDir and Project as plugins confusing because I'm used to those being automatically included and it's not clear what it means to check or not check that box. It could help if there was room to add a few words after each one, e.g. "SrcDir (generate the /src directory and a /src/$Package.jl file)". Also, having default plugins pre-checked would help here too, so that even if I don't know what SrcDir means, I have the visual clue to just leave it checked.

Also, I found the dir option at the first level confusing; at first I checked the box to customize it, then it asked me to Enter value for 'dir' (String): and I wasn't sure what to put, so I restarted and this time didn't check the "customize dir" box to avoid it. I guess it's something like ~/.julia/? It would help a lot if the default value was prefilled so you get an idea of what it does (i.e. which dir is it?).

Thanks for the very useful package, by the way :).

@christopher-dG
Copy link
Member Author

Thanks for testing it out!

I agree that it's kind of clunky, I kind of optimized for writing less code.
Let me make an update I was thinking about to see if I can make it a bit less bad...

@christopher-dG
Copy link
Member Author

Also I can't reproduce that error. Can you show me the exact sequence of keypresses to get there?

@nickrobinson251
Copy link
Collaborator

nickrobinson251 commented Apr 23, 2020

I also hit the same error as Eric:

julia> t = Template(interactive=true)
Template keywords to customize: 
[press: d=done, a=all, n=none]
   [ ] authors
   [ ] dir
   [ ] disable_defaults
   [ ] host
   [ ] julia
   [X] plugins
 > [X] user
Select plugins:  # a, d
[press: d=done, a=all, n=none]
   [X] AppVeyor
   [X] CirrusCI
 > [X] Citation
   [X] Codecov
   [X] CompatHelper
   [X] Coveralls
   [X] Develop
   [X] Documenter
   [X] DroneCI
v  [X] Git
AppVeyor keywords to customize:  # d
[press: d=done, a=all, n=none] 
 > [ ] coverage
   [ ] extra_versions
   [ ] file
   [ ] x86
CirrusCI keywords to customize:  # d
[press: d=done, a=all, n=none]
 > [ ] coverage
   [ ] extra_versions
   [ ] file
   [ ] image
Citation keywords to customize:  # d
[press: d=done, a=all, n=none]
 > [ ] file
   [ ] readme
ERROR: MethodError: Cannot `convert` an object of type Type{Nothing} to an object of type Union
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:171
Stacktrace:
 [1] convert(::Type{Pair{Symbol,Union}}, ::Pair{Symbol,DataType}) at ./pair.jl:71
 [2] push!(::Array{Pair{Symbol,Union},1}, ::Pair{Symbol,DataType}) at ./array.jl:913
 [3] interactive(::Type{Codecov}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:29
 [4] iterate at ./generator.jl:47 [inlined]
 [5] collect_to!(::Array{PkgTemplates.FilePlugin,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}, ::Int64, ::Int64) at ./array.jl:711
 [6] collect_to!(::Array{AppVeyor,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}, ::Int64, ::Int64) at ./array.jl:719
 [7] collect_to_with_first!(::Array{AppVeyor,1}, ::AppVeyor, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}, ::Int64) at ./array.jl:689
 [8] _collect(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}, ::Base.EltypeUnknown, ::Base.HasShape{1}) at ./array.jl:683
 [9] collect_similar(::Array{Any,1}, ::Base.Generator{Array{Any,1},typeof(PkgTemplates.interactive)}) at ./array.jl:607
 [10] map(::Function, ::Array{Any,1}) at ./abstractarray.jl:2072
 [11] prompt(::Type{Template}, ::Type{T} where T, ::Val{:plugins}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:152
 [12] prompt(::Type{Template}, ::Type, ::Symbol) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:103
 [13] (::PkgTemplates.var"#120#122"{Template,Dict{Symbol,Any}})(::Pair{Symbol,UnionAll}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:40
 [14] foreach(::PkgTemplates.var"#120#122"{Template,Dict{Symbol,Any}}, ::Array{Pair{Symbol,B} where B,1}) at ./abstractarray.jl:1919
 [15] interactive(::Type{Template}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/interactive.jl:39
 [16] Template(::Val{true}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/template.jl:76
 [17] Template(; interactive::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at /Users/npr/.julia/packages/PkgTemplates/mpzm5/src/template.jl:75
 [18] top-level scope at REPL[2]:1

@nickrobinson251
Copy link
Collaborator

I agree the new Template(interactive=true) experience as it currently is has a ways to go to meet the excellent user experience of v0.6 interactive_teimplate()

@christopher-dG
Copy link
Member Author

I think that error should be fixed with the last commit.

And yeah, I think that using the exact same interactive method for Template as all the other plugins is too big a tradeoff in usability vs amount of code, a custom method would definitely make plugin selection 500x better.
As for default values... I think we can make that better with some macro magic (I originally wanted to do this but opted for something simpler). Let me investigate that tonight...

@christopher-dG
Copy link
Member Author

christopher-dG commented Apr 24, 2020

Definitely some improvements:

julia> Template(; interactive=true)
Template keywords to customize:
[press: d=done, a=all, n=none]
 > [X] user
   [X] authors
   [X] dir
   [X] host
   [X] julia
   [X] plugins
Enter value for 'user' (String, default="christopher-dG"):
Enter value for 'authors' (Vector{String}, comma-delimited, default="Chris de Graaf <chrisadegraaf@gmail.com> and contributors"): this line is so long
Enter value for 'dir' (String, default="~/.local/share/julia/dev"): ~/code
Select Git repository hosting service:
   github.com
 > gitlab.com
   bitbucket.org
   Other
Select minimum Julia version:
 > 1.0
   1.1
   1.2
   1.3
   1.4
   1.5
   Other
Select plugins:
[press: d=done, a=all, n=none]
   [ ] CompatHelper
   [X] ProjectFile
   [X] SrcDir
   [X] Git
   [X] License
   [X] Readme
   [X] Tests
   [ ] TagBot
   [ ] AppVeyor
   [ ] CirrusCI
   [ ] Citation
   [ ] Codecov
   [ ] Coveralls
   [ ] Develop
   [X] Documenter
   [ ] DroneCI
   [ ] GitHubActions
 > [X] GitLabCI
   [ ] TravisCI
ProjectFile keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] version
   [ ] None
SrcDir keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] destination
   [ ] file
Git keywords to customize:
[press: d=done, a=all, n=none]
   [ ] email
 > [X] gpgsign
   [ ] ignore
   [ ] manifest
   [ ] name
   [ ] ssh
Enter value for 'gpgsign' (Bool, default=false): bad vlaue
Γöî Warning: Invalid input
Γöé   ex = ArgumentError: Unrecognized boolean response
Γöö @ PkgTemplates ~/code/PkgTemplates/src/interactive.jl:131
Enter value for 'gpgsign' (Bool, default=false): yes
License keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] destination
   [ ] name
   [ ] path
Readme keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] destination
   [ ] file
   [ ] inline_badges
Tests keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] file
   [ ] project
Documenter deploy style:
   Nothing
   TravisCI
 > GitLabCI
Documenter keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] assets
   [ ] index_md
   [ ] make_jl
GitLabCI keywords to customize:
[press: d=done, a=all, n=none]
 > [ ] coverage
   [ ] extra_versions
   [ ] file
Template:
  authors: ["this line is so long"]
  dir: "~/code"
  host: "gitlab.com"
  julia: v"1.0.0"
  user: "christopher-dG"
  plugins:
    Documenter:
      assets: String[]
      makedocs_kwargs: Dict{Symbol,Any}()
      canonical_url: PkgTemplates.gitlab_pages_url
      make_jl: "~/code/PkgTemplates/templates/docs/make.jl"
      index_md: "~/code/PkgTemplates/templates/docs/src/index.md"
    Git:
      ignore: String[]
      name: nothing
      email: nothing
      ssh: false
      manifest: false
      gpgsign: true
    GitLabCI:
      file: "~/code/PkgTemplates/templates/gitlab-ci.yml"
      coverage: true
      extra_versions: ["1.0", "1.4"]
    License:
      path: "~/code/PkgTemplates/templates/licenses/MIT"
      destination: "LICENSE"
    ProjectFile:
      version: v"0.1.0"
    Readme:
      file: "~/code/PkgTemplates/templates/README.md"
      destination: "README.md"
      inline_badges: false
    SrcDir:
      file: "~/code/PkgTemplates/templates/src/module.jl"
    Tests:
      file: "~/code/PkgTemplates/templates/test/runtests.jl"
      project: false

Updating the tests and adding new ones is tomorrow's job 🙂

@christopher-dG
Copy link
Member Author

The tests are fixed! I should probably write some more thorough ones for some of the trickier bits of code... maybe tomorrow.

@christopher-dG
Copy link
Member Author

The Travis failures on 1.0 are quite puzzling. I have two methods:

convert_input(::Type, T::Type, s::AbstractString) = T(s)
convert_input(P::Type, ::Type{Union{T, Nothing}}, s::AbstractString) where T = ...

It's failing on convert_input(Plugin, Union{String, Nothing}, "nothing") with a MethodError -- it's calling the first method and trying to do Union{String, Nothing}(::String). Why wouldn't the second method be used? It works fine on 1.4.

But it gets even weirder, it also works fine in my REPL on 1.0...

julia> VERSION
v"1.0.5"

julia> using PkgTemplates

julia> PkgTemplates.convert_input(PkgTemplates.Plugin, Union{String, Nothing}, "nothing")

julia> PkgTemplates.convert_input(PkgTemplates.Plugin, Union{String, Nothing}, "ahhh")
"ahhh"

@halleysfifthinc
Copy link

I just came across this error when trying this PR:

License keywords to customize:
[press: d=done, a=all, n=none]
 > [X] destination
   [X] name
   [X] path
ERROR: MethodError: no method matching defaultkw(::Type{License}, ::Val{:destination})
Closest candidates are:
  defaultkw(::Type{SrcDir}, ::Val{:destination}) at /home/allen/.julia/packages/PkgTemplates/jFRcw/src/plugin.jl:23
  defaultkw(::Type{Readme}, ::Val{:destination}) at /home/allen/.julia/packages/PkgTemplates/jFRcw/src/plugin.jl:23
  defaultkw(::Type{TagBot}, ::Val{:destination}) at /home/allen/.julia/packages/PkgTemplates/jFRcw/src/plugin.jl:23
  ...
Stacktrace:
 [1] defaultkw(::Type{License}, ::Symbol) at /home/allen/.julia/packages/PkgTemplates/jFRcw/src/template.jl:168

@christopher-dG
Copy link
Member Author

Thanks, that should be fixed now!

@christopher-dG
Copy link
Member Author

Alright, I hacked around the 1.0 issue and it seems to work okay now.
Here's to hoping that 1.5 becomes the next LTS!

@christopher-dG
Copy link
Member Author

I've also removed the root manifest... I think I'm on team no-manifest now for libraries at least.

No need to offer the unreleased 1.6 if the user is running 1.0.
This makes it a lot easier to keep nightly tests passing.
@christopher-dG
Copy link
Member Author

I would say this is ready to go. Just need a thumbs up.

src/template.jl Outdated Show resolved Hide resolved
Co-authored-by: Curtis Vogt <curtis.vogt@gmail.com>
@christopher-dG christopher-dG merged commit 18c32a1 into master May 25, 2020
@christopher-dG christopher-dG deleted the cdg/interactive branch May 25, 2020 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants