From 5e74ae06f3aaaf72c61995b50d0edc0215e6df14 Mon Sep 17 00:00:00 2001 From: "leedongmyung[desktop]" Date: Sat, 28 Oct 2023 22:06:44 +0900 Subject: [PATCH] Inital push --- .gitignore | 56 ++++++ .vscode/launch.json | 29 +++ CHANGELOG.md | 3 + README.md | 2 + analysis_options.yaml | 30 +++ bin/oto_cli.dart | 15 ++ lib/cli/cli.dart | 261 +++++++++++++++++++++++++ lib/cli/commands/command_base.dart | 87 +++++++++ lib/cli/commands/command_install.dart | 55 ++++++ lib/cli/commands/command_manager.dart | 90 +++++++++ lib/cli/commands/command_start.dart | 35 ++++ lib/cli/commands/command_template.dart | 31 +++ lib/test.dart | 1 + pubspec.yaml | 29 +++ test/desktop_service_cli_test.dart | 5 + test/test.bat | 65 ++++++ 16 files changed, 794 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 CHANGELOG.md create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 bin/oto_cli.dart create mode 100644 lib/cli/cli.dart create mode 100644 lib/cli/commands/command_base.dart create mode 100644 lib/cli/commands/command_install.dart create mode 100644 lib/cli/commands/command_manager.dart create mode 100644 lib/cli/commands/command_start.dart create mode 100644 lib/cli/commands/command_template.dart create mode 100644 lib/test.dart create mode 100644 pubspec.yaml create mode 100644 test/desktop_service_cli_test.dart create mode 100644 test/test.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57b4ea3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# Created by https://www.toptal.com/developers/gitignore/api/dart,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=dart,visualstudiocode + +### Dart ### +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ +release/ + +# dotenv environment variables file +.env* + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + +### Dart Patch ### +# dotenv environment variables file +.env + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/dart,visualstudiocode \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3aeda50 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "oto_cli_linux", + "request": "launch", + "type": "dart", + "program": "./bin/oto_cli.dart", + "args": ["stop"] + }, + { + "name": "oto_cli_mac", + "request": "launch", + "type": "dart", + "program": "./bin/oto_cli.dart", + "args": ["install"] + }, + { + "name": "oto_cli_win", + "request": "launch", + "type": "dart", + "program": "./bin/oto_cli.dart", + "args": ["uninstall"] + } + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..effe43c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3816eca --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +A sample command-line application with an entrypoint in `bin/`, library code +in `lib/`, and example unit test in `test/`. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..dee8927 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/bin/oto_cli.dart b/bin/oto_cli.dart new file mode 100644 index 0000000..944f804 --- /dev/null +++ b/bin/oto_cli.dart @@ -0,0 +1,15 @@ +import 'package:oto_cli/cli/commands/command_install.dart'; +import 'package:oto_cli/cli/commands/command_start.dart'; + +import 'package:oto_cli/cli/cli.dart'; +import 'package:oto_cli/cli/commands/command_template.dart'; + +void main(List arguments) async { + CLI.initialize('desktop_service', arguments, [ + CommandTemplate(), + CommandInstall(), + CommandUninstall(), + CommandStart(), + CommandStop() + ]); +} diff --git a/lib/cli/cli.dart b/lib/cli/cli.dart new file mode 100644 index 0000000..e2f2d73 --- /dev/null +++ b/lib/cli/cli.dart @@ -0,0 +1,261 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:build_manager/application.dart'; +import 'package:dart_framework/utils/system_util.dart'; +import 'package:oto_cli/cli/commands/command_base.dart'; +import 'package:oto_cli/cli/commands/command_manager.dart'; +import 'package:path/path.dart' as path; + +enum Color { + black, + red, + green, + yellow, + blue, + magenta, + cyan, + lightGray, + darkGray, + lightRed, + lightGreen, + lightYellow, + lightBlue, + lightMagenta, + lightCyan, + white +} + +enum Style { bold, underline, dim, reverse } + +class CLIConfig { + String serviceName; + List arguments; + List commands; + late String executableFileName; + CLIConfig(this.serviceName, this.arguments, this.commands) { + var fileName = path.basename(Platform.resolvedExecutable); + fileName = fileName.replaceAll(path.extension(fileName), ''); + executableFileName = fileName; + } +} + +class CLI { + static final _colorCodeMap = { + Color.black: "30", + Color.red: "31", + Color.green: "32", + Color.yellow: "33", + Color.blue: "34", + Color.magenta: "35", + Color.cyan: "36", + Color.lightGray: "37", + Color.darkGray: "90", + Color.lightRed: "91", + Color.lightGreen: "92", + Color.lightYellow: "93", + Color.lightBlue: "94", + Color.lightMagenta: "95", + Color.lightCyan: "96", + Color.white: "97" + }; + + static final _backgroundCodeMap = { + Color.black: "40", + Color.red: "41", + Color.green: "42", + Color.yellow: "43", + Color.blue: "44", + Color.magenta: "45", + Color.cyan: "46", + Color.lightGray: "47", + Color.darkGray: "100", + Color.lightRed: "101", + Color.lightGreen: "102", + Color.lightYellow: "103", + Color.lightBlue: "104", + Color.lightMagenta: "105", + Color.lightCyan: "106", + Color.white: "107" + }; + + static final _styleCodeMap = { + Style.bold: "1", + Style.dim: "2", + Style.underline: "4", + Style.reverse: "7" + }; + + static Printer get printer { + if (Platform.isWindows) { + return Printer.windows(); + } else { + return Printer.unix(); + } + } + + CLI._privateConstructor(); + static final CLI _instance = CLI._privateConstructor(); + static CLI get current => _instance; + static void initialize( + String serviceName, List arguments, List commands) { + current.start(serviceName, arguments, commands); + } + + static String style(String message, + {Color? color, Color? background, Style? style}) { + return printer.getStyle(message, + color: color, background: background, style: style); + } + + static final commandNameSpace = 18; + static get serviceName => CLI.current.config.serviceName; + static get executableFileName => CLI.current.config.executableFileName; + + static Future print(List printList) async { + await printer.printCLI(printList); + return simpleFuture; + } + + late CLIConfig config; + late CommandManager _commandManager; + + void start(String serviceName, List arguments, + List commands) async { + config = CLIConfig(serviceName, arguments, commands); + _commandManager = CommandManager(config.commands); + + //find command + String? command; + var args = config.arguments.toList(); + if (arguments.isNotEmpty) { + for (var value in args) { + command = value; + break; + } + + args.removeAt(0); + } + await _commandManager.execute(command, args); + } +} + +//Printer Base +abstract class Printer { + Printer(); + factory Printer.windows() => _PrinterWindows(); + factory Printer.unix() => _PrinterUnix(); + + String getStyle(String message, + {Color? color, Color? background, Style? style}) { + var combine = ''; + if (color != null) { + combine = CLI._colorCodeMap[color]!; + } + if (background != null) { + combine = combineText(combine, CLI._backgroundCodeMap[background]!); + } + if (style != null) { + combine = combineText(combine, CLI._styleCodeMap[style]!); + } + return combine; + } + + String combineText(String combine, String item) { + if (combine == '') { + combine = item; + } else { + combine += ';$item'; + } + return combine; + } + + Future getTempFile(String content, String extension) async { + var c = Completer(); + var now = DateTime.now(); + var time = + '${now.hour}${now.minute}${now.second}${now.millisecond}${now.microsecond}'; + var tempFile = + File(path.join(Directory.current.path, 'temp_$time.$extension')); + await tempFile.writeAsString(content); + c.complete(tempFile); + return c.future; + } + + Future printCLI(List printList) async {} +} + +//Printer windows +class _PrinterWindows extends Printer { + @override + String getStyle(String message, + {Color? color, Color? background, Style? style}) { + var combine = super + .getStyle(message, color: color, background: background, style: style); + return '%ESC%[${combine}m$message%ESC%[0m'; + } + + @override + Future printCLI(List printList) async { + var c = Completer(); + StringBuffer message = StringBuffer(); + message.writeln('@echo off'); + message.writeln(''); + message.writeln('setlocal'); + message.writeln('call :setESC'); + + for (var item in printList) { + if (item.isEmpty) { + message.writeln('echo.'); + } else { + item = item + .replaceAll('<', '^<') + .replaceAll('>', '^>') + // .replaceAll('[', '^[') + .replaceAll(']', '^]') + .replaceAll('|', '^|'); + message.writeln('echo $item'); + } + } + message.writeln(':setESC'); + + var temp = await getTempFile(message.toString(), 'bat'); + await Process.run('cmd', ['/C', temp.path]).then((ProcessResult result) { + print(result.stdout); + }); + await temp.delete(); + c.complete(); + return c.future; + } +} + +//Printer mac/linux +class _PrinterUnix extends Printer { + @override + String getStyle(String message, + {Color? color, Color? background, Style? style}) { + var combine = super + .getStyle(message, color: color, background: background, style: style); + return '\\e[${combine}m$message\\e[0m'; + } + + @override + Future printCLI(List printList) async { + var c = Completer(); + StringBuffer message = StringBuffer(); + message.writeln("echo -e '"); + + for (var item in printList) { + message.writeln(item); + } + message.write("'"); + + var temp = await getTempFile(message.toString(), 'sh'); + await Process.run('zsh', [temp.path]).then((ProcessResult result) { + print(result.stdout); + }); + await temp.delete(); + c.complete(); + return c.future; + } +} diff --git a/lib/cli/commands/command_base.dart b/lib/cli/commands/command_base.dart new file mode 100644 index 0000000..f5f564b --- /dev/null +++ b/lib/cli/commands/command_base.dart @@ -0,0 +1,87 @@ +import 'dart:async'; + +import 'package:oto_cli/cli/cli.dart'; + +enum PrintType { error, warning, information } + +abstract class CommandBase { + Map> get arguments => {}; + String get name; + String get usage => ''; + + Future execute(List parameters); + + String getCommandDescription() { + return ' $name'.padRight(CLI.commandNameSpace) + getDescription(); + } + + String getDescription(); + + //==================== print ====================== + final messageTypeMap = { + PrintType.error: {"color": Color.red, "message": "Error:"}, + PrintType.warning: {"color": Color.yellow, "message": "Warning:"}, + PrintType.information: {"color": Color.green, "message": "Information:"} + }; + + void printOut(String message, PrintType type) { + var color = messageTypeMap[type]!["color"]! as Color; + var typeStr = messageTypeMap[type]!["message"]! as String; + message = '${CLI.style(typeStr, background: color)} $message'; + if (type == PrintType.error) { + printHelp(append: [message]); + } else { + CLI.print([message]); + } + } + + void printWarning(String message) { + printHelp(append: [ + '${CLI.style('Warning:', background: Color.yellow)} $message' + ]); + } + + void printInfo(String message) { + printHelp( + append: ['${CLI.style('Error:', background: Color.blue)} $message']); + } + + void printHelp({List? append}) { + var exeName = CLI.executableFileName; + final argumentTag = '{ARGUMENTS}'; + var list = [ + '', + getDescription(), + '', + 'Usage: ${CLI.style('$exeName $name $usage', color: Color.lightGreen)}', + argumentTag, + ]; + + var index = list.indexOf(argumentTag); + list.removeAt(index); + + if (arguments.isNotEmpty) { + List argsDescs = ['', 'Available arguments:']; + for (var item in arguments.entries) { + var addedArg = false; + for (var argDesc in item.value) { + if (!addedArg) { + argDesc = ' ${item.key}'.padRight(CLI.commandNameSpace) + argDesc; + addedArg = true; + } else { + argDesc = ' '.padRight(CLI.commandNameSpace) + argDesc; + } + argsDescs.add(argDesc); + } + } + argsDescs.add(''); + list.insertAll(index, argsDescs); + } + + if (append != null) { + list.insertAll(0, append); + list.insert(0, ''); + } + CLI.print(list); + } +} diff --git a/lib/cli/commands/command_install.dart b/lib/cli/commands/command_install.dart new file mode 100644 index 0000000..6367e16 --- /dev/null +++ b/lib/cli/commands/command_install.dart @@ -0,0 +1,55 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:dart_framework/utils/os_startup.dart'; +import 'package:oto_cli/cli/cli.dart'; +import 'package:oto_cli/cli/commands/command_base.dart'; + +class CommandInstall extends CommandBase { + @override + String get name => 'install'; + + @override + Future execute(List parameters) async { + var c = Completer(); + var label = CLI.serviceName; + if (!await OSStartup.isRegistedStartup(label)) { + await OSStartup.registStartup(Platform.resolvedExecutable, label, + arguments: ['start']); + printOut('Installed successfully.', PrintType.information); + } else { + printOut('Installation failed because it is already installed.', + PrintType.error); + } + return c.future; + } + + @override + String getDescription() { + var serviceName = CLI.current.config.serviceName; + return 'Install "$serviceName" to run in the background as a startup program.'; + } +} + +class CommandUninstall extends CommandBase { + @override + String get name => 'uninstall'; + + @override + Future execute(List parameters) async { + var c = Completer(); + var label = CLI.serviceName; + if (await OSStartup.isRegistedStartup(label)) { + await OSStartup.unregistStartup(label); + printOut('Uninstalled successfully.', PrintType.information); + } else { + printOut('It is already uninstalled.', PrintType.warning); + } + return c.future; + } + + @override + String getDescription() { + return 'Delete it from Startup.'; + } +} diff --git a/lib/cli/commands/command_manager.dart b/lib/cli/commands/command_manager.dart new file mode 100644 index 0000000..2b4aa0b --- /dev/null +++ b/lib/cli/commands/command_manager.dart @@ -0,0 +1,90 @@ +import 'dart:async'; + +import 'package:dart_framework/utils/system_util.dart'; + +import 'command_base.dart'; +import 'package:oto_cli/cli/cli.dart'; +import 'package:path/path.dart' as path; + +class CommandManager { + Map commandMap = {}; + CommandManager(List commands) { + for (var command in commands) { + commandMap[command.name] = command; + } + } + + Future execute(String? command, List parameters) async { + if (command == null) { + printHelp(); + } else { + if (commandMap.containsKey(command)) { + var argStr = ''; + for (var arg in parameters) { + argStr += '$arg, '; + } + var printHelp = false; + var commandItem = commandMap[command]!; + if (argStr.isNotEmpty) { + if (parameters[0].contains('-h')) { + commandItem.printHelp(); + printHelp = true; + } else { + argStr = argStr.replaceFirst(', ', '', argStr.length - 3); + argStr = ', Arguments: [$argStr]'; + } + } + + if (!printHelp) { + await CLI.print([ + CLI.style('Execute command: $command$argStr', color: Color.green) + ]); + await commandItem.execute(parameters); + } + } else { + printHelp(append: [ + '${CLI.style('Error:', background: Color.red)} The ${CLI.style('"$command"', color: Color.red, style: Style.bold)} command does not exist.' + ]); + } + } + return simpleFuture; + } + + void printHelp({List? append}) { + var serviceName = CLI.current.config.serviceName; + var exeName = CLI.executableFileName; + final commandTag = '{COMMAND}'; + var list = [ + '', + 'A command-line $serviceName.', + '', + 'Usage: ${CLI.style('$exeName <-h|[arguments]>', color: Color.lightGreen)}', + '', + 'Available Command:', + commandTag, + '', + 'Command options:', + ' -h Print help for the current command.', + '', + '', + "Run `$exeName -h` for more information about a command.", + ]; + + var index = list.indexOf(commandTag); + list.removeAt(index); + + if (commandMap.isNotEmpty) { + List commandDescs = []; + for (var item in commandMap.entries) { + commandDescs.add(item.value.getCommandDescription()); + } + list.insertAll(index, commandDescs); + } + + if (append != null) { + list.insertAll(0, append); + list.insert(0, ''); + } + CLI.print(list); + } +} diff --git a/lib/cli/commands/command_start.dart b/lib/cli/commands/command_start.dart new file mode 100644 index 0000000..53e3faa --- /dev/null +++ b/lib/cli/commands/command_start.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:oto_cli/cli/cli.dart'; +import 'package:oto_cli/cli/commands/command_base.dart'; +import 'package:dart_framework/utils/system_util.dart'; + +class CommandStart extends CommandBase { + @override + String get name => 'start'; + + @override + Future execute(List parameters) { + return simpleFuture; + } + + @override + String getDescription() { + return 'Run the program as a background service.'; + } +} + +class CommandStop extends CommandBase { + @override + String get name => 'stop'; + + @override + Future execute(List parameters) { + return simpleFuture; + } + + @override + String getDescription() { + return 'Exit the "${CLI.serviceName}" currently running in the background.'; + } +} diff --git a/lib/cli/commands/command_template.dart b/lib/cli/commands/command_template.dart new file mode 100644 index 0000000..0f46a6f --- /dev/null +++ b/lib/cli/commands/command_template.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +import 'package:dart_framework/utils/system_util.dart'; +import 'package:oto_cli/cli/cli.dart'; +import 'package:oto_cli/cli/commands/command_base.dart'; + +class CommandTemplate extends CommandBase { + @override + Map> get arguments => { + "--s": [ + "This is argument description template", + "This is second line." + ], + "--g": ["Second argument"] + }; + @override + String get name => 'template'; + @override + String get usage => '--arg0 --arg1'; + + @override + Future execute(List parameters) async { + return simpleFuture; + } + + @override + String getDescription() { + var serviceName = CLI.current.config.serviceName; + return 'This is template command description from $serviceName.'; + } +} diff --git a/lib/test.dart b/lib/test.dart new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/lib/test.dart @@ -0,0 +1 @@ + diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..9187cba --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,29 @@ +name: oto_cli +description: A sample command-line application. +version: 1.0.0 +# repository: https://github.com/my_org/my_repo + +environment: + sdk: '>=2.18.6 <4.0.0' + +# Add regular dependencies here. +dependencies: + # path: ^1.8.0 + json_annotation: ^4.8.0 + resource_importer: ^0.2.0 + dart_framework: + # path: '../dart_framework' + git: + url: toki@toki-labs.com:/Volumes/Data2/git/dart_framework.git + ref: master + build_manager: + # path: ../build_manager + git: + url: toki@toki-labs.com:/Volumes/Data2/git/build_manager.git + ref: master + +dev_dependencies: + lints: ^2.0.0 + test: ^1.21.0 + build_runner: ^2.1.4 + json_serializable: ^6.0.1 diff --git a/test/desktop_service_cli_test.dart b/test/desktop_service_cli_test.dart new file mode 100644 index 0000000..9384a7f --- /dev/null +++ b/test/desktop_service_cli_test.dart @@ -0,0 +1,5 @@ +import 'package:test/test.dart'; + +void main() { + test('calculate', () {}); +} diff --git a/test/test.bat b/test/test.bat new file mode 100644 index 0000000..167d282 --- /dev/null +++ b/test/test.bat @@ -0,0 +1,65 @@ +@echo off + +setlocal +call :setESC + +cls +echo %ESC%[101;93m STYLES %ESC%[0m +echo ^[0m %ESC%[0mReset%ESC%[0m +echo ^[1m %ESC%[1mBold%ESC%[0m +echo ^[4m %ESC%[4mUnderline%ESC%[0m +echo ^[7m %ESC%[7mInverse%ESC%[0m +echo. +echo %ESC%[101;93m NORMAL FOREGROUND COLORS %ESC%[0m +echo ^[30m %ESC%[30mBlack%ESC%[0m (black) +echo ^[31m %ESC%[31mRed%ESC%[0m +echo ^[32m %ESC%[32mGreen%ESC%[0m +echo ^[33m %ESC%[33mYellow%ESC%[0m +echo ^[34m %ESC%[34mBlue%ESC%[0m +echo ^[35m %ESC%[35mMagenta%ESC%[0m +echo ^[36m %ESC%[36mCyan%ESC%[0m +echo ^[37m %ESC%[37mWhite%ESC%[0m +echo. +echo %ESC%[101;93m NORMAL BACKGROUND COLORS %ESC%[0m +echo ^[40m %ESC%[40mBlack%ESC%[0m +echo ^[41m %ESC%[41mRed%ESC%[0m +echo ^[42m %ESC%[42mGreen%ESC%[0m +echo ^[43m %ESC%[43mYellow%ESC%[0m +echo ^[44m %ESC%[44mBlue%ESC%[0m +echo ^[45m %ESC%[45mMagenta%ESC%[0m +echo ^[46m %ESC%[46mCyan%ESC%[0m +echo ^[47m %ESC%[47mWhite%ESC%[0m (white) +echo. +echo %ESC%[101;93m STRONG FOREGROUND COLORS %ESC%[0m +echo ^[90m %ESC%[90mWhite%ESC%[0m +echo ^[91m %ESC%[91mRed%ESC%[0m +echo ^[92m %ESC%[92mGreen%ESC%[0m +echo ^[93m %ESC%[93mYellow%ESC%[0m +echo ^[94m %ESC%[94mBlue%ESC%[0m +echo ^[95m %ESC%[95mMagenta%ESC%[0m +echo ^[96m %ESC%[96mCyan%ESC%[0m +echo ^[97m %ESC%[97mWhite%ESC%[0m +echo. +echo %ESC%[101;93m STRONG BACKGROUND COLORS %ESC%[0m +echo ^[100m %ESC%[100mBlack%ESC%[0m +echo ^[101m %ESC%[101mRed%ESC%[0m +echo ^[102m %ESC%[102mGreen%ESC%[0m +echo ^[103m %ESC%[103mYellow%ESC%[0m +echo ^[104m %ESC%[104mBlue%ESC%[0m +echo ^[105m %ESC%[105mMagenta%ESC%[0m +echo ^[106m %ESC%[106mCyan%ESC%[0m +echo ^[107m %ESC%[107mWhite%ESC%[0m +echo. +echo %ESC%[101;93m COMBINATIONS %ESC%[0m +echo ^[31m %ESC%[31mred foreground color%ESC%[0m +echo ^[7m %ESC%[7minverse foreground ^<-^> background%ESC%[0m +echo ^[7;31m %ESC%[7;31minverse red foreground color%ESC%[0m +echo ^[7m and nested ^[31m %ESC%[7mbefore %ESC%[31mnested%ESC%[0m +echo ^[31m and nested ^[7m %ESC%[31mbefore %ESC%[7mnested%ESC%[0m + +:setESC +for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do ( + set ESC=%%b + exit /B 0 +) +exit /B 0 \ No newline at end of file