Skip to content

Add support for playgrounds with multiple pages#34

Merged
ashfurrow merged 7 commits into
playgroundbooks:masterfrom
dionlarson:add-playgroundpages-support
Mar 15, 2017
Merged

Add support for playgrounds with multiple pages#34
ashfurrow merged 7 commits into
playgroundbooks:masterfrom
dionlarson:add-playgroundpages-support

Conversation

@dionlarson
Copy link
Copy Markdown
Collaborator

@dionlarson dionlarson commented Sep 15, 2016

Playgrounds for Xcode can have multiple pages. When you add a new page, the file structure becomes:

Chapter\ 1.playground/
├── Pages
│   ├── My\ First\ Page.xcplaygroundpage
│   │   └── Contents.swift
│   └── My\ Second\ Page.xcplaygroundpage
│       └── Contents.swift
├── Sources
│   └── Preamble.swift
├── contents.xcplayground
└── playground.xcworkspace
    ├── contents.xcworkspacedata
    └── xcuserdata
        └── [USERNAME].xcuserdatad
            └── UserInterfaceState.xcuserstate

The default Playground (with only one page) has a file structure of:

Chapter\ 2.playground/
├── Contents.swift
├── contents.xcplayground
└── playground.xcworkspace
    ├── contents.xcworkspacedata
    └── xcuserdata
        └── [USERNAME].xcuserdatad
            └── UserInterfaceState.xcuserstate

I believe that taking advantage of this structure is better than putting everything in a single Contents.swift. This is currently just a proof of concept (not fully implemented and no tests).

Work in Progress:

  • Transfer the entire contents of Sources instead of looking for Sources/Preample.swift
  • Transfer contents of Resources from .playground to .playgroundchapter
  • Transfer contents of Sources from .xcplaygroundpage to .playgroundpage
  • Transfer contents of Resources from .xcplaygroundpage to .playgroundpage
  • Decide if old way (single file with //// split) should still be supported
  • Update documentation
  • Rip out //// code
  • Update tests

You can test it against this repo (the generated .playgroundbook is included in the repo).

@ashfurrow
Copy link
Copy Markdown
Member

Fascinating! I didn't realize that, that make writing playgrounds books inside playgrounds much much easier, thank you for the pull request! The example repo really helped me understand what was going on. I'll take a look at adding tests later 👍

@dionlarson
Copy link
Copy Markdown
Collaborator Author

Yeah, with support for this, writing Playgrounds for iPad will be much more manageable. Thank you for getting a large bulk of the work done! I've written a bunch of interactive/visual Playgrounds for Xcode and I'm in the process of deciding what to port over.

In addition to the root Sources folder, each .xcplaygroundpage can also have it's own Sources (and even Resources) folder. These files are only accessible to that page.

Conditionals.playground/
├── Pages
│   ├── 01-If-Statements.xcplaygroundpage
│   │   ├── Contents.swift
│   │   └── timeline.xctimeline
│   ├── 02-If-Else.xcplaygroundpage
│   │   ├── Contents.swift
│   │   └── timeline.xctimeline
│   ├── 03-Boolean-Logic.xcplaygroundpage
│   │   ├── Contents.swift
│   │   └── timeline.xctimeline
│   ├── 04-Chaining-Ifs.xcplaygroundpage
│   │   ├── Contents.swift
│   │   ├── Sources
│   │   │   └── GameScene+BrakeHard.swift
│   │   └── timeline.xctimeline
│   └── 05-A-classic-challenge.xcplaygroundpage
│       └── Contents.swift
├── Resources
│   ├── Exhaust.sks
│   ├── GameScene.sks
│   ├── Info.plist
├── Sources
│   └── GameScene.swift
├── contents.xcplayground
└── playground.xcworkspace
    ├── contents.xcworkspacedata
    └── xcuserdata
        └── [USERNAME].xcuserdatad
            └── UserInterfaceState.xcuserstate

It looks like this is also true of .playgroundpage in .playgroundbook.

├── Contents
│   ├── Chapters
│   │   ├── Document1.playgroundchapter
│   │   │   ├── Manifest.plist
│   │   │   └── Pages
│   │   │       ├── Challenge1.playgroundpage
│   │   │       │   ├── Contents.swift
│   │   │       │   ├── LiveView.swift
│   │   │       │   ├── Manifest.plist
│   │   │       │   └── Sources
│   │   │       │       ├── Assessments.swift
│   │   │       │       ├── Commands.swift
│   │   │       │       └── Setup.swift
[...]

@dionlarson
Copy link
Copy Markdown
Collaborator Author

Alright, this now supports .playground and .xcplaygroundpage level Source and Resource folders. You can test it against this repo (the generated .playgroundbook is included in the repo).

Do you think //// should still be supported @ashfurrow ?

@ashfurrow
Copy link
Copy Markdown
Member

That's an excellent question. I think if Xcode Playgrounds support pages out of the box, our abstraction no longer provides significant value. I'm wary of removing it only because of anyone still using the tool, a note in the readme and updating my blog post should mitigate that risk.

@ashfurrow
Copy link
Copy Markdown
Member

@orta @rpowelll I'd love to hear your thoughts on this question ^

@orta
Copy link
Copy Markdown
Collaborator

orta commented Sep 16, 2016

Thanks for the poke was not watching, lets have a look

@orta
Copy link
Copy Markdown
Collaborator

orta commented Sep 16, 2016

re: //// nah - if we have a better abstraction, use it. This isn't 1.0 yet, and no-one has to my knowledge wrote a production book with it yet

@dionlarson
Copy link
Copy Markdown
Collaborator Author

Great. I'll get started on documentation and tests then.

@ashfurrow
Copy link
Copy Markdown
Member

Really excited about this, since it seems like such a better way to write playground books. If there's anything I can do to help, please let me know 🙇

@dionlarson
Copy link
Copy Markdown
Collaborator Author

Sorry about the delays. I'm back on this starting tomorrow. I just returned from some personal travel.

@orta
Copy link
Copy Markdown
Collaborator

orta commented Oct 6, 2016

Never feel guilty for not contributing to OSS in your spare time 👍

@ashfurrow
Copy link
Copy Markdown
Member

ashfurrow commented Nov 9, 2016

Looks good to me, @dionlarson can you confirm this is good to merge?

@macteo
Copy link
Copy Markdown

macteo commented Nov 9, 2016

I took some time to test this implementation with a simple book I'm writing and it works really well, however, if I may suggest an improvement, it's the ability to copy folders (not only files) placed in the Resources folders. At the moment an exception is returned.

/Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1394:in `copy_stream': Is a directory - read (Errno::EISDIR)
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1394:in `block (2 levels) in copy_file'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1393:in `open'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1393:in `block in copy_file'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1392:in `open'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1392:in `copy_file'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:486:in `copy_file'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:403:in `block in cp'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1571:in `block in fu_each_src_dest'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1585:in `fu_each_src_dest0'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:1569:in `fu_each_src_dest'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/2.3.0/fileutils.rb:402:in `cp'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:79:in `block in copy_resources'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:78:in `each'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:78:in `copy_resources'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:41:in `block in collate'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:22:in `chdir'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/chapter_collator.rb:22:in `collate'
    from /Users/matteo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/playgroundbook-0.4.0/lib/renderer/playgroundbook_renderer.rb:93:in `block (4 levels) i

To solve the issue you can just replace the cp method with copy_entry at line 79 of chapter_collator.rb obtaining:

FileUtils.copy_entry("../../../../#{resource}", SharedResourcesDirectoryName)

@macteo
Copy link
Copy Markdown

macteo commented Nov 9, 2016

Just a quick note, in order to build the gem (but I'm not that expert) I had to rename the Code of Conduct.md file removing the spaces as the

s.files       = `git ls-files`.split($INPUT_RECORD_SEPARATOR)

in the .gemspec was messing with them.

@ashfurrow
Copy link
Copy Markdown
Member

Going to take a look at this PR this afternoon and merge if it looks good. Thanks again @dionlarson.

@ashfurrow ashfurrow merged commit 2d92cf3 into playgroundbooks:master Mar 15, 2017
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

Successfully merging this pull request may close these issues.

4 participants