1646 lines
79 KiB
C#
1646 lines
79 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
using DirectoryService.Utils;
|
|
using FileSystem.Utils;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.ParseNumbers;
|
|
|
|
using Microsoft.Singularity;
|
|
using System.IO;
|
|
|
|
using System.GC;
|
|
using System.Runtime.Remoting;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using System.Diagnostics;
|
|
|
|
using Microsoft.SingSharp;
|
|
using Microsoft.Singularity.Directory;
|
|
using Microsoft.Singularity.V1.Services;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.FileSystem;
|
|
using Microsoft.Singularity.Channels;
|
|
|
|
using Microsoft.Contracts;
|
|
using Microsoft.SingSharp.Reflection;
|
|
using Microsoft.Singularity.Applications;
|
|
using Microsoft.Singularity.Configuration;
|
|
[assembly: Transform(typeof(ApplicationResourceTransform))]
|
|
|
|
namespace Microsoft.Singularity.Applications
|
|
{
|
|
[ConsoleCategory(HelpMessage="Stream Editor", DefaultAction=true)]
|
|
internal class Parameters {
|
|
[InputEndpoint("data")]
|
|
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
|
|
|
|
[OutputEndpoint("data")]
|
|
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
|
|
|
|
[StringParameter( "filename", Mandatory=true, Position=0, HelpMessage="Name of file.")]
|
|
internal string fileName;
|
|
|
|
reflective internal Parameters();
|
|
|
|
internal int AppMain() {
|
|
SEditor.AppMain(this);
|
|
return 0;
|
|
}
|
|
}
|
|
public class SEditor
|
|
{
|
|
internal static void AppMain(Parameters! config)
|
|
{
|
|
// constants
|
|
string EditorName = "SEditor";
|
|
int szLineCount = 0;
|
|
int nIndex = 0;
|
|
|
|
//FOR DEBUG
|
|
// Console.WriteLine("Number of cmd line params = {0}", args.Length);
|
|
|
|
// FOR DEBUG
|
|
// Console.WriteLine("args[1] is {0}", args[1]);
|
|
string filename = config.fileName;
|
|
|
|
string szSrcLine;
|
|
ArrayList szContents = new ArrayList();
|
|
|
|
if (File.Exists(filename)) {
|
|
FileStream fsInput = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
|
StreamReader srInput = new StreamReader(fsInput);
|
|
while ((szSrcLine = srInput.ReadLine()) != null) {
|
|
szContents.Add(szSrcLine);
|
|
// FOR DEBUG
|
|
// Console.WriteLine("{0}", szSrcLine);
|
|
// Console.ReadLine();
|
|
// END DEBUG
|
|
}
|
|
srInput.Close();
|
|
fsInput.Close();
|
|
|
|
// Display number of lines loaded
|
|
szLineCount = szContents.Count;
|
|
Console.WriteLine("* Number of lines read from {0} was {1}", filename, szLineCount);
|
|
|
|
// FOR DEBUG ONLY: display contents of file
|
|
// for (nIndex = 0; nIndex < szContents.Count; nIndex++) {
|
|
// write line to console with numbering
|
|
// Console.WriteLine("{0}: {1}", (nIndex + 1), szContents[nIndex]);
|
|
// }
|
|
}
|
|
else if (System.IO.Directory.Exists(filename)) { // check that it's not a directory
|
|
Console.WriteLine("Exiting: {0} is a directory.", filename);
|
|
Console.WriteLine("Syntax: {0} filename", EditorName);
|
|
return;
|
|
}
|
|
else { // not a directory, but file doesn't exist, so create it
|
|
Console.WriteLine("* Creating new file.");
|
|
}
|
|
|
|
// Command parser - this is the main program loop
|
|
Parser(szContents, nIndex, filename);
|
|
} // end Main
|
|
|
|
|
|
// Parse incoming commands
|
|
static void Parser(ArrayList szArray, int pIndex, string InputFileName)
|
|
{
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* Parser called.");
|
|
// Console.WriteLine("* Current line index is {0}," pIndex);
|
|
Console.Write("* ");
|
|
string ParserInput;
|
|
string ParserInputFirstChar;
|
|
string BackupFileName = "";
|
|
int tempIndex = 0;
|
|
ArrayList tempArray = new ArrayList();
|
|
bool IsTextUpdated = false;
|
|
int tempSize = 0;
|
|
|
|
// build proper backup file name - look for extension if it exists, and replace it with (or add to) ".bak"
|
|
if (Path.HasExtension(InputFileName) && (Path.GetExtension(InputFileName) != ".bak")) { // has an extension other than .bak
|
|
BackupFileName = Path.ChangeExtension(InputFileName, ".bak");
|
|
}
|
|
else if (Path.HasExtension(InputFileName) && (Path.GetExtension(InputFileName) == ".bak")) { // .bak already in use, use something else
|
|
Console.WriteLine("{0} ends in .bak - using .ba2 for backup files...", InputFileName);
|
|
Console.Write("* ");
|
|
BackupFileName = Path.ChangeExtension(InputFileName, ".ba2");
|
|
}
|
|
else { // no extension, so add one
|
|
BackupFileName = InputFileName + ".bak";
|
|
}
|
|
|
|
while (((ParserInput = GetConsoleInput()) != "q") && (ParserInput != "Q") && (ParserInput != null)) {
|
|
if (ParserInput != "") {
|
|
//FOR DEBUG
|
|
//Console.WriteLine("* Input was {0}", ParserInput);
|
|
//Console.Write("* ");
|
|
|
|
// ParserInputFirstChar = Convert.ToString(ParserInput[0]);
|
|
ParserInputFirstChar = ParserInput[0].ToString();
|
|
}
|
|
else {
|
|
Console.Write("* ");
|
|
continue;
|
|
}
|
|
|
|
// Simple switch based parsing of commands
|
|
switch (ParserInputFirstChar) {
|
|
case "h":
|
|
case "H":
|
|
case "?":
|
|
Console.WriteLine("* Commands available are:");
|
|
Console.WriteLine("* ?, (h | H) - prints this message");
|
|
Console.WriteLine("* [number] - start editing at line [number]");
|
|
Console.WriteLine("* (a | A) - append lines at end of file");
|
|
Console.WriteLine("* (c | C)[num1],[num2],[destnum] - copy lines from num1 to num2 to dest num");
|
|
Console.WriteLine("* (d | D); (d | D)[num]; (d | D)[num1],[num2] - delete current line, ");
|
|
Console.WriteLine("* line at num, lines from num1 to num2");
|
|
Console.WriteLine("* (e | E) - exit, saving changes");
|
|
Console.WriteLine("* (i | I); (i | I)[num] - insert line above current line, or above line num");
|
|
Console.WriteLine("* (l | L); (l | L)[num]; (l | L)[num1],[num2] - list the whole file, ");
|
|
Console.WriteLine("* list the line at num, list the lines from num1 to num2");
|
|
Console.WriteLine("* (m | M)[num1],[num2],[destnum] - move lines from num1 to num2 to dest num");
|
|
Console.WriteLine("* (n | N) - print current line number (location in file)");
|
|
Console.WriteLine("* (p | P) - same as l, only displays one page at a time.");
|
|
Console.WriteLine("* (q | Q) - quit, saving no changes since last write");
|
|
Console.WriteLine("* (r | R)[num1],([num2] | ?),[searchstr]^[replacestr] - replace");
|
|
Console.WriteLine("* searchstr with replacestr. If ? is used as second param, sub is prompted");
|
|
Console.WriteLine("* (s | S)[num1],([num2] | ?),[searchstr] - search for searchstr. ");
|
|
Console.WriteLine("* If ? is used as second param, occurrence is displayed with prompt");
|
|
Console.WriteLine("* until accepted with y, Y, or newline.");
|
|
Console.WriteLine("* (t | T)[num],[filename] - insert contents of filename above line num.");
|
|
Console.WriteLine("* (w | W) - write contents of memory to filename. Original contents will be");
|
|
Console.WriteLine("* backed up as for exit command.");
|
|
break;
|
|
case "a":
|
|
case "A":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for AppendAtEOF()");
|
|
|
|
tempSize = szArray.Count;
|
|
|
|
tempArray = AppendAtEOF(szArray);
|
|
|
|
if (tempArray.Count > tempSize) { // array has grown, so assume text modified
|
|
IsTextUpdated = true;
|
|
}
|
|
|
|
szArray = tempArray;
|
|
pIndex = tempArray.Count; // move line pointer to the end of the file
|
|
|
|
break;
|
|
case "c":
|
|
case "C":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for CopyLines()");
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text available to copy - new empty file");
|
|
}
|
|
else {
|
|
tempArray = CopyLines(szArray, ParserInput, pIndex);
|
|
|
|
if (szArray.Count != pIndex) { // assume the array has changed, ergo text modified
|
|
IsTextUpdated = true;
|
|
}
|
|
|
|
szArray = tempArray;
|
|
}
|
|
|
|
break;
|
|
case "d":
|
|
case "D":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for DeleteLines()");
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text available to delete - new empty file");
|
|
}
|
|
else {
|
|
tempArray = DeleteLines(szArray, ParserInput, pIndex);
|
|
|
|
if (szArray.Count != pIndex) { // assume the array has changed, ergo text modified
|
|
IsTextUpdated = true;
|
|
}
|
|
|
|
szArray = tempArray;
|
|
|
|
tempIndex = szArray.Count;
|
|
|
|
if (tempIndex < pIndex) { // deletion has reduced line count below pIndex - reset the pointer
|
|
pIndex = tempIndex;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case "e":
|
|
case "E":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for Exit ...");
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text to save, exiting without write.");
|
|
return;
|
|
}
|
|
else {
|
|
Console.WriteLine("* Exiting....");
|
|
EditorWrite(szArray, InputFileName, BackupFileName);
|
|
return;
|
|
}
|
|
|
|
break;
|
|
case "i":
|
|
case "I":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for InsertAtLine()");
|
|
|
|
// Insert is a special case. The line pointer for the file needs to move
|
|
// to the point of insertion if an argument is given, so we will parse that
|
|
// here and pass the results, since we need to get the updated array back.
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No lines to insert above - new empty file");
|
|
}
|
|
else {
|
|
Regex shortr = new Regex(@"^[iI](?<1>\d+)", RegexOptions.Compiled);
|
|
Match shortm;
|
|
shortm = shortr.Match(ParserInput);
|
|
Group shortg1 = shortm.Groups[1];
|
|
|
|
if ((ParserInput == "i") || (ParserInput == "i")) { //insert above current line pointer pIndex
|
|
InsertAtLine(szArray, pIndex);
|
|
IsTextUpdated = true;
|
|
}
|
|
else if (shortm.Success) { // we have one line number
|
|
//FOR DEBUG
|
|
//Console.WriteLine("Line number {0}", shortm.Groups[1]);
|
|
|
|
// write out line
|
|
Capture shortc1 = shortg1.Captures[0];
|
|
|
|
// tempIndex = Convert.ToInt32(shortc1.Value);
|
|
tempIndex = Int32.Parse(shortc1.Value);
|
|
if (tempIndex >= 1 && tempIndex <= szArray.Count) { // check for line numbers in range of file
|
|
pIndex = tempIndex; // update pIndex
|
|
InsertAtLine(szArray, pIndex);
|
|
IsTextUpdated = true;
|
|
}
|
|
else {
|
|
Console.WriteLine("* Line number {0} out of range. File length is {1}", tempIndex, szArray.Count);
|
|
}
|
|
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
}
|
|
}
|
|
break;
|
|
case "l":
|
|
case "L":
|
|
// FOR DEBUG
|
|
//Console.WriteLine("* Input was for ListText()");
|
|
|
|
tempIndex = ListText(szArray, ParserInput, pIndex);
|
|
if (tempIndex != -1) { // update current line number if list command moved the pointer
|
|
pIndex = tempIndex;
|
|
}
|
|
break;
|
|
case "m":
|
|
case "M":
|
|
//FOR DEBUG
|
|
//Console.WriteLine("* Input was for MoveLines()");
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text available to move - new empty file");
|
|
}
|
|
else {
|
|
tempArray = MoveLines(szArray, ParserInput, pIndex);
|
|
|
|
szArray = tempArray;
|
|
|
|
IsTextUpdated = true;
|
|
}
|
|
break;
|
|
case "n":
|
|
case "N":
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* Input was for PrintLineNumber()");
|
|
|
|
Console.WriteLine("* {0}", pIndex);
|
|
break;
|
|
case "p":
|
|
case "P":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for PageText()");
|
|
|
|
tempIndex = PageText(szArray, ParserInput, pIndex);
|
|
if (tempIndex != -1) { // update current line number if list command moved the pointer
|
|
pIndex = tempIndex;
|
|
}
|
|
|
|
break;
|
|
case "r":
|
|
case "R":
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* Input was for ReplaceText()");
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text available to replace");
|
|
}
|
|
else {
|
|
tempArray = ReplaceText(szArray, ParserInput, pIndex);
|
|
szArray = tempArray;
|
|
IsTextUpdated = true;
|
|
}
|
|
break;
|
|
case "s":
|
|
case "S":
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* Input was for SearchForText()");
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text available to search");
|
|
}
|
|
else {
|
|
tempIndex = SearchForText(szArray, ParserInput, pIndex);
|
|
if (tempIndex != -1) { // update current line number if list command moved the pointer
|
|
pIndex = tempIndex;
|
|
}
|
|
}
|
|
break;
|
|
case "t":
|
|
case "T":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for TransferText()");
|
|
|
|
tempArray = TransferText(szArray, ParserInput);
|
|
|
|
if (szArray.Count != pIndex) { // assume the array has changed, ergo text modified
|
|
IsTextUpdated = true;
|
|
}
|
|
|
|
szArray = tempArray;
|
|
|
|
break;
|
|
case "w":
|
|
case "W":
|
|
// FOR DEBUG
|
|
// Console.WriteLine("* Input was for WriteTextToFile()");
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No text to save.");
|
|
}
|
|
else {
|
|
EditorWrite(szArray, InputFileName, BackupFileName);
|
|
IsTextUpdated = false;
|
|
}
|
|
|
|
break;
|
|
case "":
|
|
break;
|
|
default:
|
|
int LineNumber = 0;
|
|
|
|
if (szArray.Count == 0) {
|
|
Console.WriteLine("* No lines to edit at - new empty file");
|
|
break;
|
|
}
|
|
else {
|
|
|
|
try {
|
|
// LineNumber = Convert.ToInt32(ParserInput);
|
|
LineNumber = Int32.Parse(ParserInput);
|
|
}
|
|
catch (System.ArgumentNullException) {
|
|
Console.WriteLine("String is null.");
|
|
break;
|
|
}
|
|
catch (System.FormatException) {
|
|
Console.WriteLine("* Unrecognized command");
|
|
break;
|
|
}
|
|
catch (System.OverflowException) {
|
|
Console.WriteLine("* Overflow in string to int conversion.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* Input was for EditAtLine() - line {0}", LineNumber);
|
|
|
|
// update line pointer to LineNumber
|
|
pIndex = LineNumber;
|
|
|
|
tempArray = EditAtLine(szArray, pIndex);
|
|
|
|
szArray = tempArray;
|
|
|
|
IsTextUpdated = true;
|
|
|
|
break;
|
|
}
|
|
Console.Write("* ");
|
|
}
|
|
if (IsTextUpdated == true) { // ask them if they really wanted to quit without writing text out
|
|
Console.WriteLine("* WARNING: modified text not saved.");
|
|
Console.Write("* Save? (Y/N) ");
|
|
|
|
string SaveReply = GetConsoleInput();
|
|
// string SaveReplyFirstChar = Convert.ToString(SaveReply[0]);
|
|
if (SaveReply != "") {
|
|
string SaveReplyFirstChar = SaveReply[0].ToString();
|
|
switch (SaveReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
Console.WriteLine("* Exiting....");
|
|
EditorWrite(szArray, InputFileName, BackupFileName);
|
|
break;
|
|
default:
|
|
Console.WriteLine("* Exiting without save.");
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Exiting without save.");
|
|
}
|
|
}
|
|
|
|
} // end of Parser
|
|
|
|
|
|
// ListText - returns updated list pointer as int
|
|
static int ListText(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Regex fullr = new Regex(@"^[lL](?<1>\d+),(?<2>\d+)", RegexOptions.Compiled);
|
|
Regex shortr = new Regex(@"^[lL](?<1>\d+)", RegexOptions.Compiled);
|
|
Match fullm;
|
|
Match shortm;
|
|
int listSuccess = 0;
|
|
int PAGEWIDTH = 72; // allow for line numbers in printouts - up to 99,999.
|
|
// TODO: adjust line number range dynamically for large files
|
|
int tempwidth = 0;
|
|
string workstring = "";
|
|
string tempstring = "";
|
|
int remainder = 0;
|
|
int division = 0;
|
|
int linesinline = 0;
|
|
int leftinstring = 0;
|
|
int lowLine = 0;
|
|
int hiLine = 0;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
fullm = fullr.Match(ParserInput);
|
|
shortm = shortr.Match(ParserInput);
|
|
Group fullg1 = fullm.Groups[1];
|
|
Group fullg2 = fullm.Groups[2];
|
|
Group shortg1 = shortm.Groups[1];
|
|
|
|
if (fullm.Success) { // we think we have two line numbers, set lowLine and hiLine accordingly
|
|
|
|
//FOR DEBUG
|
|
//Console.WriteLine("First line number {0}, last line number {1}", fullm.Groups[1], fullm.Groups[2]);
|
|
|
|
Capture fullc1 = fullg1.Captures[0];
|
|
Capture fullc2 = fullg2.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(fullc1.Value);
|
|
lowLine = Int32.Parse(fullc1.Value) - 1; // offset by one to allow for difference in starting point...
|
|
|
|
// int hiLine = Convert.ToInt32(fullc2.Value);
|
|
hiLine = Int32.Parse(fullc2.Value); // but leave this one alone, due to the loop
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 0 && lowLine <= szArray.Count) && (hiLine >= 0 && hiLine <= szArray.Count)) {
|
|
// continue on to listing...
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to list, or line out of range.");
|
|
Console.WriteLine("* lnum1,num2 where num1 <= num2 and num2 <= length of file.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
}
|
|
else if (shortm.Success) { // we have one line number
|
|
//FOR DEBUG
|
|
//Console.WriteLine("Line number {0}", shortm.Groups[1]);
|
|
|
|
// write out line
|
|
Capture shortc1 = shortg1.Captures[0];
|
|
|
|
// nIndex = Convert.ToInt32(shortc1.Value);
|
|
nIndex = Int32.Parse(shortc1.Value);
|
|
|
|
if (nIndex >= 1 && nIndex <= szArray.Count) { // check for line numbers in range of file
|
|
lowLine = nIndex - 1;
|
|
hiLine = nIndex;
|
|
// proceed to listing
|
|
}
|
|
else {
|
|
Console.WriteLine("* Line number {0} out of range. File length is {1}", nIndex, szArray.Count);
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
}
|
|
else if ((ParserInput == "l") || (ParserInput == "L")) { // set lowLine = 0, hiLine = szArray.Count
|
|
lowLine = 0;
|
|
hiLine = szArray.Count;
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
|
|
// print out buffer contents between lowLine and hiLine
|
|
for (nIndex = lowLine; nIndex < hiLine; nIndex++) {
|
|
workstring = szArray[nIndex].ToString();
|
|
tempwidth = workstring.Length;
|
|
if (tempwidth > PAGEWIDTH) {
|
|
//FOR DEBUG
|
|
//Console.WriteLine(" need to break up line length");
|
|
while (division != 1) {
|
|
linesinline++;
|
|
division = tempwidth / PAGEWIDTH;
|
|
remainder = tempwidth % PAGEWIDTH;
|
|
tempwidth = tempwidth - PAGEWIDTH;
|
|
//FOR DEBUG
|
|
//Console.WriteLine("remainder = {0}, division = {1}, tempwidth = {2}, linesinline = {3}", remainder, division, tempwidth, linesinline);
|
|
//Console.ReadLine();
|
|
}
|
|
if (remainder != 0) {
|
|
linesinline++;
|
|
//FOR DEBUG
|
|
//Console.WriteLine("remainder = {0}, division = {1}, tempwidth = {2}, linesinline = {3}", remainder, division, tempwidth, linesinline);
|
|
//Console.ReadLine();
|
|
}
|
|
leftinstring = workstring.Length;
|
|
while (linesinline > 0) {
|
|
if (leftinstring >= PAGEWIDTH) {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, PAGEWIDTH);
|
|
}
|
|
else {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, remainder);
|
|
}
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), tempstring);
|
|
linesinline--;
|
|
if (leftinstring > PAGEWIDTH) {
|
|
leftinstring = leftinstring - PAGEWIDTH;
|
|
}
|
|
}
|
|
|
|
// rezero worker constants
|
|
remainder = 0;
|
|
division = 0;
|
|
linesinline = 0;
|
|
leftinstring = 0;
|
|
listSuccess = 1;
|
|
}
|
|
else {
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), szArray[nIndex]);
|
|
}
|
|
|
|
listSuccess = 1;
|
|
}
|
|
|
|
if (listSuccess == 1) {
|
|
return nIndex; // paging worked
|
|
}
|
|
else { // note: you should never get here
|
|
return -1; // bad arguments, don't move line pointer
|
|
}
|
|
} // end of ListText
|
|
|
|
// CopyLines() - returns updated ArrayList with copies done, or the original ArrayList
|
|
static ArrayList CopyLines(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Queue copyQueue = new Queue();
|
|
Regex copyr = new Regex(@"^[cC](?<1>\d+),(?<2>\d+),(?<3>\d+)", RegexOptions.Compiled);
|
|
Match copym;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
copym = copyr.Match(ParserInput);
|
|
Group copyg1 = copym.Groups[1];
|
|
Group copyg2 = copym.Groups[2];
|
|
Group copyg3 = copym.Groups[3];
|
|
|
|
if (copym.Success) { // we think we have two line numbers and a dest number
|
|
//FOR DEBUG
|
|
//Console.WriteLine("First line number {0}, last line number {1}, dest {2}", copym.Groups[1], copym.Groups[2], copym.Groups[3]);
|
|
|
|
//Put array elements to be copied into copyQueue
|
|
Capture copyc1 = copyg1.Captures[0]; // first line of copy
|
|
Capture copyc2 = copyg2.Captures[0]; // last line of copy
|
|
|
|
// int lowLine = Convert.ToInt32(copyc1.Value);
|
|
int lowLine = Int32.Parse(copyc1.Value);
|
|
|
|
// int hiLine = Convert.ToInt32(copyc2.Value);
|
|
int hiLine = Int32.Parse(copyc2.Value);
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 1 && lowLine <= szArray.Count) && (hiLine >= 1 && hiLine <= szArray.Count)) {
|
|
for (nIndex = lowLine; nIndex <= hiLine; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
copyQueue.Enqueue(szArray[nIndex - 1]);
|
|
}
|
|
|
|
// check dest num valid
|
|
Capture copyc3 = copyg3.Captures[0];
|
|
|
|
// int destLine = Convert.ToInt32(copyc3.Value);
|
|
int destLine = Int32.Parse(copyc3.Value);
|
|
|
|
if (destLine >= 1 && destLine <= szArray.Count) {
|
|
// insert copyQueue at point dest in szArray
|
|
// note that due to the indexing offset you need to decrement destLine by 1 here
|
|
szArray.InsertRange(destLine - 1, copyQueue);
|
|
}
|
|
else if (destLine > szArray.Count) { // ask them if they want the copy at the end of the file
|
|
Console.Write("* Copy past end of file - do you want block appended? (y/n) ");
|
|
string appendReply = GetConsoleInput();
|
|
// string appendReplyFirstChar = Convert.ToString(appendReply[0]);
|
|
if (appendReply != "") {
|
|
string appendReplyFirstChar = appendReply[0].ToString();
|
|
switch (appendReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
szArray.AddRange(copyQueue);
|
|
break;
|
|
default:
|
|
Console.WriteLine("* Aborting copy.");
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Aborting copy.");
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Invalid copy destination.");
|
|
Console.WriteLine("* cnum1,num2,dest where num1 <= num2, num2 and dest <= length of file.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to copy, or line out of range.");
|
|
Console.WriteLine("* cnum1,num2 where num1 <= num2, num2 and dest <= length of file.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
}
|
|
|
|
return szArray; // c[num1,num2,dest] worked
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
return szArray;
|
|
}
|
|
} // end of CopyLines
|
|
|
|
// DeleteLines() - returns updated ArrayList with deletes done, or the original ArrayList
|
|
static ArrayList DeleteLines(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Regex fullr = new Regex(@"^[dD](?<1>\d+),(?<2>\d+)", RegexOptions.Compiled);
|
|
Regex shortr = new Regex(@"^[dD](?<1>\d+)", RegexOptions.Compiled);
|
|
Match fullm;
|
|
Match shortm;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
fullm = fullr.Match(ParserInput);
|
|
shortm = shortr.Match(ParserInput);
|
|
Group fullg1 = fullm.Groups[1];
|
|
Group fullg2 = fullm.Groups[2];
|
|
Group shortg1 = shortm.Groups[1];
|
|
|
|
if ((ParserInput == "d") || (ParserInput == "D")) { // delete line at current nIndex (which means subtracting 1)
|
|
szArray.RemoveAt(nIndex - 1);
|
|
|
|
return szArray;
|
|
}
|
|
else if (fullm.Success) { // we think we have two line numbers
|
|
//FOR DEBUG
|
|
//Console.WriteLine("First line number {0}, last line number {1}", fullm.Groups[1], fullm.Groups[2]);
|
|
|
|
//delete lines between first and second numbers
|
|
Capture fullc1 = fullg1.Captures[0];
|
|
Capture fullc2 = fullg2.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(fullc1.Value);
|
|
int lowLine = Int32.Parse(fullc1.Value);
|
|
|
|
// int hiLine = Convert.ToInt32(fullc2.Value);
|
|
int hiLine = Int32.Parse(fullc2.Value);
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 1 && lowLine <= szArray.Count) && (hiLine >= 1 && hiLine <= szArray.Count) && ((hiLine - lowLine) != 0)) {
|
|
szArray.RemoveRange(lowLine - 1, ((hiLine - lowLine) + 1));
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to list, or line out of range.");
|
|
Console.WriteLine("* dnum1,num2 where num1 <= num2 and num2 <= length of file.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
}
|
|
return szArray; // end of d[num1,num]
|
|
}
|
|
else if (shortm.Success) { // we have one line number
|
|
//FOR DEBUG
|
|
//Console.WriteLine("Line number {0}", shortm.Groups[1]);
|
|
|
|
// delete line
|
|
Capture shortc1 = shortg1.Captures[0];
|
|
|
|
// nIndex = Convert.ToInt32(shortc1.Value);
|
|
nIndex = Int32.Parse(shortc1.Value);
|
|
|
|
if (nIndex >= 1 && nIndex <= szArray.Count) { // check for line numbers in range of file
|
|
szArray.RemoveAt(nIndex - 1);
|
|
}
|
|
else {
|
|
Console.WriteLine("* Line number {0} out of range. File length is {1}", nIndex, szArray.Count);
|
|
return szArray;
|
|
}
|
|
return szArray;
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
return szArray;
|
|
}
|
|
} // end of DeleteLines
|
|
|
|
// EditAtLine() - edit the line at nIndex in szArray. Since we know the line number, we don't have
|
|
// to parse ParserInput here.
|
|
static ArrayList EditAtLine(ArrayList szArray, int nIndex)
|
|
{
|
|
Queue editQueue = new Queue();
|
|
|
|
if (nIndex >= 1 && nIndex <= szArray.Count) { // check that line number is in range of file
|
|
Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
Console.Write("> ");
|
|
string editInput = GetConsoleInput();
|
|
if (editInput == "") {
|
|
return szArray;
|
|
}
|
|
else {
|
|
editQueue.Enqueue(editInput);
|
|
szArray.RemoveAt(nIndex - 1);
|
|
szArray.InsertRange(nIndex - 1, editQueue);
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Line number {0} out of range. File length is {1}", nIndex, szArray.Count);
|
|
}
|
|
return szArray;
|
|
} // end of EditAtLine
|
|
|
|
|
|
// InsertAtLine() - insert line(s) above nIndex in szArray. Since we know the line number, we don't have
|
|
// to parse ParserInput here.
|
|
static ArrayList InsertAtLine(ArrayList szArray, int nIndex)
|
|
{
|
|
Queue insertQueue = new Queue();
|
|
string insertInput = null;
|
|
|
|
Console.WriteLine("* Inserting text above {0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
Console.WriteLine("* Press ^^ to end input.");
|
|
|
|
while (insertInput != "^^") { // Double carat ^^ ends input - would have used control char, but need tty to understand them....
|
|
Console.Write("> ");
|
|
insertInput = GetConsoleInput();
|
|
if (insertInput != "^^") {
|
|
insertQueue.Enqueue(insertInput);
|
|
}
|
|
}
|
|
szArray.InsertRange(nIndex - 1, insertQueue);
|
|
return szArray;
|
|
} // end of InsertAtLine
|
|
|
|
// AppendAtEOF() - append line(s) below current end of szArray. Since we are appending, we don't have
|
|
// to parse ParserInput here.
|
|
static ArrayList AppendAtEOF(ArrayList szArray)
|
|
{
|
|
Queue appendQueue = new Queue();
|
|
string appendInput = null;
|
|
|
|
Console.WriteLine("* Appending text at EOF - Press ^^ to end input.");
|
|
|
|
while (appendInput != "^^") { // ^^ ends input
|
|
Console.Write("> ");
|
|
appendInput = GetConsoleInput();
|
|
if (appendInput != "^^") {
|
|
appendQueue.Enqueue(appendInput);
|
|
}
|
|
}
|
|
szArray.AddRange(appendQueue);
|
|
return szArray;
|
|
} // end of AppendAtEOF()
|
|
|
|
// MoveLines() - returns updated ArrayList with moves done, or the original ArrayList
|
|
static ArrayList MoveLines(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Queue moveQueue = new Queue();
|
|
Regex mover = new Regex(@"^[mM](?<1>\d+),(?<2>\d+),(?<3>\d+)", RegexOptions.Compiled);
|
|
Match movem;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
movem = mover.Match(ParserInput);
|
|
Group moveg1 = movem.Groups[1];
|
|
Group moveg2 = movem.Groups[2];
|
|
Group moveg3 = movem.Groups[3];
|
|
|
|
if (movem.Success) { // we think we have two line numbers and a dest number
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, last line number {1}, dest {2}", movem.Groups[1], movem.Groups[2], movem.Groups[3]);
|
|
|
|
//Put array elements to be moved into moveQueue
|
|
Capture movec1 = moveg1.Captures[0]; // first line of move
|
|
Capture movec2 = moveg2.Captures[0]; // last line of move
|
|
|
|
// int lowLine = Convert.ToInt32(movec1.Value);
|
|
int lowLine = Int32.Parse(movec1.Value);
|
|
|
|
// int hiLine = Convert.ToInt32(movec2.Value);
|
|
int hiLine = Int32.Parse(movec2.Value);
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 1 && lowLine <= szArray.Count) && (hiLine >= 1 && hiLine <= szArray.Count)) {
|
|
for (nIndex = lowLine; nIndex <= hiLine; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
moveQueue.Enqueue(szArray[nIndex - 1]);
|
|
}
|
|
|
|
// check dest num valid
|
|
// However, you can't overlap - dest must either be before the block you're moving, or after it.
|
|
Capture movec3 = moveg3.Captures[0];
|
|
|
|
// int destLine = Convert.ToInt32(movec3.Value);
|
|
int destLine = Int32.Parse(movec3.Value);
|
|
|
|
if ((destLine >= 1 && destLine <= szArray.Count) && ((destLine < lowLine) || (destLine) > hiLine)) {
|
|
// insert moveQueue at point dest in szArray
|
|
// note that due to the indexing offset you need to decrement destLine by 1 here
|
|
szArray.InsertRange(destLine - 1, moveQueue);
|
|
|
|
// once the insertion is complete, then you can delete the lines from the original
|
|
// however, need to be careful about seeing what happened to the original lines - they
|
|
// may have moved their indexes in the array depending on where you did the insertion
|
|
if (destLine > hiLine) { // indexes stayed the same for the original block - delete it
|
|
szArray.RemoveRange(lowLine - 1, ((hiLine - lowLine) + 1));
|
|
}
|
|
else { // destLine above lowLine, need to adjust
|
|
int padLine = hiLine - lowLine;
|
|
szArray.RemoveRange((lowLine + padLine), ((hiLine - lowLine) + 1));
|
|
}
|
|
}
|
|
else if (destLine > szArray.Count) { // ask them if they want the move at the end of the file
|
|
Console.Write("* Move past end of file - do you want block appended? (y/n) ");
|
|
string appendReply = GetConsoleInput();
|
|
// string appendReplyFirstChar = Convert.ToString(appendReply[0]);
|
|
if (appendReply != "") {
|
|
string appendReplyFirstChar = appendReply[0].ToString();
|
|
switch (appendReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
szArray.AddRange(moveQueue);
|
|
// we don't have to worry about the index adjustment here - we can just remove the lines
|
|
// from their original location
|
|
szArray.RemoveRange(lowLine - 1, ((hiLine - lowLine) + 1));
|
|
break;
|
|
default:
|
|
Console.WriteLine("* Aborting move.");
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Aborting move.");
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Invalid move destination.");
|
|
Console.WriteLine("* mnum1,num2,dest where num1 <= num2, num2 and dest <= length of file,");
|
|
Console.WriteLine("* but dest not within num1 - num2 range.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to move, or line out of range.");
|
|
Console.WriteLine("* mnum1,num2 where num1 <= num2, num2 and dest <= length of file,");
|
|
Console.WriteLine("* but dest not within num1 - num2 range.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
}
|
|
return szArray; // m[num1,num2,dest] worked
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
return szArray;
|
|
}
|
|
} // end of MoveLines
|
|
|
|
// SearchForText() - returns updated list pointer, since we're not modifying any text
|
|
static int SearchForText(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Regex closedsearchr = new Regex(@"^[sS](?<1>\d+),(?<2>\d+),(?<3>.+)", RegexOptions.Compiled);
|
|
Regex opensearchr = new Regex(@"^[sS](?<1>\d+),\?,(?<2>.+)", RegexOptions.Compiled);
|
|
Match closedsearchm;
|
|
Match opensearchm;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
closedsearchm = closedsearchr.Match(ParserInput);
|
|
opensearchm = opensearchr.Match(ParserInput);
|
|
Group closedsearchg1 = closedsearchm.Groups[1];
|
|
Group closedsearchg2 = closedsearchm.Groups[2];
|
|
Group closedsearchg3 = closedsearchm.Groups[3];
|
|
Group opensearchg1 = opensearchm.Groups[1];
|
|
Group opensearchg2 = opensearchm.Groups[2];
|
|
int searchSuccess = 0;
|
|
|
|
if (closedsearchm.Success) { // we think we have two line numbers and a search string
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, last line number {1}, string {2}", closedsearchm.Groups[1], closedsearchm.Groups[2], closedsearchm.Groups[3]);
|
|
|
|
Capture closedsearchc1 = closedsearchg1.Captures[0];
|
|
Capture closedsearchc2 = closedsearchg2.Captures[0];
|
|
Capture closedsearchc3 = closedsearchg3.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(closedsearchc1.Value);
|
|
int lowLine = Int32.Parse(closedsearchc1.Value);
|
|
|
|
// int hiLine = Convert.ToInt32(closedsearchc2.Value);
|
|
int hiLine = Int32.Parse(closedsearchc2.Value);
|
|
|
|
Regex searchstringr = new Regex(Regex.Escape(closedsearchc3.Value));
|
|
Match searchstringm;
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 1 && lowLine <= szArray.Count) && (hiLine >= 1 && hiLine <= szArray.Count)) {
|
|
for (nIndex = lowLine; nIndex <= hiLine; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
// search for the searchstring in the current line
|
|
// searchstringm = searchstringr.Match(Regex.Escape(Convert.ToString(szArray[nIndex - 1])));
|
|
searchstringm = searchstringr.Match(Regex.Escape(szArray[nIndex - 1].ToString()));
|
|
if (searchstringm.Success) { // found a match
|
|
Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
searchSuccess = 1;
|
|
break;
|
|
}
|
|
else { // no match found
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* No match found");
|
|
searchSuccess = -1;
|
|
}
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to search, or line out of range.");
|
|
Console.WriteLine("* snum1,[num2 | ?],string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
searchSuccess = -1;
|
|
}
|
|
|
|
if (searchSuccess == 1) {
|
|
return nIndex;
|
|
}
|
|
else {
|
|
Console.WriteLine("* No match found");
|
|
return -1;
|
|
}
|
|
}
|
|
else if (opensearchm.Success) { // we have a starting line number and a string
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, last line number {1}, string {2}", closedsearchm.Groups[1], closedsearchm.Groups[2], closedsearchm.Groups[3]);
|
|
|
|
Capture opensearchc1 = opensearchg1.Captures[0];
|
|
Capture opensearchc2 = opensearchg2.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(opensearchc1.Value);
|
|
int lowLine = Int32.Parse(opensearchc1.Value);
|
|
|
|
Regex searchstringr = new Regex(Regex.Escape(opensearchc2.Value));
|
|
Match searchstringm;
|
|
|
|
// test for start number out of range
|
|
if (lowLine >= 1 && lowLine <= szArray.Count) {
|
|
for (nIndex = lowLine; nIndex <= szArray.Count; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
// search for the searchstring in the current line
|
|
// searchstringm = searchstringr.Match(Regex.Escape(Convert.ToString(szArray[nIndex - 1])));
|
|
searchstringm = searchstringr.Match(Regex.Escape(szArray[nIndex - 1].ToString()));
|
|
if (searchstringm.Success) { // found a match
|
|
Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
Console.Write("O.K.? ");
|
|
string searchReply = GetConsoleInput();
|
|
if (searchReply == "") {
|
|
searchSuccess = 1;
|
|
}
|
|
else {
|
|
// string searchReplyFirstChar = Convert.ToString(searchReply[0]);
|
|
string searchReplyFirstChar = searchReply[0].ToString();
|
|
switch (searchReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
searchSuccess = 1;
|
|
break;
|
|
default:
|
|
searchSuccess = -1;
|
|
break;
|
|
}
|
|
}
|
|
if (searchSuccess == 1) { // found a match, so stop looking (break from the for loop)
|
|
break;
|
|
}
|
|
}
|
|
else { // no match found
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* No match found");
|
|
searchSuccess = -1;
|
|
}
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to search, or line out of range.");
|
|
Console.WriteLine("* snum1,[num2 | ?],string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
searchSuccess = -1;
|
|
}
|
|
|
|
if (searchSuccess == 1) {
|
|
return nIndex;
|
|
}
|
|
else {
|
|
Console.WriteLine("* No match found");
|
|
return -1;
|
|
}
|
|
}
|
|
else { // bad match to initial parse of command args
|
|
Console.WriteLine("* Malformed arguments to search, or line out of range.");
|
|
Console.WriteLine("* snum1,[num2 | ?],string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
return -1;
|
|
}
|
|
} // end of SearchForText
|
|
|
|
// ReplaceText() - returns updated list pointer, since we're not modifying any text
|
|
static ArrayList ReplaceText(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Regex closedreplacer = new Regex(@"^[rR](?<1>\d+),(?<2>\d+),(?<3>.+)\^(?<4>.+)", RegexOptions.Compiled);
|
|
Regex openreplacer = new Regex(@"^[rR](?<1>\d+),\?,(?<2>.+)\^(?<3>.+)", RegexOptions.Compiled);
|
|
Match closedreplacem;
|
|
Match openreplacem;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
closedreplacem = closedreplacer.Match(ParserInput);
|
|
openreplacem = openreplacer.Match(ParserInput);
|
|
Group closedreplaceg1 = closedreplacem.Groups[1];
|
|
Group closedreplaceg2 = closedreplacem.Groups[2];
|
|
Group closedreplaceg3 = closedreplacem.Groups[3];
|
|
Group closedreplaceg4 = closedreplacem.Groups[4];
|
|
Group openreplaceg1 = openreplacem.Groups[1];
|
|
Group openreplaceg2 = openreplacem.Groups[2];
|
|
Group openreplaceg3 = openreplacem.Groups[3];
|
|
|
|
if (closedreplacem.Success) { // we think we have two line numbers, a search string, and a replace string
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, last line number {1}, string {2}, string {3}", closedreplacem.Groups[1], closedreplacem.Groups[2], closedreplacem.Groups[3], closedreplacem.Groups[4]);
|
|
|
|
Capture closedreplacec1 = closedreplaceg1.Captures[0];
|
|
Capture closedreplacec2 = closedreplaceg2.Captures[0];
|
|
Capture closedreplacec3 = closedreplaceg3.Captures[0];
|
|
Capture closedreplacec4 = closedreplaceg4.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(closedreplacec1.Value);
|
|
int lowLine = Int32.Parse(closedreplacec1.Value);
|
|
|
|
// int hiLine = Convert.ToInt32(closedreplacec2.Value);
|
|
int hiLine = Int32.Parse(closedreplacec2.Value);
|
|
|
|
Regex searchstringr = new Regex(Regex.Escape(closedreplacec3.Value));
|
|
// Match searchstringm;
|
|
Regex replacestringr = new Regex(Regex.Escape(closedreplacec4.Value));
|
|
string replaceresult = null;
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 1 && lowLine <= szArray.Count) && (hiLine >= 1 && hiLine <= szArray.Count)) {
|
|
for (nIndex = lowLine; nIndex <= hiLine; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
// search for the searchstring in the current line and replace it with the replacement string if found
|
|
// replaceresult = Regex.Replace(Convert.ToString(szArray[nIndex - 1]), Convert.ToString(searchstringr), Convert.ToString(replacestringr));
|
|
replaceresult = Regex.Replace(szArray[nIndex - 1].ToString(), searchstringr.ToString(), replacestringr.ToString());
|
|
Queue replaceQueue = new Queue();
|
|
replaceQueue.Enqueue(replaceresult);
|
|
szArray.InsertRange(nIndex - 1, replaceQueue);
|
|
szArray.RemoveAt(nIndex);
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to replace, or line out of range.");
|
|
Console.WriteLine("* rnum1,[num2 | ?],string,string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
}
|
|
|
|
return szArray;
|
|
}
|
|
else if (openreplacem.Success) { // we have a starting line number, a search string and a replace string
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, string {1}, string {2}", openreplacem.Groups[1], openreplacem.Groups[2], openreplacem.Groups[3]);
|
|
|
|
Capture openreplacec1 = openreplaceg1.Captures[0];
|
|
Capture openreplacec2 = openreplaceg2.Captures[0];
|
|
Capture openreplacec3 = openreplaceg3.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(openreplacec1.Value);
|
|
int lowLine = Int32.Parse(openreplacec1.Value);
|
|
|
|
Regex searchstringr = new Regex(Regex.Escape(openreplacec2.Value));
|
|
Match searchstringm;
|
|
Regex replacestringr = new Regex(Regex.Escape(openreplacec3.Value));
|
|
string replaceresult = null;
|
|
|
|
// test for start number out of range
|
|
if (lowLine >= 1 && lowLine <= szArray.Count) {
|
|
for (nIndex = lowLine; nIndex <= szArray.Count; nIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
|
|
// search for the searchstring in the current line
|
|
// searchstringm = searchstringr.Match(Regex.Escape(Convert.ToString(szArray[nIndex - 1])));
|
|
searchstringm = searchstringr.Match(Regex.Escape(szArray[nIndex - 1].ToString()));
|
|
if (searchstringm.Success) { // found a match
|
|
Console.WriteLine("{0}: {1}", nIndex, szArray[nIndex - 1]);
|
|
Console.Write("O.K.? ");
|
|
string replaceReply = GetConsoleInput();
|
|
if (replaceReply == "") {
|
|
// replaceresult = Regex.Replace(Convert.ToString(szArray[nIndex - 1]), Convert.ToString(searchstringr), Convert.ToString(replacestringr));
|
|
replaceresult = Regex.Replace(szArray[nIndex - 1].ToString(), searchstringr.ToString(), replacestringr.ToString());
|
|
Queue replaceQueue = new Queue();
|
|
replaceQueue.Enqueue(replaceresult);
|
|
szArray.InsertRange(nIndex - 1, replaceQueue);
|
|
szArray.RemoveAt(nIndex);
|
|
}
|
|
else {
|
|
// string replaceReplyFirstChar = Convert.ToString(replaceReply[0]);
|
|
string replaceReplyFirstChar = replaceReply[0].ToString();
|
|
switch (replaceReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
// replaceresult = Regex.Replace(Convert.ToString(szArray[nIndex - 1]), Convert.ToString(searchstringr), Convert.ToString(replacestringr));
|
|
replaceresult = Regex.Replace(szArray[nIndex - 1].ToString(), searchstringr.ToString(), replacestringr.ToString());
|
|
Queue replaceQueue = new Queue();
|
|
replaceQueue.Enqueue(replaceresult);
|
|
szArray.InsertRange(nIndex - 1, replaceQueue);
|
|
szArray.RemoveAt(nIndex);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else { // no match found
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* No match found");
|
|
}
|
|
}
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to replace, or line out of range.");
|
|
Console.WriteLine("* rnum1,[num2 | ?],string,string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
}
|
|
return szArray;
|
|
}
|
|
else { // bad match to initial parse of command args
|
|
Console.WriteLine("* Malformed arguments to replace, or line out of range.");
|
|
Console.WriteLine("* rnum1,[num2 | ?],string,string where num1 <= num2 and");
|
|
Console.WriteLine("* num2 <= length of file. File length is {0}", szArray.Count);
|
|
return szArray;
|
|
}
|
|
} // end of ReplaceText
|
|
|
|
static void EditorWrite(ArrayList szArray, string InputFileName, string BackupFileName)
|
|
{
|
|
int pIndex = 0;
|
|
|
|
// check to see if file exists at all, first - if it doesn't,
|
|
// we have to create it, but don't have to back it up.
|
|
|
|
if (File.Exists(InputFileName)) { // it does exist, ergo we need to back it up
|
|
// Test to see if the backup file exists, if it does, delete it (to clear it)
|
|
if (File.Exists(BackupFileName)) {
|
|
File.Delete(BackupFileName);
|
|
}
|
|
|
|
// Then, copy the original file to one with bak at the end
|
|
File.Copy(InputFileName, BackupFileName, true);
|
|
|
|
// Then delete the original file (to clear it)
|
|
File.Delete(InputFileName);
|
|
|
|
// Then write out the contents of the buffer to our InputFileName
|
|
FileStream fsOutput = new FileStream(InputFileName, FileMode.Create, FileAccess.Write);
|
|
StreamWriter srOutput = new StreamWriter(fsOutput);
|
|
for (pIndex = 0; pIndex < szArray.Count; pIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("* pIndex = {0}, line = {1}", pIndex, szArray[pIndex]);
|
|
|
|
srOutput.WriteLine(szArray[pIndex]);
|
|
}
|
|
srOutput.Close();
|
|
fsOutput.Close();
|
|
return;
|
|
}
|
|
else { // file didn't exist, so create it, and don't back it up
|
|
FileStream fsOutput = new FileStream(InputFileName, FileMode.Create, FileAccess.Write);
|
|
StreamWriter srOutput = new StreamWriter(fsOutput);
|
|
for (pIndex = 0; pIndex < szArray.Count; pIndex++) {
|
|
srOutput.WriteLine(szArray[pIndex]);
|
|
}
|
|
srOutput.Close();
|
|
fsOutput.Close();
|
|
return;
|
|
}
|
|
} // end of EditorWrite();
|
|
|
|
// PageText - returns updated list pointer as int
|
|
static int PageText(ArrayList szArray, string ParserInput, int nIndex)
|
|
{
|
|
Regex fullr = new Regex(@"^[pP](?<1>\d+),(?<2>\d+)", RegexOptions.Compiled);
|
|
Regex shortr = new Regex(@"^[pP](?<1>\d+)", RegexOptions.Compiled);
|
|
Match fullm;
|
|
Match shortm;
|
|
int listSuccess = 0;
|
|
int pageCounter = 0;
|
|
string pageReply = "";
|
|
string pageReplyFirstChar = "";
|
|
int PAGELENGTH = 47; // allow for Singularity "activity" line at top of console
|
|
int PAGEWIDTH = 72; // allow for line numbers in printouts - up to 99,999.
|
|
// TODO: adjust line number range dynamically for large files
|
|
int tempwidth = 0;
|
|
string workstring = "";
|
|
string tempstring = "";
|
|
int remainder = 0;
|
|
int division = 0;
|
|
int linesinline = 0;
|
|
int leftinstring = 0;
|
|
int lowLine = 0;
|
|
int hiLine = 0;
|
|
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
fullm = fullr.Match(ParserInput);
|
|
shortm = shortr.Match(ParserInput);
|
|
Group fullg1 = fullm.Groups[1];
|
|
Group fullg2 = fullm.Groups[2];
|
|
Group shortg1 = shortm.Groups[1];
|
|
|
|
if (fullm.Success) { // we think we have two line numbers, set lowLine and hiLine accordingly
|
|
|
|
//FOR DEBUG
|
|
//Console.WriteLine("First line number {0}, last line number {1}", fullm.Groups[1], fullm.Groups[2]);
|
|
|
|
Capture fullc1 = fullg1.Captures[0];
|
|
Capture fullc2 = fullg2.Captures[0];
|
|
|
|
// int lowLine = Convert.ToInt32(fullc1.Value);
|
|
lowLine = Int32.Parse(fullc1.Value) - 1; // offset by one to allow for difference in starting point...
|
|
|
|
// int hiLine = Convert.ToInt32(fullc2.Value);
|
|
hiLine = Int32.Parse(fullc2.Value); // but leave this one alone, due to the loop
|
|
|
|
// test for numbers out of range or out of order
|
|
if ((lowLine <= hiLine) && (lowLine >= 0 && lowLine <= szArray.Count) && (hiLine >= 0 && hiLine <= szArray.Count)) {
|
|
// continue on to listing...
|
|
}
|
|
else { // bad arguments
|
|
Console.WriteLine("* Malformed arguments to page, or line out of range.");
|
|
Console.WriteLine("* pnum1,num2 where num1 <= num2 and num2 <= length of file.");
|
|
Console.WriteLine("* File length is {0}.", szArray.Count);
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
}
|
|
else if (shortm.Success) { // we have one line number
|
|
//FOR DEBUG
|
|
//Console.WriteLine("Line number {0}", shortm.Groups[1]);
|
|
|
|
// write out line
|
|
Capture shortc1 = shortg1.Captures[0];
|
|
|
|
// nIndex = Convert.ToInt32(shortc1.Value);
|
|
nIndex = Int32.Parse(shortc1.Value);
|
|
|
|
if (nIndex >= 1 && nIndex <= szArray.Count) { // check for line numbers in range of file
|
|
lowLine = nIndex - 1;
|
|
hiLine = nIndex;
|
|
// proceed to listing
|
|
}
|
|
else {
|
|
Console.WriteLine("* Line number {0} out of range. File length is {1}", nIndex, szArray.Count);
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
}
|
|
else if ((ParserInput == "p") || (ParserInput == "P")) { // set lowLine = 0, hiLine = szArray.Count
|
|
lowLine = 0;
|
|
hiLine = szArray.Count;
|
|
}
|
|
else {
|
|
Console.WriteLine("Invalid match");
|
|
listSuccess = -1;
|
|
return listSuccess;
|
|
}
|
|
|
|
// print out buffer contents between lowLine and hiLine by pages
|
|
for (nIndex = lowLine; nIndex < hiLine; nIndex++) {
|
|
workstring = szArray[nIndex].ToString();
|
|
tempwidth = workstring.Length;
|
|
if (tempwidth > PAGEWIDTH) {
|
|
//FOR DEBUG
|
|
//Console.WriteLine(" need to break up line length");
|
|
while (division != 1) {
|
|
linesinline++;
|
|
division = tempwidth / PAGEWIDTH;
|
|
remainder = tempwidth % PAGEWIDTH;
|
|
tempwidth = tempwidth - PAGEWIDTH;
|
|
//FOR DEBUG
|
|
//Console.WriteLine("remainder = {0}, division = {1}, tempwidth = {2}, linesinline = {3}", remainder, division, tempwidth, linesinline);
|
|
//Console.ReadLine();
|
|
}
|
|
if (remainder != 0) {
|
|
linesinline++;
|
|
//FOR DEBUG
|
|
//Console.WriteLine("remainder = {0}, division = {1}, tempwidth = {2}, linesinline = {3}", remainder, division, tempwidth, linesinline);
|
|
//Console.ReadLine();
|
|
}
|
|
if (linesinline < (PAGELENGTH - pageCounter)) {
|
|
// room to print the whole wrapped line
|
|
leftinstring = workstring.Length;
|
|
while (linesinline > 0) {
|
|
if (leftinstring >= PAGEWIDTH) {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, PAGEWIDTH);
|
|
}
|
|
else {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, remainder);
|
|
}
|
|
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), tempstring);
|
|
pageCounter++;
|
|
linesinline--;
|
|
if (leftinstring > PAGEWIDTH) {
|
|
leftinstring = leftinstring - PAGEWIDTH;
|
|
}
|
|
}
|
|
}
|
|
else if (pageCounter <= PAGELENGTH) {
|
|
// less than PAGELENGTH, but not enough room to print the whole wrapped line
|
|
leftinstring = workstring.Length;
|
|
while (linesinline > 0) {
|
|
if (leftinstring >= PAGEWIDTH) {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, PAGEWIDTH);
|
|
}
|
|
else {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, remainder);
|
|
}
|
|
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), tempstring);
|
|
pageCounter++;
|
|
linesinline--;
|
|
if (leftinstring > PAGEWIDTH) {
|
|
leftinstring = leftinstring - PAGEWIDTH;
|
|
}
|
|
if (pageCounter > PAGELENGTH) {
|
|
pageCounter = 0;
|
|
Console.Write("-- <ENTER> -- ");
|
|
pageReply = GetConsoleInput();
|
|
if (pageReply != "") {
|
|
//pageReplyFirstChar = Convert.ToString(pageReply[0]);
|
|
pageReplyFirstChar = pageReply[0].ToString();
|
|
switch (pageReplyFirstChar) {
|
|
case "q":
|
|
case "Q":
|
|
return nIndex + 1;
|
|
default:
|
|
if (leftinstring >= PAGEWIDTH) {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, PAGEWIDTH);
|
|
}
|
|
else {
|
|
tempstring = workstring.Substring(workstring.Length - leftinstring, remainder);
|
|
}
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), tempstring);
|
|
pageCounter++;
|
|
linesinline--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// rezero worker constants
|
|
remainder = 0;
|
|
division = 0;
|
|
linesinline = 0;
|
|
leftinstring = 0;
|
|
listSuccess = 1;
|
|
}
|
|
else {
|
|
Console.WriteLine("{0,5}: {1}", (nIndex + 1), szArray[nIndex]);
|
|
|
|
if (pageCounter < PAGELENGTH) {
|
|
pageCounter++;
|
|
}
|
|
else {
|
|
pageCounter = 0;
|
|
Console.Write("-- <ENTER> -- ");
|
|
pageReply = GetConsoleInput();
|
|
if (pageReply != "") {
|
|
//pageReplyFirstChar = Convert.ToString(pageReply[0]);
|
|
pageReplyFirstChar = pageReply[0].ToString();
|
|
switch (pageReplyFirstChar) {
|
|
case "q":
|
|
case "Q":
|
|
return nIndex + 1;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
listSuccess = 1;
|
|
}
|
|
}
|
|
|
|
if (listSuccess == 1) {
|
|
return nIndex; // paging worked
|
|
}
|
|
else { // note that you should never get here
|
|
return -1; // bad arguments, don't move line pointer
|
|
}
|
|
} // end of PageText
|
|
|
|
// TransferText() - returns updated ArrayList with content merged in from external file, or the original ArrayList
|
|
static ArrayList TransferText(ArrayList szArray, string ParserInput)
|
|
{
|
|
Queue transferQueue = new Queue();
|
|
Regex transferr = new Regex(@"^[tT](?<1>\d+),(?<2>.+)", RegexOptions.Compiled);
|
|
Match transferm;
|
|
|
|
//FOR DEBUGGING
|
|
//Console.WriteLine("Current line number is {0}", nIndex);
|
|
|
|
transferm = transferr.Match(ParserInput);
|
|
Group transferg1 = transferm.Groups[1];
|
|
Group transferg2 = transferm.Groups[2];
|
|
|
|
if (transferm.Success) { // we think we have a line number and a filename of some sort
|
|
//FOR DEBUG
|
|
// Console.WriteLine("First line number {0}, filename {1}", transferm.Groups[1], transferm.Groups[2]);
|
|
|
|
//Put file contents to be copied into transferQueue
|
|
Capture transferc1 = transferg1.Captures[0]; // insertion point
|
|
|
|
// int lowLine = Convert.ToInt32(transferc1.Value);
|
|
int lowLine = Int32.Parse(transferc1.Value);
|
|
|
|
Capture transferc2 = transferg2.Captures[0]; // filename
|
|
// string TransferFileName = Convert.ToString(transferc2.Value);
|
|
string TransferFileName = transferc2.Value.ToString();
|
|
|
|
if (File.Exists(TransferFileName)) { // file exists, so read it into a buffer
|
|
string TransferLine;
|
|
ArrayList transferContents = new ArrayList();
|
|
FileStream fsInput = new FileStream(TransferFileName, FileMode.Open, FileAccess.Read);
|
|
StreamReader srInput = new StreamReader(fsInput);
|
|
while ((TransferLine = srInput.ReadLine()) != null) {
|
|
transferContents.Add(TransferLine);
|
|
}
|
|
srInput.Close();
|
|
fsInput.Close();
|
|
for (int transferIndex = 0; transferIndex < transferContents.Count; transferIndex++) {
|
|
//FOR DEBUG
|
|
// Console.WriteLine("{0}: {1}", transferIndex, transferContents[transferIndex]);
|
|
|
|
transferQueue.Enqueue(transferContents[transferIndex]);
|
|
}
|
|
}
|
|
else { // file to be merged wasn't there
|
|
Console.WriteLine("* File to be merged doesn't exist.");
|
|
return szArray;
|
|
}
|
|
|
|
// test for numbers out of range or out of order
|
|
if (lowLine >= 1 && lowLine <= szArray.Count) { //
|
|
szArray.InsertRange(lowLine - 1, transferQueue);
|
|
return szArray;
|
|
}
|
|
else if (lowLine > szArray.Count) { // check if number is past the end of the file and they want to append
|
|
Console.Write("* Transfer past end of file - do you want file appended? (Y/N) ");
|
|
|
|
string appendReply = GetConsoleInput();
|
|
// string appendReplyFirstChar = Convert.ToString(appendReply[0]);
|
|
if (appendReply != "") {
|
|
string appendReplyFirstChar = appendReply[0].ToString();
|
|
switch (appendReplyFirstChar) {
|
|
case "y":
|
|
case "Y":
|
|
szArray.AddRange(transferQueue);
|
|
break;
|
|
default:
|
|
Console.WriteLine("* Aborting transfer.");
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
Console.WriteLine("* Aborting transfer.");
|
|
}
|
|
return szArray;
|
|
}
|
|
else { // something else is wrong with the insertion point
|
|
Console.WriteLine("* Invalid transfer destination.");
|
|
Console.WriteLine("* tnum1, filename where num1 is insertion point and filename");
|
|
Console.WriteLine("* is what is to be inserted. File length is {0}.", szArray.Count);
|
|
return szArray;
|
|
}
|
|
}
|
|
else {// bad arguments
|
|
Console.WriteLine("* Malformed arguments to transfer.");
|
|
Console.WriteLine("* tnum1, filename where num1 is insertion point and filename");
|
|
Console.WriteLine("* is what is to be inserted. File length is {0}.", szArray.Count);
|
|
return szArray;
|
|
}
|
|
} // end of TransferText
|
|
|
|
static string GetConsoleInput() { // filter Console.ReadLine input for backspaces
|
|
string InputString = "";
|
|
string InputCheck = "";
|
|
|
|
InputString = Console.ReadLine();
|
|
if (InputString != "") {
|
|
//FOR DEBUG
|
|
//Console.WriteLine("* Input was {0}", InputString);
|
|
//Console.Write("* ");
|
|
//
|
|
//for (int i = 0; i < InputString.Length; i++) {
|
|
// Console.Write("{0:x}",(int)InputString[i]);
|
|
//}
|
|
//Console.Write("* ");
|
|
// END DEBUG
|
|
|
|
// Check for backspace chars and remove them if present, but also delete the character(s) they meant to delete
|
|
int j = 0;
|
|
string TempString = "";
|
|
for (int i = 0; i < InputString.Length; i++) {
|
|
if ((int)InputString[i] != 0x08) {
|
|
TempString = string.Concat(InputCheck,InputString[i].ToString());
|
|
InputCheck = TempString;
|
|
j++;
|
|
}
|
|
else {
|
|
InputCheck = InputCheck.Remove(j - 1,1);
|
|
j--;
|
|
}
|
|
}
|
|
//FOR DEBUG
|
|
//Console.WriteLine("* Check was {0}", InputCheck);
|
|
//Console.Write("* ");
|
|
//
|
|
//for (int i = 0; i < InputCheck.Length; i++) {
|
|
// Console.Write("{0:x}",(int)InputCheck[i]);
|
|
//}
|
|
//END DEBUG
|
|
|
|
}
|
|
return InputCheck;
|
|
} // end of GetConsoleInput()
|
|
|
|
|
|
}
|
|
}
|
|
|