Initial commit.
This commit is contained in:
commit
8eb7a7ce99
17 changed files with 913 additions and 0 deletions
88
.gitignore
vendored
Normal file
88
.gitignore
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
*.class
|
||||||
|
*.code-workspace
|
||||||
|
*.ctxt
|
||||||
|
*.iws
|
||||||
|
*.log
|
||||||
|
*.nar
|
||||||
|
*.rar
|
||||||
|
*.sublime-*
|
||||||
|
*.tar.gz
|
||||||
|
*.zip
|
||||||
|
.DS_Store
|
||||||
|
.classpath
|
||||||
|
.dart_tool/
|
||||||
|
.gradle
|
||||||
|
.history
|
||||||
|
.kobalt
|
||||||
|
.mtj.tmp/
|
||||||
|
.mvn/timing.properties
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
.nb-gradle
|
||||||
|
.packages
|
||||||
|
.project
|
||||||
|
.scannerwork
|
||||||
|
.settings
|
||||||
|
.vscode/*
|
||||||
|
/**/.idea/$CACHE_FILE$
|
||||||
|
/**/.idea/$PRODUCT_WORKSPACE_FILE$
|
||||||
|
/**/.idea/**/caches/build_file_checksums.ser
|
||||||
|
/**/.idea/**/contentModel.xml
|
||||||
|
/**/.idea/**/dataSources.ids
|
||||||
|
/**/.idea/**/dataSources.local.xml
|
||||||
|
/**/.idea/**/dataSources/
|
||||||
|
/**/.idea/**/dbnavigator.xml
|
||||||
|
/**/.idea/**/dictionaries
|
||||||
|
/**/.idea/**/dynamic.xml
|
||||||
|
/**/.idea/**/gradle.xml
|
||||||
|
/**/.idea/**/httpRequests
|
||||||
|
/**/.idea/**/libraries
|
||||||
|
/**/.idea/**/mongoSettings.xml
|
||||||
|
/**/.idea/**/replstate.xml
|
||||||
|
/**/.idea/**/shelf
|
||||||
|
/**/.idea/**/shelf/
|
||||||
|
/**/.idea/**/sqlDataSources.xml
|
||||||
|
/**/.idea/**/tasks.xml
|
||||||
|
/**/.idea/**/uiDesigner.xml
|
||||||
|
/**/.idea/**/usage.statistics.xml
|
||||||
|
/**/.idea/**/workspace.xml
|
||||||
|
/**/.idea/sonarlint*
|
||||||
|
/**/.idea_modules/
|
||||||
|
Thumbs.db
|
||||||
|
__pycache__
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
bin/dcat
|
||||||
|
bin/dcat.exe
|
||||||
|
build/
|
||||||
|
cmake-build-*/
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics-build.properties
|
||||||
|
crashlytics.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
deploy/
|
||||||
|
dist/
|
||||||
|
ehthumbs.db
|
||||||
|
fabric.properties
|
||||||
|
gen/
|
||||||
|
gradle.properties
|
||||||
|
hs_err_pid*
|
||||||
|
kobaltBuild
|
||||||
|
kobaltw*-test
|
||||||
|
lib/kotlin*
|
||||||
|
libs/
|
||||||
|
local.properties
|
||||||
|
out/
|
||||||
|
pom.xml.asc
|
||||||
|
pom.xml.next
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
proguard-project.txt
|
||||||
|
project.properties
|
||||||
|
release.properties
|
||||||
|
target/
|
||||||
|
test-output
|
||||||
|
venv
|
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
43
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
43
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="TOP_LEVEL_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="INNER_CLASS_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="METHOD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="FIELD_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
|
||||||
|
<option name="REQUIRED_TAGS" value="" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="IGNORE_DEPRECATED" value="false" />
|
||||||
|
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
|
||||||
|
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
|
||||||
|
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
|
||||||
|
<option name="myAdditionalJavadocTags" value="created" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="REPORT_VARIABLES" value="true" />
|
||||||
|
<option name="REPORT_PARAMETERS" value="true" />
|
||||||
|
<option name="REPORT_CATCH_PARAMETERS" value="false" />
|
||||||
|
<option name="REPORT_IMPLICIT_FINALS" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="RedundantExplicitVariableType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/dcat.iml" filepath="$PROJECT_DIR$/dcat.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
10
.idea/runConfigurations.xml
generated
Normal file
10
.idea/runConfigurations.xml
generated
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
- Initial version.
|
29
LICENSE
Normal file
29
LICENSE
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2021, Erik C. Thauvin (erik@thauvin.net)
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of this project nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2
README.md
Normal file
2
README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Concatenate file(s) to standard output.
|
||||||
|
|
30
analysis_options.yaml
Normal file
30
analysis_options.yaml
Normal file
|
@ -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
|
200
bin/dcat.dart
Normal file
200
bin/dcat.dart
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
// Copyright (c) 2021, Erik C. Thauvin. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
|
// in the LICENSE file.
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:args/args.dart';
|
||||||
|
import 'package:indent/indent.dart';
|
||||||
|
|
||||||
|
const appName = 'dcat';
|
||||||
|
const appVersion = '1.0.0';
|
||||||
|
const exitFailure = 1;
|
||||||
|
const exitSuccess = 0;
|
||||||
|
const helpFlag = 'help';
|
||||||
|
const nonBlankFlag = 'number-nonblank';
|
||||||
|
const numberFlag = 'number';
|
||||||
|
const showEndsFlag = 'show-ends';
|
||||||
|
const showTabsFlag = 'show-tabs';
|
||||||
|
const squeezeBlank = 'squeeze-blank';
|
||||||
|
const versionFlag = 'version';
|
||||||
|
|
||||||
|
/// Prints [message] and [path] to stderr.
|
||||||
|
Future<int> handleError(String message, {String path = ''}) async {
|
||||||
|
if (path.isNotEmpty) {
|
||||||
|
stderr.writeln('$appName: $path: $message');
|
||||||
|
} else {
|
||||||
|
stderr.write('$appName: $message');
|
||||||
|
}
|
||||||
|
return exitFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Concatenates files in [paths].
|
||||||
|
Future<int> cat(List<String> paths,
|
||||||
|
{List<String>? log,
|
||||||
|
bool showEnds = false,
|
||||||
|
bool numberNonBlank = false,
|
||||||
|
bool showLineNumbers = false,
|
||||||
|
bool showTabs = false,
|
||||||
|
bool squeezeBlank = false}) async {
|
||||||
|
var lineNumber = 1;
|
||||||
|
var returnCode = 0;
|
||||||
|
log?.clear();
|
||||||
|
if (paths.isEmpty) {
|
||||||
|
final lines = await _readStdin();
|
||||||
|
await _writeLines(lines, lineNumber, log, showEnds, showLineNumbers,
|
||||||
|
numberNonBlank, showTabs, squeezeBlank);
|
||||||
|
} else {
|
||||||
|
for (final path in paths) {
|
||||||
|
try {
|
||||||
|
final Stream<String> lines;
|
||||||
|
if (path == '-') {
|
||||||
|
lines = await _readStdin();
|
||||||
|
} else {
|
||||||
|
lines = utf8.decoder
|
||||||
|
.bind(File(path).openRead())
|
||||||
|
.transform(const LineSplitter());
|
||||||
|
}
|
||||||
|
lineNumber = await _writeLines(lines, lineNumber, log, showEnds,
|
||||||
|
showLineNumbers, numberNonBlank, showTabs, squeezeBlank);
|
||||||
|
} on FileSystemException catch (e) {
|
||||||
|
final String? osMessage = e.osError?.message;
|
||||||
|
final String message;
|
||||||
|
if (osMessage != null && osMessage.isNotEmpty) {
|
||||||
|
message = osMessage;
|
||||||
|
} else {
|
||||||
|
message = e.message;
|
||||||
|
}
|
||||||
|
returnCode = await handleError(message, path: path);
|
||||||
|
} on FormatException {
|
||||||
|
returnCode =
|
||||||
|
await handleError('Binary file not supported.', path: path);
|
||||||
|
} catch (e) {
|
||||||
|
returnCode = await handleError(e.toString(), path: path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Concatenates files specified in [arguments].
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// dcat [OPTION]... [FILE]...
|
||||||
|
/// ```
|
||||||
|
Future<int> main(List<String> arguments) async {
|
||||||
|
final parser = ArgParser();
|
||||||
|
Future<int> returnCode;
|
||||||
|
exitCode = exitSuccess;
|
||||||
|
parser.addFlag(nonBlankFlag,
|
||||||
|
negatable: false,
|
||||||
|
abbr: 'b',
|
||||||
|
help: 'number nonempty output lines, overrides -n');
|
||||||
|
parser.addFlag(showEndsFlag,
|
||||||
|
negatable: false, abbr: 'E', help: 'display \$ at end of each line');
|
||||||
|
parser.addFlag(helpFlag,
|
||||||
|
negatable: false, abbr: 'h', help: 'display this help and exit');
|
||||||
|
parser.addFlag(numberFlag,
|
||||||
|
negatable: false, abbr: 'n', help: 'number all output lines');
|
||||||
|
parser.addFlag(showTabsFlag,
|
||||||
|
negatable: false, abbr: 'T', help: 'display TAB characters as ^I');
|
||||||
|
parser.addFlag(squeezeBlank,
|
||||||
|
negatable: false,
|
||||||
|
abbr: 's',
|
||||||
|
help: 'suppress repeated empty output lines');
|
||||||
|
parser.addFlag(versionFlag,
|
||||||
|
negatable: false, help: 'output version information and exit');
|
||||||
|
|
||||||
|
final ArgResults argResults;
|
||||||
|
try {
|
||||||
|
argResults = parser.parse(arguments);
|
||||||
|
} on FormatException catch (e) {
|
||||||
|
return await handleError(
|
||||||
|
"${e.message}\nTry '$appName --$helpFlag' for more information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argResults[helpFlag]) {
|
||||||
|
returnCode = usage(parser.usage);
|
||||||
|
} else if (argResults[versionFlag]) {
|
||||||
|
returnCode = printVersion();
|
||||||
|
} else {
|
||||||
|
final paths = argResults.rest;
|
||||||
|
returnCode = cat(paths,
|
||||||
|
showEnds: argResults[showEndsFlag],
|
||||||
|
showLineNumbers: argResults[numberFlag],
|
||||||
|
numberNonBlank: argResults[nonBlankFlag],
|
||||||
|
showTabs: argResults[showTabsFlag],
|
||||||
|
squeezeBlank: argResults[squeezeBlank]);
|
||||||
|
}
|
||||||
|
|
||||||
|
exitCode = await returnCode;
|
||||||
|
return exitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prints version info.
|
||||||
|
Future<int> printVersion() async {
|
||||||
|
print('''$appName (Dart cat) $appVersion
|
||||||
|
Copyright (C) 2021 Erik C. Thauvin
|
||||||
|
License: 3-Clause BSD <https://opensource.org/licenses/BSD-3-Clause>
|
||||||
|
|
||||||
|
Based on <https://dart.dev/tutorials/server/cmdline>
|
||||||
|
Written by Erik C. Thauvin <https://erik.thauvin.net/>''');
|
||||||
|
return exitSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads from stdin.
|
||||||
|
Future<Stream<String>> _readStdin() async =>
|
||||||
|
stdin.transform(utf8.decoder).transform(const LineSplitter());
|
||||||
|
|
||||||
|
/// Prints usage with [options].
|
||||||
|
Future<int> usage(String options) async {
|
||||||
|
print('''Usage: $appName [OPTION]... [FILE]...
|
||||||
|
Concatenate FILE(s) to standard output.
|
||||||
|
|
||||||
|
With no FILE, or when FILE is -, read standard input.
|
||||||
|
|
||||||
|
${options.indent(2)}
|
||||||
|
Examples:
|
||||||
|
$appName f - g Output f's contents, then standard input, then g's contents.
|
||||||
|
$appName Copy standard input to standard output.
|
||||||
|
|
||||||
|
Source and documentation: <https://github.com/ethauvin/dcat>''');
|
||||||
|
return exitSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes lines to stdout.
|
||||||
|
Future<int> _writeLines(Stream<String> lines, int lineNumber,
|
||||||
|
[List<String>? log,
|
||||||
|
bool showEnds = false,
|
||||||
|
bool showLineNumbers = false,
|
||||||
|
bool showNonBlank = false,
|
||||||
|
bool showTabs = false,
|
||||||
|
bool sqeezeBlank = false]) async {
|
||||||
|
var emptyLine = 0;
|
||||||
|
final sb = StringBuffer();
|
||||||
|
await for (final line in lines) {
|
||||||
|
sb.clear();
|
||||||
|
if (sqeezeBlank && line.isEmpty) {
|
||||||
|
if (++emptyLine >= 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyLine = 0;
|
||||||
|
}
|
||||||
|
if (showNonBlank || showLineNumbers) {
|
||||||
|
sb.write('${lineNumber++}: ');
|
||||||
|
}
|
||||||
|
if (showTabs) {
|
||||||
|
sb.write(line.replaceAll('\t', '^I'));
|
||||||
|
} else {
|
||||||
|
sb.write(line);
|
||||||
|
}
|
||||||
|
if (showEnds) {
|
||||||
|
sb.write('\$');
|
||||||
|
}
|
||||||
|
|
||||||
|
log?.add(sb.toString());
|
||||||
|
stdout.writeln(sb);
|
||||||
|
}
|
||||||
|
return lineNumber;
|
||||||
|
}
|
14
dcat.iml
Normal file
14
dcat.iml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||||
|
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
348
pubspec.lock
Normal file
348
pubspec.lock
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
# Generated by pub
|
||||||
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
_fe_analyzer_shared:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _fe_analyzer_shared
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "28.0.0"
|
||||||
|
analyzer:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: analyzer
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.0"
|
||||||
|
args:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.0"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.8.2"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.4"
|
||||||
|
collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.15.0"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
coverage:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: coverage
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.2"
|
||||||
|
frontend_server_client:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: frontend_server_client
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
glob:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: glob
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
http_multi_server:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_multi_server
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.0"
|
||||||
|
indent:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: indent
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
io:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: io
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.3"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.3"
|
||||||
|
lints:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: lints
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
logging:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logging
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.2"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.11"
|
||||||
|
meta:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.7.0"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
node_preamble:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: node_preamble
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
package_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_config
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.2"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.0"
|
||||||
|
pool:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pool
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.0"
|
||||||
|
pub_semver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pub_semver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
shelf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
shelf_packages_handler:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_packages_handler
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
|
shelf_static:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_static
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
shelf_web_socket:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shelf_web_socket
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
source_map_stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_map_stack_trace
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
source_maps:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_maps
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.10.10"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.8.1"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.10.0"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
|
test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: test
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.18.2"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.5"
|
||||||
|
test_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_core
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.5"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.0"
|
||||||
|
vm_service:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vm_service
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "7.3.0"
|
||||||
|
watcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: watcher
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
web_socket_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: web_socket_channel
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
webkit_inspection_protocol:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webkit_inspection_protocol
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
|
sdks:
|
||||||
|
dart: ">=2.14.3 <3.0.0"
|
14
pubspec.yaml
Normal file
14
pubspec.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: dcat
|
||||||
|
description: Concatenate file(s) to standard output.
|
||||||
|
version: 1.0.0
|
||||||
|
homepage: https://github.com/ethauvin/dcat
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.14.3 <3.0.0'
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
lints: ^1.0.0
|
||||||
|
test: ^1.18.2
|
||||||
|
dependencies:
|
||||||
|
args: ^2.3.0
|
||||||
|
indent: ^2.0.0
|
102
test/dcat_test.dart
Normal file
102
test/dcat_test.dart
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import '../bin/dcat.dart' as dcat;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
final List<String> log = [];
|
||||||
|
int exitCode;
|
||||||
|
|
||||||
|
test('Test Help', () async {
|
||||||
|
expect(dcat.main(['-h']), completion(equals(0)));
|
||||||
|
expect(dcat.main(['--help']), completion(equals(0)));
|
||||||
|
exitCode = await dcat.main(['-h']);
|
||||||
|
expect(exitCode, equals(dcat.exitSuccess));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test --version', () async {
|
||||||
|
expect(dcat.main(['--version']), completion(equals(0)));
|
||||||
|
exitCode = await dcat.main(['--version']);
|
||||||
|
expect(exitCode, equals(dcat.exitSuccess));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test directory', () async {
|
||||||
|
exitCode = await dcat.main(['bin']);
|
||||||
|
expect(exitCode, equals(dcat.exitFailure));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test missing file', () async {
|
||||||
|
exitCode = await dcat.main(['foo']);
|
||||||
|
expect(exitCode, equals(dcat.exitFailure), reason: 'foo not found');
|
||||||
|
exitCode = await dcat.main(['bin/dcat.dart', 'foo']);
|
||||||
|
expect(exitCode, equals(dcat.exitFailure), reason: 'one missing file');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat source', () async {
|
||||||
|
await dcat.cat(['bin/dcat.dart'], log: log);
|
||||||
|
expect(log.isEmpty, false, reason: 'log is empty');
|
||||||
|
expect(log.first, startsWith('// Copyright (c)'), reason: 'has copyright');
|
||||||
|
expect(log.last, equals('}'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat -n source', () async {
|
||||||
|
exitCode =
|
||||||
|
await dcat.cat(['bin/dcat.dart'], log: log, showLineNumbers: true);
|
||||||
|
expect(exitCode, 0, reason: 'result code is 0');
|
||||||
|
expect(log.first, startsWith('1: // Copyright (c)'),
|
||||||
|
reason: 'has copyright');
|
||||||
|
expect(log.last, endsWith(': }'), reason: 'last line');
|
||||||
|
for (final String line in log) {
|
||||||
|
expect(line, matches('^\\d+: .*'), reason: 'has line number');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat -E', () async {
|
||||||
|
await dcat.cat(['test/test.txt'], log: log, showEnds: true);
|
||||||
|
var hasBlank = false;
|
||||||
|
for (final String line in log) {
|
||||||
|
expect(line, endsWith('\$'));
|
||||||
|
if (line == '\$') {
|
||||||
|
hasBlank = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(hasBlank, true, reason: 'has blank line');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat -bE', () async {
|
||||||
|
await dcat
|
||||||
|
.cat(['test/test.txt'], log: log, numberNonBlank: true, showEnds: true);
|
||||||
|
var hasBlank = false;
|
||||||
|
for (final String line in log) {
|
||||||
|
expect(line, endsWith('\$'));
|
||||||
|
if (line.contains(RegExp(r'^\d+: .*\$$'))) {
|
||||||
|
hasBlank = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(hasBlank, true, reason: 'has blank line');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat -T', () async {
|
||||||
|
await dcat.cat(['test/test.txt'], log: log, showTabs: true);
|
||||||
|
var hasTab = false;
|
||||||
|
for (final String line in log) {
|
||||||
|
if (line.startsWith('^I')) {
|
||||||
|
hasTab = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(hasTab, true, reason: 'has tab');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Test cat -s', () async {
|
||||||
|
await dcat.cat(['test/test.txt'], log: log, squeezeBlank: true);
|
||||||
|
var hasSqueeze = true;
|
||||||
|
var prevLine = 'foo';
|
||||||
|
for (final String line in log) {
|
||||||
|
if (line == prevLine) {
|
||||||
|
hasSqueeze = false;
|
||||||
|
}
|
||||||
|
prevLine = line;
|
||||||
|
}
|
||||||
|
expect(hasSqueeze, true, reason: 'has squeeze');
|
||||||
|
});
|
||||||
|
}
|
7
test/test.txt
Normal file
7
test/test.txt
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||||
|
|
||||||
|
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||||
|
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||||
|
|
||||||
|
|
||||||
|
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
Loading…
Add table
Add a link
Reference in a new issue