diff --git a/bake b/bake index b739e568..1d2dc707 100755 --- a/bake +++ b/bake @@ -182,8 +182,8 @@ flutter_web.install() { _run flutter_web flutter pub get ; } flutter_web.clean() { _run flutter_web flutter clean; rm -rf build; } flutter_web.upgrade() { _run flutter_web flutter pub upgrade ; } -flutter_web.gen() { #_run root dart run packages/you_cli/bin/you_cli2.dart gen all --dir notes/flutter_web/; - _run root dart run packages/you_cli/bin/you_cli2.dart gen routes.g.dart --dir notes/flutter_web/ # --async +flutter_web.gen() { #_run root dart run packages/you_cli/bin/cli.dart gen all --dir notes/flutter_web/; + _run root dart run packages/you_cli/bin/cli.dart gen routes.g.dart --dir notes/flutter_web/ # --async } flutter_web.dev() { flutter_web.dev_html ; } flutter_web.build() { flutter_web.build_html ;} diff --git a/packages/you_cli/bin/you_cli2.dart b/packages/you_cli/bin/cli.dart similarity index 100% rename from packages/you_cli/bin/you_cli2.dart rename to packages/you_cli/bin/cli.dart diff --git a/packages/you_cli/bin/you_cli.dart b/packages/you_cli/bin/you_cli.dart deleted file mode 100644 index ded7f4b1..00000000 --- a/packages/you_cli/bin/you_cli.dart +++ /dev/null @@ -1,418 +0,0 @@ -import 'package:analyzer/dart/analysis/features.dart'; -import 'package:analyzer/dart/ast/ast.dart'; -import 'package:args/command_runner.dart'; -import 'package:code_builder/code_builder.dart' as code; -import 'package:code_builder/code_builder.dart'; -import 'package:collection/collection.dart'; - -import 'package:dart_style/dart_style.dart'; -import 'package:file/file.dart'; -import 'package:file/local.dart'; -import 'package:glob/glob.dart'; -import 'package:you_note_dart/note_conf.dart'; -import 'package:path/path.dart' as path; - -import 'package:analyzer/dart/analysis/utilities.dart' as analyzer_util; -import 'package:watcher/watcher.dart'; -import 'dart:io' as io; -import 'package:you_cli/src/yaml.dart'; - -const String _libRoot = "lib"; -const String _notesRoot = "lib/pages/notes"; -const String _packageName = "flutter_web"; - -final Glob _noteGlob = Glob("{**/page.dart,page.dart}"); - -main(List args) async { - _log("Platform.script : ${io.Platform.script}"); - _log("Directory.current: ${io.Directory.current}"); - FileSystem fs = const LocalFileSystem(); - - var runner = CommandRunner("note", "A flutter note tools."); - runner.addCommand( - Cmd_gen(fs: fs) - ..addSubcommand(Cmd_gen_all(fs: fs)) - ..addSubcommand(Cmd_gen_notes_g_dart(fs: fs)), - ); - - await runner.run(args); -} - -// ignore: camel_case_types -class Cmd_gen_all extends Command { - // The [name] and [description] properties must be defined by every - // subclass. - Cmd_gen_all({required this.fs}) { - argParser.addOption("dir", mandatory: true, help: "要生成的flutter note项目根目录"); - } - - final FileSystem fs; - @override - final name = "all"; - @override - final description = "gen all ."; - - // [run] may also return a Future. - @override - Future run() async { - String dirOpt = argResults?["dir"]!; - var dir = fs.directory(path.absolute(dirOpt)); - if (!dir.existsSync()) { - throw AssertionError("【--dir $dir】 not exists"); - } - - _log("gen: $dir"); - NotesGenerator gen = NotesGenerator(packageName: _packageName, fmt: DartFormatter(pageWidth: 500), fs: fs, projectDir: dir); - var pageDataList = await gen._noteLibs.map((e) => e.collectPageData()).asyncExpand((e) => e.asStream()).toList(); - - await gen._gen_pubspec_yaml(pageDataList); - await gen._gen_pages_g_json(pageDataList); - // TODO 应考虑note.json和note.g.json合并 - // await gen._genNoteGJson(pageDataList); - await gen._gen_notes_g_dart(pageDataList.map((e) => e.noteLib).toList()); - } -} - -// ignore: camel_case_types -class Cmd_gen extends Command { - Cmd_gen({required this.fs}); - - final FileSystem fs; - @override - final name = "gen"; - @override - final description = "gen management ."; - - // [run] may also return a Future. - @override - Future run() async {} -} - -// ignore: camel_case_types -class Cmd_gen_notes_g_dart extends Command { - Cmd_gen_notes_g_dart({required this.fs}) : libMode = false; - - Cmd_gen_notes_g_dart.libMode({ - required this.fs, - required this.projectDir, - required this.noteLibs, - }) : libMode = true; - - bool libMode; - late Directory projectDir; - late List noteLibs; - - @override - final name = "gen.notes.g.dart"; - @override - final description = "gen.notes.g.dart ."; - final FileSystem fs; - - // [run] may also return a Future. - @override - Future run() async { - if (libMode) { - String dirOpt = argResults?["dir"]!; - projectDir = fs.directory(path.absolute(dirOpt)); - if (!projectDir.existsSync()) { - throw AssertionError("【--dir $projectDir】 not exists"); - } - } - - var fmt = DartFormatter(); - var nameMaxLen = noteLibs.map((e) => e.flatName.length).reduce((value, element) => value > element ? value : element); - var fields = noteLibs.map((noteLib) { - var noteVarNameWithPadding = noteLib.flatName.padRight(nameMaxLen); - // final NoteRoute dev_devtool = put("/dev/devtool", (context,print) async => await dev_devtool_.loadLibrary().then((value) => dev_devtool_.build(context,print))); - return """ final $noteVarNameWithPadding = put("${noteLib.noteKey}", (context,print) async => await ${noteLib.flatName}_.loadLibrary().then((value) => ${noteLib.flatName}_.build(context,print))); """; - }).join("\n"); - Library importCode = Library((b) => b - ..comments.addAll(["Generated by github.com/chen56/you, please don't edit! ", "ignore_for_file: library_prefixes, non_constant_identifier_names"]) - ..directives.addAll( - noteLibs.map((lib) { - return code.Directive.importDeferredAs(lib.package, "${lib.flatName}_"); - }), - )); - - String importCodeFmt = '${importCode.accept(DartEmitter(allocator: Allocator.none, orderDirectives: true, useNullSafetySyntax: true))}'; - importCodeFmt = fmt.format(importCodeFmt); - String allCode = """ -import 'package:you_note_dart/note.dart'; - -$importCodeFmt - -abstract class BaseNotes { - static final NoteRoute rootroot = NoteRoute.root(); - static NoteRoute put(String path, LazyNoteBuilder lazyNoteBuilder) { - return rootroot.put(path, lazyNoteBuilder); - } -$fields -} -"""; - - await projectDir.childFile("lib/pages.g.dart").writeAsString(allCode); - // 暂时不格式化,因为要保持变量名后的padding,对齐变量更好看 - // file.writeAsString(_fmt.format(toCode)); - } -} - -class NotesGenerator { - final DartFormatter _fmt; - final FileSystem fs; - final String packageName; - final Directory projectDir; - late final Directory libDir; - late final Directory noteRootDir; - - NotesGenerator({ - required this.packageName, - required this.fs, - required this.projectDir, - DartFormatter? fmt, - }) : _fmt = fmt ?? DartFormatter() { - libDir = projectDir.childDirectory(_libRoot); - noteRootDir = projectDir.childDirectory(_notesRoot); - } - - Stream watch() async* { - var watcher = DirectoryWatcher(noteRootDir.path); - await for (WatchEvent e in watcher.events) { - if (!_noteGlob.matches(e.path)) { - yield e; - continue; - } - var file = fs.file(e.path); - var pubspec = _loadPubspec(); - NoteLib noteLib = newNoteLib2(file); - - switch (e.type) { - case ChangeType.ADD || ChangeType.MODIFY: - await noteLib.collectPageData(); - pubspec.addAsset(noteLib.asset); - case ChangeType.REMOVE: - var noteAsset = path.relative(file.parent.path, from: projectDir.path); - pubspec.removeAsset(noteAsset); - default: - throw Exception("unknown ChangeType ${e.type}"); - } - - // await _genSpaceJson(_noteLibs); - await _gen_notes_g_dart(await _noteLibs.toList()); - await pubspec.save(); - yield e; - } - } - - // ignore: non_constant_identifier_names - Future<({File file, List notes})> _gen_notes_g_dart(List noteLibs) async { - var nameMaxLen = noteLibs.map((e) => e.flatName.length).reduce((value, element) => value > element ? value : element); - var fields = noteLibs.map((noteLib) { - var noteVarNameWithPadding = noteLib.flatName.padRight(nameMaxLen); - // final NoteRoute dev_devtool = put("/dev/devtool", (context,print) async => await dev_devtool_.loadLibrary().then((value) => dev_devtool_.build(context,print))); - return """ final $noteVarNameWithPadding = put("${noteLib.noteKey}", (context,print) async => await ${noteLib.flatName}_.loadLibrary().then((value) => ${noteLib.flatName}_.build(context,print))); """; - }).join("\n"); - Library importCode = Library((b) => b - ..comments.addAll(["Generated by github.com/chen56/you, please don't edit! ", "ignore_for_file: library_prefixes, non_constant_identifier_names"]) - ..directives.addAll( - noteLibs.map((lib) { - return code.Directive.importDeferredAs(lib.package, "${lib.flatName}_"); - }), - )); - - String importCodeFmt = '${importCode.accept(DartEmitter(allocator: Allocator.none, orderDirectives: true, useNullSafetySyntax: true))}'; - importCodeFmt = _fmt.format(importCodeFmt); - String allCode = """ -import 'package:you_note_dart/note.dart'; - -$importCodeFmt - -abstract class BaseNotes { - static final NoteRoute rootroot = NoteRoute.root(); - static NoteRoute put(String path, LazyNoteBuilder lazyNoteBuilder) { - return rootroot.put(path, lazyNoteBuilder); - } -$fields -} -"""; - - File file = await projectDir.childFile("lib/pages.g.dart").writeAsString(allCode); - // 暂时不格式化,因为要保持变量名后的padding,对齐变量更好看 - // file.writeAsString(_fmt.format(toCode)); - - return (file: file, notes: noteLibs); - } - - File get _noteSpaceJsonFile => projectDir.childFile("lib/pages.g.json"); - - // ignore: unused_element,non_constant_identifier_names - Future _gen_note_g_json(List notes) async { - int maxNoteId = 1; - for (var note in notes) { - NoteGJson? noteGenConf = note.noteGJson; - if (noteGenConf != null && noteGenConf.noteId > maxNoteId) { - maxNoteId = noteGenConf.noteId; - } - } - - int nextNoteId = maxNoteId + 1; - for (var note in notes) { - _log("${note.noteGJson == null ? "🟢create" : "⚪️update"} page.g.json: ${note.noteGJsonFile} "); - NoteGJson noteGJson = note.noteGJson ?? NoteGJson(noteId: nextNoteId++); - // 每次覆盖 - await noteGJson.save(note.noteGJsonFile); - } - } - - // ignore: non_constant_identifier_names - Future _gen_pages_g_json(List notes) async { - SpaceConf spaceConf = await SpaceConf.load(_noteSpaceJsonFile); - spaceConf.notes.clear(); - for (var note in notes) { - if (note.noteConf != null) { - spaceConf.notes[note.noteLib.noteKey] = note.noteConf!; - } - } - _log("_genSpaceJson: $_noteSpaceJsonFile "); - _log("_genSpaceJson: ${spaceConf.toString()} "); - - return await spaceConf.save(_noteSpaceJsonFile); - } - - Stream get _noteLibs { - return _noteGlob.listFileSystem(fs, root: noteRootDir.path).where((e) => e is File).map((e) => newNoteLib2(e as File)); - } - - // ignore: non_constant_identifier_names - Future _gen_pubspec_yaml(List pageDataList) async { - var pubspec = _loadPubspec(); - var toUpdate = pageDataList.map((e) => e.noteLib.asset).sorted((a, b) => a.compareTo(b)); - pubspec.updateAssets(toUpdatePath: "lib/pages/notes/", toUpdate: toUpdate); - for (var e in toUpdate) { - _log("gen pubspec.yaml pubspec.assets toUpdate: $e"); - } - _log("gen pubspec.yaml new file: ${pubspec.toString()}"); - await pubspec.save(); - } - - PubspecEdit _loadPubspec() { - return PubspecEdit.parseFileSync(projectDir.childFile("pubspec.yaml")); - } - - NoteLib newNoteLib2(File noteFile) { - return NoteLib( - file: noteFile, - packageBaseName: packageName, - projectDir: projectDir, - ); - } -} - -class NoteLib { - final FileSystem fs; - final Directory noteRootDir; - final Directory libDir; - final String packageBaseName; - final File file; - final Directory projectDir; - - NoteLib({ - required this.file, - required this.packageBaseName, - required this.projectDir, - }) : fs = file.fileSystem, - libDir = projectDir.childDirectory(_libRoot), - noteRootDir = projectDir.childDirectory(_notesRoot); - - String get noteKey { - String result = path.dirname(path.relative(file.path, from: noteRootDir.path)); - return result == "." ? "/" : path.join("/", result); - } - - String get basename => path.basename(noteKey); - - // String get noteName => path.basenameWithoutExtension(file.path); - String get package => "package:$packageBaseName/${path.relative(file.path, from: libDir.path)}"; - - String get asset => "${path.relative(file.parent.path, from: projectDir.path)}/"; - - /// note name平整化,可作为变量名: - /// lib/pages/1.a/b/page.dart ---> a_b - String get flatName { - String dir = noteKey; - if (dir == "/") { - return "root"; - } - var names = dir.split(path.separator).where((e) => e.isNotEmpty); - return names - .map((e) => e - // ignore: unnecessary_string_escapes - .replaceAll(RegExp("^\\d+\."), "") // 1.z.about -> note_note-self - .replaceAll(".", "_") - .replaceAll("-", "_") - .replaceAll("&", "_") - .replaceAll("*", "_") - .replaceAll("*", "_") - .replaceAll("@", "_")) - .join("_"); - } - - File get noteConfFile => fs.file(file.parent.childFile("page.json")); - - File get noteGenConfFile => fs.file(file.parent.childFile("page.g.json")); - - String packageOf(String dartFileName) { - String noteLibDir = path.dirname(path.relative(file.path, from: libDir.path)); - return "package:$packageBaseName/$noteLibDir/$dartFileName"; - } - - Future collectPageData() async { - String? noteConf = !await noteConfFile.exists() ? null : await noteConfFile.readAsString(); - String? noteGenConf = !await noteGenConfFile.exists() ? null : await noteGenConfFile.readAsString(); - var result = PageData.parse( - noteLib: this, - content: await file.readAsString(), - noteGJsonFile: noteGenConfFile, - noteConf: noteConf == null ? null : NoteConf.decode(noteConf), - noteGJson: noteGenConf == null ? null : NoteGJson.decode(noteGenConf), - fmt: DartFormatter(), - ); - return result; - // _log("gen note.g.dart:$noteConfFile"); - // return result._gen(result._collectInfo()); - } -} - -class PageData { - final NoteLib noteLib; - final DartFormatter fmt; - final NoteConf? noteConf; - final NoteGJson? noteGJson; - final File noteGJsonFile; - late final CompilationUnit unit; - late final String content; - - PageData.parse({ - required this.noteLib, - required this.fmt, - this.noteConf, - this.noteGJson, - required this.noteGJsonFile, - required String content, - }) { - var parseResult = analyzer_util.parseString(content: content, featureSet: FeatureSet.latestLanguageVersion()); - unit = parseResult.unit; - this.content = parseResult.content; - } - - get file => noteLib.file; - - @override - String toString() { - return "$file"; - } -} - -_log(Object? o) { - // ignore: avoid_print - print("${DateTime.now()} - $o"); -}