dart-lang / dart-pad

An online Dart editor with support for console, web, and Flutter apps
https://dartpad.dev
BSD 3-Clause "New" or "Revised" License
1.71k stars 555 forks source link

Provide a way to hide boilerplate code #562

Closed Sfshaza closed 5 months ago

Sfshaza commented 9 years ago

Kathy will be updating the language tour with lots and lots of embedded DartPad instances of the embed-inline variety. Currently, she has a repo that contains all of the complete code examples (so that we can build and verify them) but she is only displaying a snippet in the page itself.

Here is an example. Here is the code for factory_constructor.dart:

// BEGIN(factory_constructor)
class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to the _ in front
  // of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = new Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) {
      print(msg);
    }
  }
}
// END(factory_constructor)

main() {
  //BEGIN
  var logger = new Logger('UI');
  logger.log('Button clicked');
  //END

  var l1 = new Logger('log1');
  var l1_2 = new Logger('log1');
  var l2 = new Logger('log2');

  assert(identical(l1, l1_2));
  assert(l1 != l2);

  l1.log('${l1.name}: This is l1.');
  l1_2.log('${l1_2.name}: This is l1_2.');
  l2.log('${l2.name}: This is l2.');
}

In the page on dartlang.org, you see only a snippet of the code:

The following example demonstrates a factory constructor returning objects from a cache:

class Logger {
  final String name;
  bool mute = false;

  // _cache is library-private, thanks to the _ in front
  // of its name.
  static final Map<String, Logger> _cache =
      <String, Logger>{};

  factory Logger(String name) {
    if (_cache.containsKey(name)) {
      return _cache[name];
    } else {
      final logger = new Logger._internal(name);
      _cache[name] = logger;
      return logger;
    }
  }

  Logger._internal(this.name);

  void log(String msg) {
    if (!mute) {
      print(msg);
    }
  }
}

It would be nice if there was a way to identify (and hide) the boilerplate code in the embed-inline version. The example would still run, but only the relevant code is exposed.

language tour: https://www.dartlang.org/docs/dart-up-and-running/ch02.html book code repo: https://github.com/dart-lang/dart-up-and-running-book/tree/master/code/ch02

kwalrath commented 9 years ago

Thanks for filing this, @Sfshaza! I couldn't have said it better.

devoncarew commented 9 years ago

Thanks for the detailed write-up; I have a few questions to help me figure out your requirements a bit more:

Would you expect the summarized versions to be editable? In this particular example, not having the main() be part of the summarization means that there's some guesswork on the part of the user about what will happen when they hit run. Would you expect the user to be able to manually toggle the embedded pad from the summarized state to the full one? Would you expect some visualization of this summarized state? If editable, would you expect that trying to edit the pad toggles into the non-summarized state automatically? You essentially want some ifdefs in the code to hide or show sections (// #hide, // #show)? Or you want to reference one pad many different times, and be able to only show a named section (embed_full.html?id=GH876H3&section=factory_constructor)?

kwalrath commented 9 years ago

Would you expect the summarized versions to be editable?

Not necessarily. I can imagine having a button that takes you to a DartPad window with the full app.

In this particular example, not having the main() be part of the summarization means that there's some guesswork on the part of the user about what will happen when they hit run.

Maybe these aren't even runnable until you go to the DartPad window with the full app.

Would you expect the user to be able to manually toggle the embedded pad from the summarized state to the full one?

Yes, although not necessarily inside the page. (See above.)

Would you expect some visualization of this summarized state?

Yes, somehow.

If editable, would you expect that trying to edit the pad toggles into the non-summarized state automatically?

I think so.

You essentially want some ifdefs in the code to hide or show sections (// #hide, // #show)? Or you want to reference one pad many different times, and be able to only show a named section (embed_full.html?id=GH876H3&section=factory_constructor)?

We already tried something like this once with the contents of the language tour and library tour, so you can see something that worked (assuming I saved the branch correctly): https://github.com/dart-lang/dart-up-and-running-book/tree/old has all the source files (XML and Dart) for the 10/2012 version of the book. It also has instructions for using a merge tool called doc-code-merge. The doc-code-merge repo has gone away, but you can read a post about it at http://news.dartlang.org/2012/12/darts-approach-to-illiterate.html.

Unfortunately we never adopted doc-code-merge, mainly because O'Reilly reworked all our files and we lost the inclusion information; we opted to use their edited source rather than applying all their edits to our original source. O'Reilly's production process is not an issue any more. Another reason we opted to use O'Reilly's was that we found it painful to write about code we couldn't see; we probably don't have much choice about that, though.

As an example of the markup we used, in https://github.com/dart-lang/dart-up-and-running-book/blob/old/xml/ch02.xml you can see <programlisting>(MERGE(basic_dart_program))</programlisting>, which refers to the file https://github.com/dart-lang/dart-up-and-running-book/blob/old/code/ch02/basic_dart_program.dart. You can still see the BEGIN and END markup in many of the samples under the latest code repo: https://github.com/dart-lang/dart-up-and-running-book/tree/master/code. (The Dart files are still in that repo; when we stopped publishing the book, the home of the book's non-code files moved to https://github.com/dart-lang/www.dartlang.org/.)

We had only a few cases where the same file would be used multiple times, so a way to optionally label sections would be good but not crucial; we could probably just duplicate the files. However, there were multiple cases (I believe) where a single snippet in the book would have multiple, discontiguous sections of a single Dart file.

Sfshaza commented 9 years ago

I met with George and Devon to discuss this while K was on vacation. George had an interesting idea. He suggested that maybe they could add an "invisible" (to the user) CSS/HTML file that specifies what to expose and what to hide. If the user enters edit mode, all of the code would be visible. So, for "embed inline", at least, there would be "obscure boilerplate" mode or "edit mode". A great idea!

parlough commented 5 months ago

As DartPad and the Dart documentation sites have evolved a lot since this issue, I'm going to close this issue. I think the best route forward for these scenarios will be https://github.com/dart-lang/dart-pad/issues/2702 which could potentially include support for this. Thanks all!