Added show non-printing option.
This commit is contained in:
parent
4948aaa970
commit
9397ebaa37
14 changed files with 316 additions and 298 deletions
27
README.md
27
README.md
|
@ -5,6 +5,10 @@
|
|||
|
||||
A **cat** command-line implemenation in [Dart](https://dart.dev/), inspired by the [Write command-line apps sample code](https://dart.dev/tutorials/server/cmdline).
|
||||
|
||||
## Synopsis
|
||||
|
||||
**dcat** copies each file, or standard input if none are given, to standard output.
|
||||
|
||||
## Command-Line Usage
|
||||
|
||||
```sh
|
||||
|
@ -16,19 +20,23 @@ Concatenate FILE(s) to standard output.
|
|||
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
||||
-b, --number-nonblank number nonempty output lines, overrides -n
|
||||
-E, --show-ends display $ at end of each line
|
||||
-h, --help display this help and exit
|
||||
-n, --number number all output lines
|
||||
-T, --show-tabs display TAB characters as ^I
|
||||
-s, --squeeze-blank suppress repeated empty output lines
|
||||
--version output version information and exit
|
||||
-A, --show-all equivalent to -vET
|
||||
-b, --number-nonblank number nonempty output lines, overrides -n
|
||||
-e, --show-nonprinting-ends equivalent to -vE
|
||||
-E, --show-ends display $ at end of each line
|
||||
-h, --help display this help and exit
|
||||
-n, --number number all output lines
|
||||
-t, --show-nonprinting-tabs equivalent to -vT
|
||||
-T, --show-tabs display TAB characters as ^I
|
||||
-s, --squeeze-blank suppress repeated empty output lines
|
||||
--version output version information and exit
|
||||
-v, --show-nonprinting use ^ and M- notation, except for LFD and TAB
|
||||
|
||||
Examples:
|
||||
dcat f - g Output f's contents, then standard input, then g's contents.
|
||||
dcat Copy standard input to standard output.
|
||||
```
|
||||
## Compile Application
|
||||
## Compile Standalone Application
|
||||
|
||||
### *nix
|
||||
```sh
|
||||
|
@ -42,4 +50,5 @@ dart compile exe bin/dcat.dart
|
|||
|
||||
## Differences from [GNU cat](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation)
|
||||
- No binary file support.
|
||||
- Line numbers are printed as `X:` where `X` is the line number.
|
||||
- A line is considered terminated by either a `CR` (carriage return), a `LF` (line feed), a `CR+LF` sequence (DOS line ending).
|
||||
- The non-printing `M-^?` notation is always used for unicode characters.
|
|
@ -8,33 +8,43 @@ import 'package:args/args.dart';
|
|||
import 'package:dcat/dcat.dart';
|
||||
import 'package:indent/indent.dart';
|
||||
|
||||
const appName = libName;
|
||||
const appName = 'dcat';
|
||||
const appVersion = '1.0.0';
|
||||
const helpFlag = 'help';
|
||||
const nonBlankFlag = 'number-nonblank';
|
||||
const numberFlag = 'number';
|
||||
const showAllFlag = 'show-all';
|
||||
const showEndsFlag = 'show-ends';
|
||||
const showNonPrintingEndsFlag = 'show-nonprinting-ends';
|
||||
const showNonPrintingFlag = 'show-nonprinting';
|
||||
const showNonPrintingTabsFlag = 'show-nonprinting-tabs';
|
||||
const showTabsFlag = 'show-tabs';
|
||||
const squeezeBlank = 'squeeze-blank';
|
||||
const versionFlag = 'version';
|
||||
|
||||
/// Concatenates files specified in [arguments].
|
||||
///
|
||||
/// Usage: `dcat [OPTION]... [FILE]...`
|
||||
/// Usage: `dcat [option] [file]…`
|
||||
Future<int> main(List<String> arguments) async {
|
||||
final parser = ArgParser();
|
||||
Future<int> returnCode;
|
||||
exitCode = exitSuccess;
|
||||
parser.addFlag(showAllFlag,
|
||||
negatable: false, abbr: 'A', help: 'equivalent to -vET');
|
||||
parser.addFlag(nonBlankFlag,
|
||||
negatable: false,
|
||||
abbr: 'b',
|
||||
help: 'number nonempty output lines, overrides -n');
|
||||
parser.addFlag(showNonPrintingEndsFlag,
|
||||
negatable: false, abbr: 'e', help: 'equivalent to -vE');
|
||||
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(showNonPrintingTabsFlag,
|
||||
negatable: false, abbr: 't', help: 'equivalent to -vT');
|
||||
parser.addFlag(showTabsFlag,
|
||||
negatable: false, abbr: 'T', help: 'display TAB characters as ^I');
|
||||
parser.addFlag(squeezeBlank,
|
||||
|
@ -43,6 +53,11 @@ Future<int> main(List<String> arguments) async {
|
|||
help: 'suppress repeated empty output lines');
|
||||
parser.addFlag(versionFlag,
|
||||
negatable: false, help: 'output version information and exit');
|
||||
parser.addFlag('ignored', negatable: false, hide: true, abbr: 'u');
|
||||
parser.addFlag(showNonPrintingFlag,
|
||||
negatable: false,
|
||||
abbr: 'v',
|
||||
help: 'use ^ and M- notation, except for LFD and TAB');
|
||||
|
||||
final ArgResults argResults;
|
||||
try {
|
||||
|
@ -59,12 +74,30 @@ Future<int> main(List<String> arguments) async {
|
|||
returnCode = printVersion();
|
||||
} else {
|
||||
final paths = argResults.rest;
|
||||
var showEnds = argResults[showEndsFlag];
|
||||
var showTabs = argResults[showTabsFlag];
|
||||
var showNonPrinting = argResults[showNonPrintingFlag];
|
||||
|
||||
if (argResults[showNonPrintingEndsFlag]) {
|
||||
showNonPrinting = showEnds = true;
|
||||
}
|
||||
|
||||
if (argResults[showNonPrintingTabsFlag]) {
|
||||
showNonPrinting = showTabs = true;
|
||||
}
|
||||
|
||||
if (argResults[showAllFlag]) {
|
||||
showNonPrinting = showEnds = showTabs = true;
|
||||
}
|
||||
|
||||
returnCode = cat(paths,
|
||||
showEnds: argResults[showEndsFlag],
|
||||
appName: appName,
|
||||
showEnds: showEnds,
|
||||
showLineNumbers: argResults[numberFlag],
|
||||
numberNonBlank: argResults[nonBlankFlag],
|
||||
showTabs: argResults[showTabsFlag],
|
||||
squeezeBlank: argResults[squeezeBlank]);
|
||||
showTabs: showTabs,
|
||||
squeezeBlank: argResults[squeezeBlank],
|
||||
showNonPrinting: showNonPrinting);
|
||||
}
|
||||
|
||||
exitCode = await returnCode;
|
||||
|
@ -76,7 +109,7 @@ 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>
|
||||
|
||||
|
||||
Inspired by <https://dart.dev/tutorials/server/cmdline>
|
||||
Written by Erik C. Thauvin <https://erik.thauvin.net/>''');
|
||||
return exitSuccess;
|
||||
|
@ -93,7 +126,7 @@ ${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>''');
|
||||
|
||||
Source and documentation: <https://github.com/ethauvin/dcat>''');
|
||||
return exitSuccess;
|
||||
}
|
||||
|
|
|
@ -54,12 +54,14 @@
|
|||
|
||||
<span class="returntype"><a href="https://api.dart.dev/stable/2.14.3/dart-async/Future-class.html">Future</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/int-class.html">int</a></span>></span></span>
|
||||
<span class="name ">cat</span>(<wbr><ol class="parameter-list"><li><span class="parameter" id="cat-param-paths"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span></span> <span class="parameter-name">paths</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-log">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span>?</span> <span class="parameter-name">log</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">''</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-log"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span>?</span> <span class="parameter-name">log</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-showEnds"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showEnds</span> = <span class="default-value">false</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-numberNonBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">numberNonBlank</span> = <span class="default-value">false</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-showLineNumbers"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showLineNumbers</span> = <span class="default-value">false</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-showTabs"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showTabs</span> = <span class="default-value">false</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-squeezeBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">squeezeBlank</span> = <span class="default-value">false</span>}</span></li>
|
||||
<li><span class="parameter" id="cat-param-squeezeBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">squeezeBlank</span> = <span class="default-value">false</span>, </span></li>
|
||||
<li><span class="parameter" id="cat-param-showNonPrinting"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showNonPrinting</span> = <span class="default-value">false</span>}</span></li>
|
||||
</ol>)
|
||||
|
||||
</section>
|
||||
|
@ -67,7 +69,7 @@
|
|||
<section class="desc markdown">
|
||||
<p>Concatenates files in <code>paths</code> to <a href="https://api.dart.dev/stable/2.14.3/dart-io/stdout.html">stdout</a></p>
|
||||
<p>The parameters are similar to the <a href="https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation">GNU cat utility</a>.
|
||||
Specify a <code>log</code> for debugging purpose.</p>
|
||||
Specify a <code>log</code> for debugging or testing purpose.</p>
|
||||
</section>
|
||||
|
||||
|
||||
|
@ -75,19 +77,21 @@ Specify a <code>log</code> for debugging purpose.</p>
|
|||
<section class="summary source-code" id="source">
|
||||
<h2><span>Implementation</span></h2>
|
||||
<pre class="language-dart"><code class="language-dart">Future<int> cat(List<String> paths,
|
||||
{List<String>? log,
|
||||
{String appName = '',
|
||||
List<String>? log,
|
||||
bool showEnds = false,
|
||||
bool numberNonBlank = false,
|
||||
bool showLineNumbers = false,
|
||||
bool showTabs = false,
|
||||
bool squeezeBlank = false}) async {
|
||||
bool squeezeBlank = false,
|
||||
bool showNonPrinting = 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);
|
||||
numberNonBlank, showTabs, squeezeBlank, showNonPrinting);
|
||||
} else {
|
||||
for (final path in paths) {
|
||||
try {
|
||||
|
@ -99,8 +103,16 @@ Specify a <code>log</code> for debugging purpose.</p>
|
|||
.bind(File(path).openRead())
|
||||
.transform(const LineSplitter());
|
||||
}
|
||||
lineNumber = await _writeLines(lines, lineNumber, log, showEnds,
|
||||
showLineNumbers, numberNonBlank, showTabs, squeezeBlank);
|
||||
lineNumber = await _writeLines(
|
||||
lines,
|
||||
lineNumber,
|
||||
log,
|
||||
showEnds,
|
||||
showLineNumbers,
|
||||
numberNonBlank,
|
||||
showTabs,
|
||||
squeezeBlank,
|
||||
showNonPrinting);
|
||||
} on FileSystemException catch (e) {
|
||||
final String? osMessage = e.osError?.message;
|
||||
final String message;
|
||||
|
@ -109,11 +121,13 @@ Specify a <code>log</code> for debugging purpose.</p>
|
|||
} else {
|
||||
message = e.message;
|
||||
}
|
||||
returnCode = await printError(message, path: path);
|
||||
returnCode = await printError(message, appName: appName, path: path);
|
||||
} on FormatException {
|
||||
returnCode = await printError('Binary file not supported.', path: path);
|
||||
returnCode = await printError('Binary file not supported.',
|
||||
appName: appName, path: path);
|
||||
} catch (e) {
|
||||
returnCode = await printError(e.toString(), path: path);
|
||||
returnCode =
|
||||
await printError(e.toString(), appName: appName, path: path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +160,6 @@ Specify a <code>log</code> for debugging purpose.</p>
|
|||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
|
|
|
@ -49,6 +49,9 @@
|
|||
</h1></div>
|
||||
|
||||
|
||||
<section class="desc markdown">
|
||||
<p>Library to concatenate file(s) to standard output,</p>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
@ -88,21 +91,6 @@
|
|||
</div>
|
||||
</dd>
|
||||
|
||||
<dt id="libName" class="constant">
|
||||
<span class="name "><a href="../dcat/libName-constant.html">libName</a></span>
|
||||
<span class="signature">→ const <a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>
|
||||
|
||||
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<span class="signature"><code>'dcat'</code></span>
|
||||
</div>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
|
@ -112,7 +100,7 @@
|
|||
|
||||
<dl class="callables">
|
||||
<dt id="cat" class="callable">
|
||||
<span class="name"><a href="../dcat/cat.html">cat</a></span><span class="signature">(<wbr><span class="parameter" id="cat-param-paths"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span></span> <span class="parameter-name">paths</span>, </span><span class="parameter" id="cat-param-log">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span>?</span> <span class="parameter-name">log</span>, </span><span class="parameter" id="cat-param-showEnds"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showEnds</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-numberNonBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">numberNonBlank</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-showLineNumbers"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showLineNumbers</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-showTabs"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showTabs</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-squeezeBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">squeezeBlank</span> = <span class="default-value">false</span>}</span>)
|
||||
<span class="name"><a href="../dcat/cat.html">cat</a></span><span class="signature">(<wbr><span class="parameter" id="cat-param-paths"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span></span> <span class="parameter-name">paths</span>, </span><span class="parameter" id="cat-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">''</span>, </span><span class="parameter" id="cat-param-log"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/List-class.html">List</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span>></span>?</span> <span class="parameter-name">log</span>, </span><span class="parameter" id="cat-param-showEnds"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showEnds</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-numberNonBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">numberNonBlank</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-showLineNumbers"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showLineNumbers</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-showTabs"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showTabs</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-squeezeBlank"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">squeezeBlank</span> = <span class="default-value">false</span>, </span><span class="parameter" id="cat-param-showNonPrinting"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/bool-class.html">bool</a></span> <span class="parameter-name">showNonPrinting</span> = <span class="default-value">false</span>}</span>)
|
||||
<span class="returntype parameter">→ <a href="https://api.dart.dev/stable/2.14.3/dart-async/Future-class.html">Future</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/int-class.html">int</a></span>></span></span>
|
||||
</span>
|
||||
|
||||
|
@ -125,7 +113,7 @@
|
|||
</dd>
|
||||
|
||||
<dt id="printError" class="callable">
|
||||
<span class="name"><a href="../dcat/printError.html">printError</a></span><span class="signature">(<wbr><span class="parameter" id="printError-param-message"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">message</span>, </span><span class="parameter" id="printError-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">libName</span>, </span><span class="parameter" id="printError-param-path"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">path</span> = <span class="default-value">''</span>}</span>)
|
||||
<span class="name"><a href="../dcat/printError.html">printError</a></span><span class="signature">(<wbr><span class="parameter" id="printError-param-message"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">message</span>, </span><span class="parameter" id="printError-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">''</span>, </span><span class="parameter" id="printError-param-path"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">path</span> = <span class="default-value">''</span>}</span>)
|
||||
<span class="returntype parameter">→ <a href="https://api.dart.dev/stable/2.14.3/dart-async/Future-class.html">Future</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/int-class.html">int</a></span>></span></span>
|
||||
</span>
|
||||
|
||||
|
@ -175,7 +163,6 @@
|
|||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
|
|
|
@ -1,129 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, user-scalable=no">
|
||||
<meta name="description" content="API docs for the libName constant from the dcat library, for the Dart programming language.">
|
||||
<title>libName constant - dcat library - Dart API</title>
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="../static-assets/github.css?v1">
|
||||
<link rel="stylesheet" href="../static-assets/styles.css?v1">
|
||||
<link rel="icon" href="../static-assets/favicon.png?v1">
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
<body data-base-href="../"
|
||||
data-using-base-href="false">
|
||||
|
||||
<div id="overlay-under-drawer"></div>
|
||||
|
||||
<header id="title">
|
||||
<button id="sidenav-left-toggle" type="button"> </button>
|
||||
<ol class="breadcrumbs gt-separated dark hidden-xs">
|
||||
<li><a href="../index.html">dcat</a></li>
|
||||
<li><a href="../dcat/dcat-library.html">dcat</a></li>
|
||||
<li class="self-crumb">libName constant</li>
|
||||
</ol>
|
||||
<div class="self-name">libName</div>
|
||||
<form class="search navbar-right" role="search">
|
||||
<input type="text" id="search-box" autocomplete="off" disabled class="form-control typeahead" placeholder="Loading search...">
|
||||
</form>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
|
||||
|
||||
<div id="dartdoc-main-content" class="main-content">
|
||||
<div>
|
||||
<h1><span class="kind-top-level-property">libName</span> top-level constant
|
||||
<a href="https://dart.dev/null-safety" class="feature feature-null-safety" title="Supports the null safety language feature.">Null safety</a>
|
||||
|
||||
</h1></div>
|
||||
|
||||
<section class="multi-line-signature">
|
||||
<a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a>
|
||||
const <span class="name ">libName</span>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section class="summary source-code" id="source">
|
||||
<h2><span>Implementation</span></h2>
|
||||
<pre class="language-dart"><code class="language-dart">const libName = 'dcat';</code></pre>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</div> <!-- /.main-content -->
|
||||
|
||||
<div id="dartdoc-sidebar-left" class="sidebar sidebar-offcanvas-left">
|
||||
<header id="header-search-sidebar" class="hidden-l">
|
||||
<form class="search-sidebar" role="search">
|
||||
<input type="text" id="search-sidebar" autocomplete="off" disabled class="form-control typeahead" placeholder="Loading search...">
|
||||
</form>
|
||||
</header>
|
||||
|
||||
<ol class="breadcrumbs gt-separated dark hidden-l" id="sidebar-nav">
|
||||
<li><a href="../index.html">dcat</a></li>
|
||||
<li><a href="../dcat/dcat-library.html">dcat</a></li>
|
||||
<li class="self-crumb">libName constant</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h5>dcat library</h5>
|
||||
<ol>
|
||||
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
<li><a href="../dcat/cat.html">cat</a></li>
|
||||
<li><a href="../dcat/printError.html">printError</a></li>
|
||||
|
||||
|
||||
|
||||
</ol>
|
||||
|
||||
</div><!--/.sidebar-offcanvas-left-->
|
||||
|
||||
<div id="dartdoc-sidebar-right" class="sidebar sidebar-offcanvas-right">
|
||||
</div><!--/.sidebar-offcanvas-->
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<span class="no-break">
|
||||
dcat
|
||||
1.0.0
|
||||
</span>
|
||||
|
||||
|
||||
</footer>
|
||||
|
||||
|
||||
|
||||
<script src="../static-assets/highlight.pack.js?v1"></script>
|
||||
<script src="../static-assets/script.js?v1"></script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
<span class="returntype"><a href="https://api.dart.dev/stable/2.14.3/dart-async/Future-class.html">Future</a><span class="signature"><<wbr><span class="type-parameter"><a href="https://api.dart.dev/stable/2.14.3/dart-core/int-class.html">int</a></span>></span></span>
|
||||
<span class="name ">printError</span>(<wbr><ol class="parameter-list"><li><span class="parameter" id="printError-param-message"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">message</span>, </span></li>
|
||||
<li><span class="parameter" id="printError-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">libName</span>, </span></li>
|
||||
<li><span class="parameter" id="printError-param-appName">{<span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">appName</span> = <span class="default-value">''</span>, </span></li>
|
||||
<li><span class="parameter" id="printError-param-path"><span class="type-annotation"><a href="https://api.dart.dev/stable/2.14.3/dart-core/String-class.html">String</a></span> <span class="parameter-name">path</span> = <span class="default-value">''</span>}</span></li>
|
||||
</ol>)
|
||||
|
||||
|
@ -69,12 +69,14 @@
|
|||
<section class="summary source-code" id="source">
|
||||
<h2><span>Implementation</span></h2>
|
||||
<pre class="language-dart"><code class="language-dart">Future<int> printError(String message,
|
||||
{String appName = libName, String path = ''}) async {
|
||||
if (path.isNotEmpty) {
|
||||
stderr.writeln('$libName: $path: $message');
|
||||
} else {
|
||||
stderr.write('$libName: $message');
|
||||
{String appName = '', String path = ''}) async {
|
||||
if (appName.isNotEmpty) {
|
||||
stderr.write('$appName: ');
|
||||
}
|
||||
if (path.isNotEmpty) {
|
||||
stderr.write('$path: ');
|
||||
}
|
||||
stderr.writeln(message);
|
||||
return exitFailure;
|
||||
}</code></pre>
|
||||
</section>
|
||||
|
@ -104,7 +106,6 @@
|
|||
<li class="section-title"><a href="../dcat/dcat-library.html#constants">Constants</a></li>
|
||||
<li><a href="../dcat/exitFailure-constant.html">exitFailure</a></li>
|
||||
<li><a href="../dcat/exitSuccess-constant.html">exitSuccess</a></li>
|
||||
<li><a href="../dcat/libName-constant.html">libName</a></li>
|
||||
|
||||
|
||||
<li class="section-title"><a href="../dcat/dcat-library.html#functions">Functions</a></li>
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
<a href="https://github.com/ethauvin/dcat/actions/workflows/dart.yml"><img src="https://github.com/ethauvin/dcat/actions/workflows/dart.yml/badge.svg" alt="GitHub CI"></a></p>
|
||||
<h1 id="dcat-concatenate-files-to-standard-output">dcat: Concatenate File(s) to Standard Output</h1>
|
||||
<p>A <strong>cat</strong> command-line implemenation in <a href="https://dart.dev/">Dart</a>, inspired by the <a href="https://dart.dev/tutorials/server/cmdline">Write command-line apps sample code</a>.</p>
|
||||
<h2 id="synopsis">Synopsis</h2>
|
||||
<p><strong>dcat</strong> copies each file, or standard input if none are given, to standard output.</p>
|
||||
<h2 id="command-line-usage">Command-Line Usage</h2>
|
||||
<pre class="language-sh"><code class="language-sh">dcat --help
|
||||
</code></pre>
|
||||
|
@ -56,19 +58,23 @@ Concatenate FILE(s) to standard output.
|
|||
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
||||
-b, --number-nonblank number nonempty output lines, overrides -n
|
||||
-E, --show-ends display $ at end of each line
|
||||
-h, --help display this help and exit
|
||||
-n, --number number all output lines
|
||||
-T, --show-tabs display TAB characters as ^I
|
||||
-s, --squeeze-blank suppress repeated empty output lines
|
||||
--version output version information and exit
|
||||
-A, --show-all equivalent to -vET
|
||||
-b, --number-nonblank number nonempty output lines, overrides -n
|
||||
-e, --show-nonprinting-ends equivalent to -vE
|
||||
-E, --show-ends display $ at end of each line
|
||||
-h, --help display this help and exit
|
||||
-n, --number number all output lines
|
||||
-t, --show-nonprinting-tabs equivalent to -vT
|
||||
-T, --show-tabs display TAB characters as ^I
|
||||
-s, --squeeze-blank suppress repeated empty output lines
|
||||
--version output version information and exit
|
||||
-v, --show-nonprinting use ^ and M- notation, except for LFD and TAB
|
||||
|
||||
Examples:
|
||||
dcat f - g Output f's contents, then standard input, then g's contents.
|
||||
dcat Copy standard input to standard output.
|
||||
</code></pre>
|
||||
<h2 id="compile-application">Compile Application</h2>
|
||||
<h2 id="compile-standalone-application">Compile Standalone Application</h2>
|
||||
<h3 id="nix">*nix</h3>
|
||||
<pre class="language-sh"><code class="language-sh">dart compile exe -o bin/dcat bin/dcat.dart
|
||||
</code></pre>
|
||||
|
@ -78,7 +84,8 @@ Examples:
|
|||
<h2 id="differences-from-gnu-cathttpswwwgnuorgsoftwarecoreutilsmanualhtml_nodecat-invocationhtmlcat-invocation">Differences from <a href="https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation">GNU cat</a></h2>
|
||||
<ul>
|
||||
<li>No binary file support.</li>
|
||||
<li>Line numbers are printed as <code>X:</code> where <code>X</code> is the line number.</li>
|
||||
<li>A line is considered terminated by either a <code>CR</code> (carriage return), a <code>LF</code> (line feed), a <code>CR+LF</code> sequence (DOS line ending).</li>
|
||||
<li>The non-printing <code>M-^?</code> notation is always used for unicode characters.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
@ -90,7 +97,7 @@ Examples:
|
|||
<span class="name"><a href="dcat/dcat-library.html">dcat</a></span>
|
||||
|
||||
</dt>
|
||||
<dd>
|
||||
<dd>Library to concatenate file(s) to standard output,
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
|
|
|
@ -1 +1 @@
|
|||
[{"name":"dcat","qualifiedName":"dcat","href":"dcat/dcat-library.html","type":"library","overriddenDepth":0,"packageName":"dcat"},{"name":"cat","qualifiedName":"dcat.cat","href":"dcat/cat.html","type":"function","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"exitFailure","qualifiedName":"dcat.exitFailure","href":"dcat/exitFailure-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"exitSuccess","qualifiedName":"dcat.exitSuccess","href":"dcat/exitSuccess-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"libName","qualifiedName":"dcat.libName","href":"dcat/libName-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"printError","qualifiedName":"dcat.printError","href":"dcat/printError.html","type":"function","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}}]
|
||||
[{"name":"dcat","qualifiedName":"dcat","href":"dcat/dcat-library.html","type":"library","overriddenDepth":0,"packageName":"dcat"},{"name":"cat","qualifiedName":"dcat.cat","href":"dcat/cat.html","type":"function","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"exitFailure","qualifiedName":"dcat.exitFailure","href":"dcat/exitFailure-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"exitSuccess","qualifiedName":"dcat.exitSuccess","href":"dcat/exitSuccess-constant.html","type":"top-level constant","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}},{"name":"printError","qualifiedName":"dcat.printError","href":"dcat/printError.html","type":"function","overriddenDepth":0,"packageName":"dcat","enclosedBy":{"name":"dcat","type":"library"}}]
|
||||
|
|
|
@ -2,33 +2,35 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
/// Library to concatenate file(s) to standard output,
|
||||
library dcat;
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
const libName = 'dcat';
|
||||
const exitFailure = 1;
|
||||
const exitSuccess = 0;
|
||||
|
||||
/// Concatenates files in [paths] to [stdout]
|
||||
///
|
||||
/// The parameters are similar to the [GNU cat utility](https://www.gnu.org/software/coreutils/manual/html_node/cat-invocation.html#cat-invocation).
|
||||
/// Specify a [log] for debugging purpose.
|
||||
/// Specify a [log] for debugging or testing purpose.
|
||||
Future<int> cat(List<String> paths,
|
||||
{List<String>? log,
|
||||
{String appName = '',
|
||||
List<String>? log,
|
||||
bool showEnds = false,
|
||||
bool numberNonBlank = false,
|
||||
bool showLineNumbers = false,
|
||||
bool showTabs = false,
|
||||
bool squeezeBlank = false}) async {
|
||||
bool squeezeBlank = false,
|
||||
bool showNonPrinting = 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);
|
||||
numberNonBlank, showTabs, squeezeBlank, showNonPrinting);
|
||||
} else {
|
||||
for (final path in paths) {
|
||||
try {
|
||||
|
@ -40,8 +42,16 @@ Future<int> cat(List<String> paths,
|
|||
.bind(File(path).openRead())
|
||||
.transform(const LineSplitter());
|
||||
}
|
||||
lineNumber = await _writeLines(lines, lineNumber, log, showEnds,
|
||||
showLineNumbers, numberNonBlank, showTabs, squeezeBlank);
|
||||
lineNumber = await _writeLines(
|
||||
lines,
|
||||
lineNumber,
|
||||
log,
|
||||
showEnds,
|
||||
showLineNumbers,
|
||||
numberNonBlank,
|
||||
showTabs,
|
||||
squeezeBlank,
|
||||
showNonPrinting);
|
||||
} on FileSystemException catch (e) {
|
||||
final String? osMessage = e.osError?.message;
|
||||
final String message;
|
||||
|
@ -50,25 +60,63 @@ Future<int> cat(List<String> paths,
|
|||
} else {
|
||||
message = e.message;
|
||||
}
|
||||
returnCode = await printError(message, path: path);
|
||||
returnCode = await printError(message, appName: appName, path: path);
|
||||
} on FormatException {
|
||||
returnCode = await printError('Binary file not supported.', path: path);
|
||||
returnCode = await printError('Binary file not supported.',
|
||||
appName: appName, path: path);
|
||||
} catch (e) {
|
||||
returnCode = await printError(e.toString(), path: path);
|
||||
returnCode =
|
||||
await printError(e.toString(), appName: appName, path: path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
/// Parses line with non-printing characters.
|
||||
Future<String> _parseNonPrinting(String line, bool showTabs) async {
|
||||
final sb = StringBuffer();
|
||||
for (var ch in line.runes) {
|
||||
if (ch >= 32) {
|
||||
if (ch < 127) {
|
||||
sb.writeCharCode(ch);
|
||||
} else if (ch == 127) {
|
||||
sb.write('^?');
|
||||
} else {
|
||||
sb.write('M-');
|
||||
if (ch >= 128 + 32) {
|
||||
if (ch < 128 + 127) {
|
||||
sb.writeCharCode(ch - 128);
|
||||
} else {
|
||||
sb.write('^?');
|
||||
}
|
||||
} else {
|
||||
sb
|
||||
..write('^')
|
||||
..writeCharCode(ch - 128 + 64);
|
||||
}
|
||||
}
|
||||
} else if (ch == 9 && !showTabs) {
|
||||
sb.write('\t');
|
||||
} else {
|
||||
sb
|
||||
..write('^')
|
||||
..writeCharCode(ch + 64);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/// Prints the [appName], [path] and error [message] to [stderr].
|
||||
Future<int> printError(String message,
|
||||
{String appName = libName, String path = ''}) async {
|
||||
if (path.isNotEmpty) {
|
||||
stderr.writeln('$libName: $path: $message');
|
||||
} else {
|
||||
stderr.write('$libName: $message');
|
||||
{String appName = '', String path = ''}) async {
|
||||
if (appName.isNotEmpty) {
|
||||
stderr.write('$appName: ');
|
||||
}
|
||||
if (path.isNotEmpty) {
|
||||
stderr.write('$path: ');
|
||||
}
|
||||
stderr.writeln(message);
|
||||
return exitFailure;
|
||||
}
|
||||
|
||||
|
@ -83,7 +131,8 @@ Future<int> _writeLines(Stream<String> lines, int lineNumber,
|
|||
bool showLineNumbers = false,
|
||||
bool showNonBlank = false,
|
||||
bool showTabs = false,
|
||||
bool squeezeBlank = false]) async {
|
||||
bool squeezeBlank = false,
|
||||
bool showNonPrinting = false]) async {
|
||||
var emptyLine = 0;
|
||||
final sb = StringBuffer();
|
||||
await for (final line in lines) {
|
||||
|
@ -95,14 +144,18 @@ Future<int> _writeLines(Stream<String> lines, int lineNumber,
|
|||
} else {
|
||||
emptyLine = 0;
|
||||
}
|
||||
if (showNonBlank || showLineNumbers) {
|
||||
sb.write('${lineNumber++}: ');
|
||||
if (showLineNumbers || (showNonBlank && line.isNotEmpty)) {
|
||||
sb.write('${lineNumber++} '.padLeft(8));
|
||||
}
|
||||
if (showTabs) {
|
||||
|
||||
if (showNonPrinting) {
|
||||
sb.write(await _parseNonPrinting(line, showTabs));
|
||||
} else if (showTabs) {
|
||||
sb.write(line.replaceAll('\t', '^I'));
|
||||
} else {
|
||||
sb.write(line);
|
||||
}
|
||||
|
||||
if (showEnds) {
|
||||
sb.write('\$');
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ environment:
|
|||
dev_dependencies:
|
||||
lints: ^1.0.0
|
||||
test: ^1.18.2
|
||||
dependencies:
|
||||
dependencies:
|
||||
args: ^2.3.0
|
||||
indent: ^2.0.0
|
||||
|
|
|
@ -7,96 +7,139 @@ void main() {
|
|||
final List<String> log = [];
|
||||
int exitCode;
|
||||
|
||||
test('Test Help', () async {
|
||||
expect(app.main(['-h']), completion(equals(0)));
|
||||
expect(app.main(['--help']), completion(equals(0)));
|
||||
exitCode = await app.main(['-h']);
|
||||
expect(exitCode, equals(exitSuccess));
|
||||
group('app', () {
|
||||
test('Test Help', () async {
|
||||
expect(app.main(['-h']), completion(equals(0)));
|
||||
expect(app.main(['--help']), completion(equals(0)));
|
||||
exitCode = await app.main(['-h']);
|
||||
expect(exitCode, equals(exitSuccess));
|
||||
});
|
||||
|
||||
test('Test --version', () async {
|
||||
expect(app.main(['--version']), completion(equals(0)));
|
||||
exitCode = await app.main(['--version']);
|
||||
expect(exitCode, equals(exitSuccess));
|
||||
});
|
||||
|
||||
test('Test directory', () async {
|
||||
exitCode = await app.main(['bin']);
|
||||
expect(exitCode, equals(exitFailure));
|
||||
});
|
||||
|
||||
test('Test missing file', () async {
|
||||
exitCode = await app.main(['foo']);
|
||||
expect(exitCode, equals(exitFailure), reason: 'foo not found');
|
||||
exitCode = await app.main(['bin/dcat.dart', 'foo']);
|
||||
expect(exitCode, equals(exitFailure), reason: 'one missing file');
|
||||
});
|
||||
});
|
||||
|
||||
test('Test --version', () async {
|
||||
expect(app.main(['--version']), completion(equals(0)));
|
||||
exitCode = await app.main(['--version']);
|
||||
expect(exitCode, equals(exitSuccess));
|
||||
});
|
||||
group('lib', () {
|
||||
test('Test cat source', () async {
|
||||
await 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 directory', () async {
|
||||
exitCode = await app.main(['bin']);
|
||||
expect(exitCode, equals(exitFailure));
|
||||
});
|
||||
|
||||
test('Test missing file', () async {
|
||||
exitCode = await app.main(['foo']);
|
||||
expect(exitCode, equals(exitFailure), reason: 'foo not found');
|
||||
exitCode = await app.main(['bin/dcat.dart', 'foo']);
|
||||
expect(exitCode, equals(exitFailure), reason: 'one missing file');
|
||||
});
|
||||
|
||||
test('Test cat source', () async {
|
||||
await 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 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 cat(['test/test.txt'], log: log, showEnds: true);
|
||||
var hasBlank = false;
|
||||
for (final String line in log) {
|
||||
expect(line, endsWith('\$'));
|
||||
if (line == '\$') {
|
||||
hasBlank = true;
|
||||
test('Test cat -n source', () async {
|
||||
exitCode = await 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');
|
||||
}
|
||||
}
|
||||
expect(hasBlank, true, reason: 'has blank line');
|
||||
});
|
||||
});
|
||||
|
||||
test('Test cat -bE', () async {
|
||||
await 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 source test', () async {
|
||||
await cat(['bin/dcat.dart', 'test/test.txt'], log: log);
|
||||
expect(log.length, greaterThan(10), reason: 'more than 10 lines');
|
||||
expect(log.first, startsWith('// Copyright'),
|
||||
reason: 'start with copyright');
|
||||
expect(log.last, endsWith('✓'), reason: 'end with checkmark');
|
||||
});
|
||||
|
||||
test('Test cat -T', () async {
|
||||
await cat(['test/test.txt'], log: log, showTabs: true);
|
||||
var hasTab = false;
|
||||
for (final String line in log) {
|
||||
if (line.startsWith('^I')) {
|
||||
hasTab = true;
|
||||
break;
|
||||
test('Test cat -E', () async {
|
||||
await 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(hasTab, true, reason: 'has tab');
|
||||
});
|
||||
expect(hasBlank, true, reason: 'has blank line');
|
||||
expect(log.last, endsWith('✓\$'), reason: 'has unicode');
|
||||
});
|
||||
|
||||
test('Test cat -s', () async {
|
||||
await 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;
|
||||
test('Test cat -bE', () async {
|
||||
await 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;
|
||||
}
|
||||
}
|
||||
prevLine = line;
|
||||
}
|
||||
expect(hasSqueeze, true, reason: 'has squeeze');
|
||||
expect(hasBlank, true, reason: 'has blank line');
|
||||
});
|
||||
|
||||
test('Test cat -T', () async {
|
||||
await 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 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');
|
||||
});
|
||||
|
||||
test('Test cat -A', () async {
|
||||
await cat(['test/test.txt'],
|
||||
log: log, showNonPrinting: true, showEnds: true, showTabs: true);
|
||||
expect(log.last, equals('^I^A^B^C^DM-^?\$'));
|
||||
});
|
||||
|
||||
test('Test cat -t', () async {
|
||||
await cat(['test/test.txt'],
|
||||
log: log, showNonPrinting: true, showTabs: true);
|
||||
expect(log.last, equals('^I^A^B^C^DM-^?'));
|
||||
});
|
||||
|
||||
test('Test cat-Abs', () async {
|
||||
await cat(['test/test.txt'],
|
||||
log: log,
|
||||
showNonPrinting: true,
|
||||
showEnds: true,
|
||||
showTabs: true,
|
||||
numberNonBlank: true,
|
||||
squeezeBlank: true);
|
||||
var blankLines = 0;
|
||||
for (final String line in log) {
|
||||
if (line == '\$') {
|
||||
blankLines++;
|
||||
}
|
||||
}
|
||||
expect(blankLines, 2, reason: 'only 2 blank lines.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,4 +4,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i
|
|||
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