Initial commit.

This commit is contained in:
Erik C. Thauvin 2021-10-09 17:18:56 -07:00
commit 8eb7a7ce99
17 changed files with 913 additions and 0 deletions

88
.gitignore vendored Normal file
View 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
View file

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
## 1.0.0
- Initial version.

29
LICENSE Normal file
View 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
View file

@ -0,0 +1,2 @@
Concatenate file(s) to standard output.

30
analysis_options.yaml Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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.