diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3ac727e..94fd1f4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,8 @@ jobs: - name: Fetch Dependencies run: dart pub get . - name: Make Build Directories - run: "mkdir -p build/releases/${{ matrix.platform }}" + run: "mkdir -p build/releases/${{ matrix.platform }} && + mkdir ./scripts/installers/${{ matrix.platform }}/lib" - name: Build Executable run: dart compile exe --define=DEBUG=false ./lib/main.dart --target-os ${{ matrix.platform }} -o build/releases/${{ matrix.platform }}/${{ matrix.output}} - name: Build Squirrel diff --git a/lib/cli.dart b/lib/cli.dart index 4a44345..6db3658 100644 --- a/lib/cli.dart +++ b/lib/cli.dart @@ -38,6 +38,7 @@ class Cli { // ANSI escape code to clear the terminal for Unix-based systems Process.runSync("clear", [], runInShell: true); } + moveCursorToTopLeft(); } /// # static `void` moveCursorToTopLeft() diff --git a/lib/hex_editor/editor.dart b/lib/hex_editor/editor.dart index eafa7b6..d83129b 100644 --- a/lib/hex_editor/editor.dart +++ b/lib/hex_editor/editor.dart @@ -6,84 +6,32 @@ import 'package:chalkdart/chalkstrings.dart'; import 'package:dart_console/dart_console.dart'; import '../cli.dart'; import '../version_control/dossier.dart'; +import 'widget_system.dart'; enum Views { - jumpToAddress, // For jumping to an address. - byteViewer, // For moving through the file byte by byte. - dataFooter, // For editing data visible in the footer. - changeLog, // For looking at the change log. TODO: Needs to be implemented. + jumpToAddress, + byteViewer, + dataFooter, + changeLog, } -enum Formats { - u8, - u16, - u32, - u64 -} // The data formats bytes can be displayed and edited in. +enum Formats { u8, u16, u32, u64 } class HexEditor { - /// # final `Plasma` _primaryFile - /// ## The file being edited. final Plasma _primaryFile; - - /// # final `Plasma?` _secondaryFile - /// ## The older version of the file being used for comparison. Plasma? _secondaryFile; - - /// # final `Map` differences - /// ## The differences between the primary file and the secondary file. DifferenceMap differences = DifferenceMap(); - - /// # final `KeyboardInput` keyboard - /// ## The keyboard input handler. final keyboard = KeyboardInput(); - - /// # `Views` currentView - /// ## The current view of the editor. - /// Defaults to `Views.byteViewer`. Views currentView = Views.byteViewer; - - /// # `ByteData` data - /// ## The data being edited. - /// Returns the primary file's data. ByteData get data => _primaryFile.data; - - /// # `Endian` dataEndian - /// ## The endianness of the data. - /// Defaults to `Endian.little`. Endian dataEndian = Endian.little; - - /// # `int` address - /// ## The current address being viewed/edited. int address = 0; - - /// # `Formats` currentFormat - /// ## The current format of the data being edited. Formats currentFormat = Formats.u8; - - /// # `String?` _currentValue - /// ## The current value being inputed. - /// Used for the `dataFooter` and `jumpToAddress` views. String? _currentValue; - - /// # `bool` error - /// ## Whether or not an error has occurred. bool error = false; - - /// # `List` byteColor - /// ## The color label for a byte. final List byteColor = [255, 255, 255]; - - /// # `List` byte16Color - /// ## The color label for a 16-bit range. final List byte16Color = [140, 140, 140]; - - /// # `List` byte32Color - /// ## The color label for a 32-bit range. final List byte32Color = [100, 100, 100]; - - /// # `List` byte64Color - /// ## The color label for a 64-bit range. final List byte64Color = [60, 60, 60]; HexEditor(this._primaryFile) { @@ -93,39 +41,28 @@ class HexEditor { } } - /// # `String` getByteAt(int address) - /// ## Get the byte at the given address as a hex string. String getByteAt(int address) { return data.getUint8(address).toRadixString(16).padLeft(2, "0"); } - /// # `bool` isValidAddress(int address) - /// ## Check if an address is valid. bool isValidAddress(int address) { return address >= 0 && address < data.lengthInBytes; } - /// # `void` render() - /// ## Render the current state of the editor to the console. void render() { - Cli.moveCursorToTopLeft(); - Cli.clearTerminal(); - Cli.moveCursorToTopLeft(); - final header = getHeader(); + final header = Header(getHeader()); + final footer = Footer(getFooter()); + final body = TextWidget(getBody()); + + final rootWidget = Column([ + header, + body, + footer, + ]); - final footer = getFooter(); - int linesUsedByHeader = header.split('\n').length; - int linesUsedByFooter = footer.split('\n').length; - stdout.write(header); - stdout.write("\n"); - stdout.write(getBody( - (Cli.windowHeight - linesUsedByFooter) - linesUsedByHeader + 5)); - Cli.moveCursorToBottomLeft(linesUsedByFooter - 1); - stdout.write(footer); + WidgetSystem(rootWidget).render(); } - /// # `String` getHeader() - /// ## Get the header of the editor. String getHeader() { String header = ""; header += _primaryFile.getFilename().italic; @@ -138,11 +75,8 @@ class HexEditor { return header; } - /// # `String` getFooter() - /// ## Get the footer of the editor. String getFooter() { String footer = ""; - // Write address at bottom left. footer += "A".underline.bold; footer += "ddress: "; if (currentView == Views.jumpToAddress) { @@ -179,12 +113,10 @@ class HexEditor { return (((data.lengthInBytes) >> 1 << 1) / 16).ceil(); } - /// # `String` renderBody() - /// ## Render the bytes as the body of the editor. - String getBody(int usableRows) { + String getBody() { final full = StringBuffer(); final body = StringBuffer(); - usableRows -= 8; + int usableRows = Cli.windowHeight - 8; int startLine = 0; int endLine = (getFileSizeInLines()); if (usableRows < getFileSizeInLines()) { @@ -192,7 +124,6 @@ class HexEditor { startLine = getLineAddress() - linesAboveBelow; endLine = getLineAddress() + linesAboveBelow; - // Adjust start and end to ensure full screen is used if (startLine < 0) { endLine += startLine.abs(); startLine = 0; @@ -204,18 +135,16 @@ class HexEditor { } full.write("\t\t00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n" - .padLeft(8, " ")); // Address Headers + .padLeft(8, " ")); for (int x = startLine * 16; x < data.lengthInBytes && x < endLine * 16; x += 16) { if (usableRows <= 0) { break; } - // 16 bytes per line, with a gap between every eight bytes. - final line = StringBuffer(""); // The line to be printed - line.write("${x.toRadixString(16).padLeft(8, "0")}\t"); // Address Labels + final line = StringBuffer(""); + line.write("${x.toRadixString(16).padLeft(8, "0")}\t"); for (int leftHalf = 0; leftHalf < 8; leftHalf++) { - // Left Half of 16 bytes int byteAddress = x + leftHalf; if (!isValidAddress(byteAddress)) { line.write(" "); @@ -229,9 +158,7 @@ class HexEditor { } } line.write(" "); - // Checks to see if there is a second half of 8 bytes for (int rightHalf = 8; rightHalf < 16; rightHalf++) { - // Right Half of 16 bytes int byteAddress = x + rightHalf; if (!isValidAddress(byteAddress)) { line.write(" "); @@ -259,7 +186,6 @@ class HexEditor { usableRows--; } if (startLine > 0) { - //Notifies user that there is more data above full.write("\t".padLeft(16, " ")); full.write("───────────────────────^───────────────────────\n"); } else { @@ -267,7 +193,6 @@ class HexEditor { } full.write(body.toString()); if (endLine < getFileSizeInLines()) { - //Notifies user that there is more data below full.write("\t".padLeft(16, " ")); full.write("───────────────────────v───────────────────────\n"); } else { @@ -276,17 +201,9 @@ class HexEditor { return full.toString(); } - /// # `String` getValues(int byteAddress) - /// ## Get the values of the different formats at the given address. - /// The values are formatted as a string with the header in the corresponding - /// color and the value in the same color. - /// If the current view is the data footer, the current format is highlighted. - /// If the current view is not the data footer, it adds a note to press E to - /// edit any of these values. String getValues(int byteAddress) { StringBuffer values = StringBuffer(); for (Formats format in Formats.values) { - // Add all the formats to the values buffer. error = false; String? value; String? header; @@ -371,7 +288,6 @@ class HexEditor { break; } if (value == null || header == null) { - //If there is no value or header, that means it is not availabe during this frame. continue; } if (currentView == Views.dataFooter && currentFormat == format) { @@ -394,9 +310,6 @@ class HexEditor { return values.toString(); } - /// # `String` getFormatted(int byteAddress, String value) - /// ## Get the values of the different formats at the given address. - /// The values are formatted as a string with the header in the corresponding color. String getFormatted(int byteAddress, String value) { if (byteAddress == address) { value = value.bgRgb(byteColor[0], byteColor[1], byteColor[2]).black; @@ -415,15 +328,10 @@ class HexEditor { return value; } - /// # `bool` _isPrintable(int charCode) - /// ## Check if the given character code is printable. - /// Used to make sure that no control characters are entered, which would break the editor. bool _isPrintable(int charCode) { return charCode >= 32 && charCode <= 126; } - /// # `bool` _hexView(Key key) - /// ## Handle key presses in the hex view. bool _hexView(Key key) { bool quit = false; if (!key.isControl) { @@ -489,8 +397,6 @@ class HexEditor { return quit; } - /// # `void` _dataFooterView(Key key) - /// ## Handle key presses in the data footer view. void _dataFooterView(Key key) { if (!key.isControl) { _currentValue ??= ""; @@ -559,8 +465,6 @@ class HexEditor { } } - /// # `void` _jumpToAddressView(Key key) - /// ## Handle key presses in the jump to address view. void _jumpToAddressView(Key key) { if (!key.isControl) { _currentValue ??= ""; @@ -597,8 +501,6 @@ class HexEditor { } } - /// # `void` _backspaceCurrentValue() - /// ## Backspace the `_currentValue`. void _backspaceCurrentValue() { if (_currentValue != null && _currentValue!.isNotEmpty) { _currentValue = _currentValue!.substring(0, _currentValue!.length - 1); @@ -606,8 +508,6 @@ class HexEditor { } } - /// # `Future` interact() - /// ## Call this to start the editor for interaction. Future interact() async { int lastHeight = 1; int lastWidth = 1; diff --git a/lib/hex_editor/widget_system.dart b/lib/hex_editor/widget_system.dart new file mode 100644 index 0000000..1b3d4ab --- /dev/null +++ b/lib/hex_editor/widget_system.dart @@ -0,0 +1,109 @@ +import 'dart:io'; + +import 'package:arceus/cli.dart'; + +class Size { + final int width; + final int height; + + Size(this.width, this.height); +} + +abstract class Widget { + void render(Size size); +} + +class Row extends Widget { + final List children; + + Row(this.children); + + @override + void render(Size size) { + int childWidth = size.width ~/ children.length; + for (var child in children) { + child.render(Size(childWidth, size.height)); + } + print(''); + } +} + +class Column extends Widget { + final List children; + + Column(this.children); + + @override + void render(Size size) { + int childHeight = size.height ~/ children.length; + for (var child in children) { + child.render(Size(size.width, childHeight)); + } + } +} + +class Grid extends Widget { + final List> children; + + Grid(this.children); + + @override + void render(Size size) { + int rowHeight = size.height ~/ children.length; + for (var row in children) { + int colWidth = size.width ~/ row.length; + for (var child in row) { + child.render(Size(colWidth, rowHeight)); + } + print(''); + } + } +} + +class Header extends Widget { + final String text; + + Header(this.text); + + @override + void render(Size size) { + Cli.moveCursorToTopLeft(); + print(text.padRight(size.width)); + } +} + +class Footer extends Widget { + final String text; + + Footer(this.text); + + @override + void render(Size size) { + Cli.moveCursorToBottomLeft(text.split('\n').length); + print(text.padRight(size.width)); + } +} + +class TextWidget extends Widget { + final String text; + + TextWidget(this.text); + + @override + void render(Size size) { + stdout.write(text.padRight(size.width)); + } +} + +class WidgetSystem { + final Widget rootWidget; + + WidgetSystem(this.rootWidget); + + void render() { + Cli.clearTerminal(); + int width = stdout.terminalColumns; + int height = stdout.terminalLines; + rootWidget.render(Size(width, height)); + } +} diff --git a/lib/main.dart b/lib/main.dart index 97a2d5e..ab754b7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -157,12 +157,11 @@ The current star is marked with ✨ ShowMapConstellationCommand(); @override - dynamic _run() { + void _run() { print( "Currently signed in as ${constellation.loggedInUser?.name.italic()}."); constellation.starmap?.printMap(); constellation.printSumOfCurStar(); - return jsonEncode(constellation.starmap?.toJson()); } } @@ -700,7 +699,7 @@ class ReadFileCommand extends ArceusCommand { return null; } Plasma plasma = Plasma.fromFile(file); - final result = (addons.first.context as PatternAdddonContext).read(plasma); + final result = (addons.first.context as PatternAddonContext).read(plasma); if (!Arceus.isInternal) { print(AnsiTreeView(result, theme: Cli.treeTheme)); } diff --git a/lib/scripting/addon.dart b/lib/scripting/addon.dart index 75b4d20..a857b76 100644 --- a/lib/scripting/addon.dart +++ b/lib/scripting/addon.dart @@ -19,8 +19,22 @@ enum FeatureSets { class Addon { final File addonFile; + Addon(this.addonFile) { + if (!addonFile.existsSync()) { + throw Exception("Addon file does not exist."); + } + switch (featureSet) { + case FeatureSets.pattern: + _context = PatternAddonContext(this); + break; + case FeatureSets.none: + _context = NoneAdddonContext(this); + break; + } + } + String get path => addonFile.path; - String get name => getMetadata()["name"]; + String get name => getMetadata()["name"] ?? "Unknown"; bool get isGlobal { if (isUninstalled()) { @@ -45,15 +59,16 @@ class Addon { return _context; } - /// # `String` get code - /// ## Returns the code of the addon. - /// Used by context. String get code => getCode(); String get decodedString { - Uint8List data = addonFile.readAsBytesSync(); - List decoded = gzip.decoder.convert(data.toList()); - return utf8.decode(decoded); + try { + Uint8List data = addonFile.readAsBytesSync(); + List decoded = gzip.decoder.convert(data.toList()); + return utf8.decode(decoded); + } catch (e) { + throw Exception("Failed to decode addon file: $e"); + } } FeatureSets get featureSet { @@ -65,17 +80,6 @@ class Addon { } } - Addon(this.addonFile) { - switch (featureSet) { - case FeatureSets.pattern: - _context = PatternAdddonContext(this); - break; - case FeatureSets.none: - _context = NoneAdddonContext(this); - break; - } - } - static Addon package(String projectPath, String outputPath) { if (!_validate(projectPath)) { YamlMap yaml = _getAddonYaml(projectPath); @@ -88,7 +92,7 @@ class Addon { while (body.contains(RegExp(r"#\s*include\(([a-zA-Z\/\s]*.nut)\s*\)"))) { final match = RegExp(r"#\s*include\(([a-zA-Z\/\s]*.nut)\s*\)").firstMatch(body)!; - body.replaceRange(match.start, match.end, ""); + body = body.replaceRange(match.start, match.end, ""); body += File("$projectPath/${match.group(1)!}").readAsStringSync(); body += "\n"; } @@ -110,16 +114,20 @@ class Addon { throw Exception("Invalid addon! Please check your addon.yaml file."); } - /// # `YamlMap` _getAddonYaml(`String` projectPath) - /// ## Returns the contents of addon.yaml as a YamlMap. - /// - /// The `projectPath` argument is the path to the project directory. static YamlMap _getAddonYaml(String projectPath) { - return loadYaml(File("$projectPath/addon.yaml").readAsStringSync()); + try { + return loadYaml(File("$projectPath/addon.yaml").readAsStringSync()); + } catch (e) { + throw Exception("Failed to load addon.yaml: $e"); + } } static String _getAddonYamlAsString(String projectPath) { - return File("$projectPath/addon.yaml").readAsStringSync(); + try { + return File("$projectPath/addon.yaml").readAsStringSync(); + } catch (e) { + throw Exception("Failed to read addon.yaml: $e"); + } } static bool _validate(String projectPath) { @@ -129,20 +137,22 @@ class Addon { isValid = false; } - YamlMap addonYaml = - loadYaml(File("$projectPath/addon.yaml").readAsStringSync()); + YamlMap addonYaml; + try { + addonYaml = loadYaml(File("$projectPath/addon.yaml").readAsStringSync()); + } catch (e) { + return false; + } if (!_validateMetadata(addonYaml)) { - // do check on metadata to make sure it is valid. isValid = false; } return isValid; } static bool _validateMetadata(YamlMap metadata) { - bool isVaild = true; + bool isValid = true; - // check for required keys List requiredKeys = [ "name", "description", @@ -154,32 +164,24 @@ class Addon { for (String key in requiredKeys) { if (!metadata.containsKey(key)) { - isVaild = false; + isValid = false; } } - if (isVaild) { - // check typing of values - if (metadata["name"] is! String) { - isVaild = false; - } else if (metadata["description"] is! String) { - isVaild = false; - } else if (metadata["version"] is! String) { - isVaild = false; - } else if (metadata["authors"] is! YamlList) { - isVaild = false; - } else if (metadata["feature-set"] is! String) { - isVaild = false; - } else if (metadata["entrypoint"] is! YamlList) { - isVaild = false; + if (isValid) { + if (metadata["name"] is! String || + metadata["description"] is! String || + metadata["version"] is! String || + metadata["authors"] is! YamlList || + metadata["feature-set"] is! String || + metadata["entrypoint"] is! String) { + isValid = false; } } - return isVaild; + return isValid; } - /// # `factory` Addon.installGlobally() - /// ## Installs an addon globally. factory Addon.installGlobally(String pathToAddonFile, {bool deleteOld = true}) { if (!File(pathToAddonFile).existsSync()) { @@ -205,8 +207,6 @@ class Addon { File("${Arceus.globalAddonPath}/${pathToAddonFile.getFilename()}")); } - /// # `factory` Addon.installLocally() - /// ## Installs an addon locally to the current constellation. factory Addon.installLocally(String pathToAddonFile, {bool deleteOld = true}) { if (!File(pathToAddonFile).existsSync()) { @@ -215,7 +215,11 @@ class Addon { File file = File(pathToAddonFile); Uint8List data = file.readAsBytesSync(); if (deleteOld) { - file.deleteSync(); + try { + file.deleteSync(); + } catch (e) { + throw Exception("Failed to delete old addon file: $e"); + } } file = File( "${Constellation(path: Arceus.currentPath).addonFolderPath}/${pathToAddonFile.getFilename()}"); @@ -236,12 +240,14 @@ class Addon { } void uninstall() { - File file = File(path); - file.deleteSync(); + try { + File file = File(path); + file.deleteSync(); + } catch (e) { + throw Exception("Failed to uninstall addon: $e"); + } } - /// # `static` getInstalledAddons() - /// ## Returns a list of all installed addons. static List getInstalledAddons() { List addons = []; if (Constellation.checkForConstellation(Arceus.currentPath)) { @@ -274,27 +280,23 @@ class Addon { return addons; } - /// # `AddonDetails` _getDetails() - /// ## Returns the details of the addon. - /// It is separated by `---END-OF-DETAILS---`. YamlMap getMetadata() { - return loadYaml(decodedString.split("---END-OF-DETAILS---")[0]); + try { + return loadYaml(decodedString.split("---END-OF-DETAILS---")[0]); + } catch (e) { + throw Exception("Failed to get metadata: $e"); + } } - /// # `String` _getCode() - /// ## Returns the code of the addon. - /// It is separated by `---END-OF-DETAILS---`. String getCode() { - return decodedString.split("---END-OF-DETAILS---")[1]; + try { + return decodedString.split("---END-OF-DETAILS---")[1]; + } catch (e) { + throw Exception("Failed to get code: $e"); + } } } -/// # `AddonContext` -/// ## An abstract class that represents the context of an addon. -/// Acts as the bridge between the addon and the Squirrel VM. -/// Before, Addon was abstract with subclasses acting as different feature sets. -/// However, this is not the case anymore. Addons will create a [AddonContext] that the `addon.yaml` asks for, -/// and then use it to run the addon. abstract class AddonContext { static final RegExp functionNameRegex = RegExp(r"function\s([A-Za-z\d]*)\([A-Za-z,\s]*\)"); @@ -319,10 +321,10 @@ abstract class AddonContext { return true; } - /// # `Pointer` startVM() - /// ## Starts the Squirrel VM and returns the VM pointer. - /// It also creates the API for the Squirrel VM, so be sure all the functions have been added to [functions]. Pointer startVM() { + if (addon == null) { + throw Exception("Addon is not set."); + } final vm = Squirrel.run(addon!.code); Squirrel.createAPI(vm, functions); return vm; diff --git a/lib/scripting/feature_sets/patterns.dart b/lib/scripting/feature_sets/patterns.dart index 38940f4..ae5b89d 100644 --- a/lib/scripting/feature_sets/patterns.dart +++ b/lib/scripting/feature_sets/patterns.dart @@ -7,8 +7,8 @@ import '../squirrel.dart'; import '../squirrel_bindings_generated.dart'; import '../../version_control/dossier.dart'; -class PatternAdddonContext extends AddonContext { - PatternAdddonContext(super.addon); +class PatternAddonContext extends AddonContext { + PatternAddonContext(super.addon); Plasma? plasma; diff --git a/lib/uuid.dart b/lib/uuid.dart index de00d05..29d40b7 100644 --- a/lib/uuid.dart +++ b/lib/uuid.dart @@ -11,14 +11,13 @@ String generateUUID() { } String generateUniqueHash(Set existingHashes, {int length = 32}) { + if (existingHashes.length >= (1 << (length * 4))) { + throw Exception("Unable to generate a unique hash! No available hashes."); + } + String hash = generateUUID(); - int retries = 8192; while (existingHashes.contains(hash.substring(0, length))) { - if (retries <= 0) { - throw Exception("Unable to generate a unique hash! Retries exceeded."); - } hash = generateUUID(); - retries--; } return hash.substring(0, length); } diff --git a/lib/version_control/constellation.dart b/lib/version_control/constellation.dart index d73f1f0..0fd5d2d 100644 --- a/lib/version_control/constellation.dart +++ b/lib/version_control/constellation.dart @@ -195,7 +195,7 @@ class Constellation { Map toJson() => { "name": name, "loggedInUser": loggedInUser?.hash, - "map": starmap?.toJson() + "map": starmap?._toJson() }; // ============================================================================ @@ -303,7 +303,7 @@ class Starmap { _childMap = {}; parentMap = {}; } else { - fromJson(map); + _fromJson(map); } } @@ -407,7 +407,7 @@ class Starmap { /// # `Map` toJson() /// ## Returns a JSON map of the starmap. /// This is used when saving the starmap to disk. - Map toJson() { + Map _toJson() { _childMap.removeWhere((key, value) => value.isEmpty); return { "root": _rootHash, @@ -420,7 +420,7 @@ class Starmap { /// # `void` fromJson(`Map` json) /// ## Uses a JSON map to initialize the starmap. /// This is used when loading the starmap from disk. - void fromJson(Map json) { + void _fromJson(Map json) { _rootHash = json["root"]; _currentStarHash = json["current"]; for (String hash in json["children"].keys) { @@ -440,7 +440,7 @@ class Starmap { /// The list will be empty if the parent has no children. List getChildren(Star parent) { List children = []; - for (String hash in getChildrenHashes(parent.hash!)) { + for (String hash in _getChildrenHashes(parent.hash!)) { children.add(Star(constellation, hash: hash)); } return children; @@ -449,7 +449,7 @@ class Starmap { /// # `List` getChildrenHashes(`String` parent) /// ## Returns a list of all children hashes of the given parent. /// The list will be empty if the parent has no children. - List getChildrenHashes(String parent) { + List _getChildrenHashes(String parent) { return _childMap[parent] ?? []; } @@ -570,7 +570,7 @@ class Starmap { /// # `bool` existAtCoordinates(`int` depth, `int` index) /// ## Returns true if a star exists at the given depth and index. /// Returns false otherwise. - bool existAtCoordinates(int depth, int index) { + bool _existAtCoordinates(int depth, int index) { List stars = getStarsAtDepth(depth); if (index >= 0 && index < stars.length) { return true; @@ -582,8 +582,8 @@ class Starmap { /// ## Returns true if there is a star next to the given coordinates. /// Returns false otherwise. bool existBesideCoordinates(int depth, int index) { - if (existAtCoordinates(depth, index - 1) || - existAtCoordinates(depth, index + 1)) { + if (_existAtCoordinates(depth, index - 1) || + _existAtCoordinates(depth, index + 1)) { return true; } return false; diff --git a/lib/version_control/dossier.dart b/lib/version_control/dossier.dart index 489f34a..13e11a2 100644 --- a/lib/version_control/dossier.dart +++ b/lib/version_control/dossier.dart @@ -22,10 +22,10 @@ class Dossier { Star star; // The following are used for the CLI: - String addSymbol = "A".bold().green(); - String removeSymbol = "D".bold().red(); - String moveSymbol = "→".bold().aqua(); - String modifiedSymbol = "M".bold().yellow(); + final String _addSymbol = "A".bold().green(); + final String _removeSymbol = "D".bold().red(); + final String _moveSymbol = "→".bold().aqua(); + final String _modifiedSymbol = "M".bold().yellow(); Dossier(this.star); @@ -46,25 +46,25 @@ class Dossier { spinner = CliSpin(text: " Checking for new files...").start(); } - List newFiles = listAddedFiles(); + List newFiles = _listAddedFiles(); if (!silent) spinner!.stop(); // Check for removed files. if (!silent) { spinner = CliSpin(text: " Checking for removed files...").start(); } - List removedFiles = listRemovedFiles(); + List removedFiles = _listRemovedFiles(); if (!silent) spinner!.stop(); // Check for moved files. Done after new and removed files, as they can be used here to make a cross reference. if (!silent) { spinner = CliSpin(text: " Checking for moved files...").start(); } - Map movedFiles = listMovedFiles(newFiles, removedFiles); + Map movedFiles = _listMovedFiles(newFiles, removedFiles); if (movedFiles.isNotEmpty) { check = true; spinner!.stop(); for (String file in movedFiles.keys) { - print(" $file $moveSymbol ${movedFiles[file]}"); + print(" $file $_moveSymbol ${movedFiles[file]}"); } } else { spinner?.success(" There are no moved files."); @@ -78,7 +78,7 @@ class Dossier { if (movedFiles.containsValue(file)) { continue; } - print(" $addSymbol $file"); + print(" $_addSymbol $file"); } } else { spinner?.success(" There are no new files."); @@ -92,7 +92,7 @@ class Dossier { if (movedFiles.containsKey(file)) { continue; } - print(" $removeSymbol $file"); + print(" $_removeSymbol $file"); } } else { spinner?.success(" There are no removed files."); @@ -102,12 +102,12 @@ class Dossier { if (!silent) { spinner = CliSpin(text: " Checking for changed files...").start(); } - List changedFiles = listChangedFiles(removedFiles); + List changedFiles = _listChangedFiles(removedFiles); if (changedFiles.isNotEmpty) { spinner?.fail(" Changed files found:"); check = true; for (String file in changedFiles) { - print(" $modifiedSymbol $file"); + print(" $_modifiedSymbol $file"); } } else { spinner?.success(" There are no changed files."); @@ -117,7 +117,7 @@ class Dossier { /// # `List` listAddedFiles() /// ## Lists all files in the current directory that have been recently added. - List listAddedFiles() { + List _listAddedFiles() { Archive archive = star.getArchive(); List newFiles = []; for (FileSystemEntity entity @@ -139,7 +139,7 @@ class Dossier { /// # `List` listRemovedFiles() /// ## Lists all files in the current directory that have been recently removed. - List listRemovedFiles() { + List _listRemovedFiles() { Archive archive = star.getArchive(); List removedFiles = []; for (ArchiveFile file in archive.files) { @@ -155,7 +155,7 @@ class Dossier { /// # `Map` listMovedFiles(`List` newFiles, `List` removedFiles) /// ## Lists all files in the current directory that have been recently moved. - Map listMovedFiles( + Map _listMovedFiles( List newFiles, List removedFiles) { Map movedFiles = {}; for (String file in removedFiles) { @@ -174,7 +174,7 @@ class Dossier { /// # `List` listChangedFiles(`List` removedFiles) /// ## Lists all files in the current directory that have been recently changed. - List listChangedFiles(List removedFiles) { + List _listChangedFiles(List removedFiles) { Archive archive = star.getArchive(); List changedFiles = []; for (ArchiveFile file in archive.files) { @@ -282,7 +282,7 @@ class Plasma { .firstWhere((e) => (e.getMetadata()["associated-files"] as YamlList) .contains(getExtension())); AnsiTreeView tree = AnsiTreeView( - (addon.context as PatternAdddonContext).read(this), + (addon.context as PatternAddonContext).read(this), theme: Cli.treeTheme); print(tree.toString()); } @@ -312,18 +312,17 @@ class Plasma { return changes; } - /// # `Map` getDifferences(Plasma other) + /// # `DifferenceMap` getDifferences(Plasma other) /// ## Compares the current plasma to another plasma. /// Returns a map of the differences between the two plasmas. /// The keys are the addresses of the differences, and the values are the values at those addresses in the current plasma. DifferenceMap getDifferences(Plasma other) { - DifferenceMap differences = DifferenceMap(); - for (int i = 0; - i < - (other.data.lengthInBytes >= data.lengthInBytes - ? other.data.lengthInBytes - : data.lengthInBytes); // Get the largest length - ++i) { + final differences = DifferenceMap(); + final maxLength = other.data.lengthInBytes >= data.lengthInBytes + ? other.data.lengthInBytes + : data.lengthInBytes; + + for (int i = 0; i < maxLength; ++i) { if (i >= data.lengthInBytes) { differences.addAddition(i, other.data.getUint8(i)); } else if (i >= other.data.lengthInBytes) { @@ -363,7 +362,7 @@ class Plasma { enum ChangeOrigin { from, to } /// # `class` `DifferenceMap` -/// ## Used to originize the differences between two plasmas into maps. +/// ## Used to organize the differences between two plasmas into maps. class DifferenceMap { Map> modifications = {}; Map additions = {}; diff --git a/lib/version_control/star.dart b/lib/version_control/star.dart index b3fd236..ca446ac 100644 --- a/lib/version_control/star.dart +++ b/lib/version_control/star.dart @@ -195,7 +195,7 @@ class Star { /// # Archive getArchive() /// ## Returns the archive of the star. - /// ALWAYS, ALWAYS, ALWAYS call [clearSync] on the archive after using it. + /// ALWAYS, ALWAYS, ALWAYS call [clearSync] on the archive object after using it. /// If you don't, then trimming the star will not work, and will throw an access error. Archive getArchive() { final inputStream = InputFileStream(constellation.getStarPath(hash!));