https://github.com/fzyzcjy/dart_interactive Skip to content Navigation Menu Toggle navigation Sign in * Product + Actions Automate any workflow + Packages Host and manage packages + Security Find and fix vulnerabilities + Codespaces Instant dev environments + GitHub Copilot Write better code with AI + Code review Manage code changes + Issues Plan and track work + Discussions Collaborate outside of code Explore + All features + Documentation + GitHub Skills + Blog * Solutions By size + Enterprise + Teams + Startups By industry + Healthcare + Financial services + Manufacturing By use case + CI/CD & Automation + DevOps + DevSecOps * Resources Topics + AI + DevOps + Security + Software Development + View all Explore + Learning Pathways + White papers, Ebooks, Webinars + Customer Stories + Partners * Open Source + GitHub Sponsors Fund open source developers + The ReadME Project GitHub community articles Repositories + Topics + Trending + Collections * Enterprise + Enterprise platform AI-powered developer platform Available add-ons + Advanced Security Enterprise-grade security features + GitHub Copilot Enterprise-grade AI features + Premium Support Enterprise-grade 24/7 support * Pricing Search or jump to... Search code, repositories, users, issues, pull requests... Search [ ] Clear Search syntax tips Provide feedback We read every piece of feedback, and take your input very seriously. [ ] [ ] Include my email address so I can be contacted Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly Name [ ] Query [ ] To see all available qualifiers, see our documentation. Cancel Create saved search Sign in Sign up Reseting focus You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert {{ message }} fzyzcjy / dart_interactive Public * Notifications You must be signed in to change notification settings * Fork 12 * Star 169 REPL (interactive shell) for Dart, supporting 3rd party packages, hot reload, and full grammar github.com/fzyzcjy/dart_interactive License MIT license 169 stars 12 forks Branches Tags Activity Star Notifications You must be signed in to change notification settings * Code * Issues 2 * Pull requests 0 * Actions * Projects 1 * Security * Insights Additional navigation options * Code * Issues * Pull requests * Actions * Projects * Security * Insights fzyzcjy/dart_interactive This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. master BranchesTags Go to file Code Folders and files Name Name Last commit Last commit message date Latest commit History 251 Commits .github .github doc doc example example packages/ packages/ interactive interactive .all-contributorsrc .all-contributorsrc .gitignore .gitignore CHANGELOG.md CHANGELOG.md LICENSE LICENSE README.md README.md justfile justfile View all files Repository files navigation * README * MIT license dart_interactive Flutter Package CI [logo] A lot of sibling languages have a REPL, and is quite helpful in everyday usage, while Dart did not have it (even though it was the 7th highest-voted request). So here it comes! Features A full-featured REPL (interactive shell), with: * Use any third-party package freely * Auto hot-reload code anywhere, with state preserved * Supports full grammar in REPL * Play with existing code side-by-side Demo Demo 1: Demonstrate features 1. Use 3rd party package >>> !dart pub add path // normal shell command >>> import 'package:path/path.dart'; // normal import >>> join('directory', 'file.txt') // use it (`join` is a function in 3rd party package `path`) directory/file.txt 2. Auto hot-reload >>> import 'a.dart'; >>> myFunc() hello, tom // ... change content of `a.dart` ... >>> myFunc() hello, alex 3. Support full grammar >>> a = 10; // support rich grammar >>> int g() => a++; class A {} class B {} ... class C extends A implements B { ... int b = 20; ... int f() { int c = 30; a++; b++; c++; return a+b+c+g(); } ... } >>> c = C() >>> c.f() 74 // support redefine class/method/... >>> class C extends A implements B { int b = 20; int f() => b; } >>> c.f() 21 Demo 2: Sample workflow Surely, you do not have to use it like this. It is just a workflow that I personally feel comfortable when working with IPython/Juypter. Suppose we have my_app.dart with some code, probably edited inside an IDE: class Counter { int count = 0; String greet() => 'Hi Tom, you have count $count!'; } Play with it a bit: $ interactive --directory path/to/my/package >>> import 'my_app.dart'; >>> counter = Counter(); >>> counter.count = 10; >>> counter.greet() Hi Tom, you have count 10! >>> counter.count = 20; >>> counter.greet() Hi Tom, you have count 20! Then we realize something wrong and want to change it: (change "Tom" to "Alex" inside `my_app.dart`) Continue playing with it (auto hot reloaded, and state preserved): >>> counter.greet() Hi Alex, you have count 20! We can also use all dependencies in the package as well, since the REPL code is just like a normal code file in this package. >>> import 'package:whatever_package'; >>> functionInWhateverPackage(); Getting started Install (just standard procedure of installing global dart packages): dart pub global activate interactive Use (just a normal binary): interactive And play with it :) Detailed functionality list Expressions >>> a = 'Hello'; b = ' world!'; >>> '$a, $b' Hello, world! Statements >>> print(a) Hello (All methods, not only print) Functions Define and redefine >>> String f() => 'old'; >>> f() old >>> String f() => 'new'; >>> f() new Use local and global variables >>> a = 10; >>> int f() { int b = 20; a++; b++; return a+b; } >>> f() 32 >>> f() 33 Classes Define and redefine, preserving states >>> class C { int a = 10; int f() => a * 2; } >>> c = C(); print(c.f()); 20 >>> class C { int a = 1000; int f() => a * 3; } >>> c.f() 30 Remark: This follows the Dart hot reload semantics. Extends and implements >>> class A { int f() => 10; } class B extends A { int f() => 20; } >>> A().f() + B().f() 30 >>> class B implements A { int f() => 30; } >>> A().f() + B().f() 40 Use local variables, fields, and global variables >>> a = 10; >>> class C { int b = 20; int f() { int c = 30; a++; b++; c++; return a+b+c; } } >>> c = C(); print(c.f()); print(c.f()); 63 65 Add libraries as dependency Use !dart pub add package_name, just like what is done in Python (Jupyter/IPython). >>> join('directory', 'file.txt') (...error, since have not added that dependency...) >>> !dart pub add path Resolving dependencies... + path 1.8.2 Changed 1 dependency! >>> join('directory', 'file.txt') (...error, since have imported it...) >>> import 'package:path/path.dart'; >>> join('directory', 'file.txt') directory/file.txt Imports Built-in package >>> Random().nextInt(100) (some error outputs here, because it is not imported) >>> import "dart:math"; >>> Random().nextInt(100) 9 Third party package Note: If it has not been added to dependency, please follow instructions above and use !dart pub add path to add it. >>> join('directory', 'file.txt') (...error, since have imported it...) >>> import 'package:path/path.dart'; >>> join('directory', 'file.txt') directory/file.txt Multiple in one go >>> int g() => 42; class C { int a = 10; int f() => a * 2; } >>> C().f() + g() 62 Multi line if not ended (The ..., instead of >>>, appears in the two lines, because the package detects it is not finished.) >>> class C { ... int a = 10; ... } >>> Run commands Use prefix !. >>> !whoami tom >>> !date 2022-10-22 ...outputs... Execute within environment of existing package interactive --directory path/to/your/package Implementation General: * Create a blank package and an isolate as execution workspace * Extract imports/classes/functions/etc using analyzer, with replacing when it has the same name, and synthesize a dart file - thus supports rich Dart feature * Trigger Dart's hot-reload after the dart file is updated * Use analyzer to distinguish expressions/statements/ compilation-units and do corresponding transformation * The only thing to let Dart VM service to evaluate is generatedMethod(), and do not evaluate anything more * Adding dependencies is as simple as running standard shell command As for "global" variables: * Indeed implemented by a field variable * Statements: Make it inside extension on dynamic { Object? generatedMethod() { ...the statements... } } to access it seamlessly * Functions: Convert functions to extension methods on dynamic to access it seamlessly * Classes: Synthesize getters/setters in classes, and delegate to the field variables, whenever there is a potential access to global variable to access it seamlessly TODO more implementation discussions if people are interested (above is so brief) Known Issues Windows non-WSL terminal Because of Dart's bug (dart-lang/sdk#48329), the upstream cli_repl package does not work well on Windows. The issues vary from terminal to terminal, but generally speaking, backspace doesn't work, we cannot move on the command line with arrows nor Ctrl+B/F, and no command history with arrows or ^P/^N either. Since dart_interactive depends on it, it is suggested to use WSL or *nix. Command history Command history is not yet saved between sessions. However, this is implementable, and feel free to create an issue or PR. Some errors will lead to Hot reload failed Currently, some user mistakes will produce Hot reload failed error instead of the actual error. It will break the next command or the whole REPL. If you can't evaluate something simple as "1" after two tries, you can restart quickly with Ctrl/Cmd+D, Up Arrow and Enter in most terminals. Example >>> 1 1 >>> print() // <----- oops, argument is not optional [WARNING 2024-03-13 01:50:18.419137] Error: Hot reload failed, maybe because code has syntax error? >>> 1 [WARNING 2024-03-13 01:50:20.464239] Error: Hot reload failed, maybe because code has syntax error? >>> 1 [WARNING 2024-03-13 01:50:20.464239] Error: Hot reload failed, maybe because code has syntax error? Contributors All Contributors Thanks goes to these wonderful people (emoji key): fzyzcjy Vyacheslav Andreas Maksim Keithcat1 Sebastian arcanemachine [fzyzcjy Egorov Kirsch Lin [ Thomschke [ ] [Vyacheslav [Andreas [Maksim Keithcat1 [ arcanemachine Egorov] Kirsch] Lin] ] Sebastian ] Thomschke ] David Chematronix Martos [ [David Chematronix Martos] ] More specifically, thanks for all these contributions: * @mraleph (Dart team): Pointing out Dart exposes hot reload and expression evaluation. * @BlackHC: Prior proof of concept and article on the problem of creating a REPL. * @maks: Prior prototype as an update-to-Dart-2 of @BlackHC's prototype. * @davidmartos96: Fix package import bug. Fix windows hot reload bug. Update analyze. * @Keithcat1: Partially fix printing object. * @sebthom: Use unused TCP port. * @arcanemachine: Pin dependency. About REPL (interactive shell) for Dart, supporting 3rd party packages, hot reload, and full grammar github.com/fzyzcjy/dart_interactive Topics shell dart interactive repl flutter Resources Readme License MIT license Activity Stars 169 stars Watchers 6 watching Forks 12 forks Report repository Releases 7 v1.4.0 Latest Jun 29, 2024 + 6 releases Packages 0 No packages published Contributors 8 * * * * * * * * Languages * Dart 97.2% * Just 2.8% Footer (c) 2024 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact * Manage cookies * Do not share my personal information You can't perform that action at this time.