singrdk/base/Applications/More/More.cs

261 lines
9.3 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
2008-11-17 18:29:00 -05:00
using Pipe = Microsoft.Singularity.Io.Tty;
2008-03-05 09:52:00 -05:00
using FileSystem.Utils;
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Configuration;
using Microsoft.Singularity.Channels;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications
{
[ConsoleCategory(HelpMessage="Display a screen full of text", DefaultAction=true)]
internal class Parameters {
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
[Endpoint]
public readonly TRef<DirectoryServiceContract.Imp:Start> nsRef;
[StringArrayParameter( "files", HelpMessage="Files to be listed.")]
internal string[] fileSet;
reflective internal Parameters();
internal int AppMain() {
return More.AppMain(this);
}
}
class More
{
2008-11-17 18:29:00 -05:00
internal static int pageCounter;
internal static Terminal! terminal;
internal static long fileSize;
internal static long bytesRead;
2008-03-05 09:52:00 -05:00
[ Conditional("DEBUG_MORE") ]
static void DebugPrint(string format, params object [] args)
{
DebugStub.Print(String.Format(format, args));
}
[ Conditional("DEBUG_MORE") ]
static void DebugWriteLine(string format, params object [] args)
{
DebugPrint(format, args);
DebugStub.Print("\n");
}
[ Conditional("DEBUG_MORE") ]
static void DebugReadLine()
{
Console.ReadLine();
}
internal static int AppMain(Parameters! config) {
// constants
//int szLineCount = 0;
int displayfile = 0;
int consoleWidth = 0;
int consoleHeight = 0;
2008-11-17 18:29:00 -05:00
pageCounter = 0;
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
terminal = new Terminal();
DirectoryServiceContract.Imp dsRoot = ((!)config.nsRef).Acquire();
if (dsRoot == null) {
throw new Exception("Unable to acquire handle to the Directory Service root");
}
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
dsRoot.RecvSuccess();
2008-03-05 09:52:00 -05:00
2008-11-17 18:29:00 -05:00
// TODO need to dynamically get window size
2008-03-05 09:52:00 -05:00
consoleHeight = 47; // allow for "activity" line on top of Singularity console....
consoleWidth = 79;
assume config.fileSet != null;
string szSrcLine;
2008-11-17 18:29:00 -05:00
bool ok;
if (config.fileSet.Length <= 0) {
//stdin
while ((szSrcLine = Console.ReadLine()) != null) {
ok = PageText(szSrcLine, consoleHeight, consoleWidth, true);
if (!ok) break;
}
delete dsRoot;
return 0;
}
2008-03-05 09:52:00 -05:00
for (displayfile = 0; displayfile < config.fileSet.Length; displayfile++) {
string filename = config.fileSet[displayfile];
2008-11-17 18:29:00 -05:00
if (filename == null) continue;
2008-03-05 09:52:00 -05:00
// check that file exists
2008-11-17 18:29:00 -05:00
ErrorCode error;
FileAttributesRecord fileAttributes;
ok = FileUtils.GetAttributes(filename, dsRoot, out fileAttributes, out error);
2008-03-05 09:52:00 -05:00
if (ok) {
2008-11-17 18:29:00 -05:00
if (fileAttributes.Type == NodeType.IoMemory || fileAttributes.Type == NodeType.File) {
fileSize = fileAttributes.FileSize;
2008-03-05 09:52:00 -05:00
// Open file RO for now
FileStream fsInput = new FileStream(dsRoot, filename, FileMode.Open, FileAccess.Read);
StreamReader srInput = new StreamReader(fsInput);
2008-11-17 18:29:00 -05:00
while ((szSrcLine = srInput.ReadLine()) != null) {
ok = PageText(szSrcLine, consoleHeight, consoleWidth, false);
if (!ok) break;
2008-03-05 09:52:00 -05:00
}
srInput.Close();
fsInput.Close();
// Display the file by pages
// TODO: change PageText to return between pages so can recheck for
// screen dimension changes (?)
if (displayfile <= config.fileSet.Length - 2) // offset by 2 due to index offset plus increment hasn't happened yet
{
Console.WriteLine("");
Console.Write("-- <ENTER> for next file --");
int key;
do {
key = Console.Read();
if (key == -1) {
2008-11-17 18:29:00 -05:00
delete dsRoot;
2008-03-05 09:52:00 -05:00
return 0;
}
} while ((char)key != '\n');
}
}
2008-11-17 18:29:00 -05:00
else if (fileAttributes.Type == NodeType.Directory) {
2008-03-05 09:52:00 -05:00
// check that it's not a directory
Console.WriteLine("\n{0} - is a directory.", filename);
}
2008-11-17 18:29:00 -05:00
} // ok
else {
2008-03-05 09:52:00 -05:00
// not a directory, but file doesn't exist, print error message
Console.WriteLine("\n{0} - file not found.", filename);
}
}
2008-11-17 18:29:00 -05:00
delete dsRoot;
2008-03-05 09:52:00 -05:00
return 0;
}
//////////////////////////////////////////////////////////////
// Write out prompt and wait for input
// After acquiring the input remove the prompt from the console
//////////////////////////////////////////////////////////////
2008-11-17 18:29:00 -05:00
static int GetInput(int PAGELENGTH, bool processingStdin)
2008-03-05 09:52:00 -05:00
{
int counter = 0;
2008-11-17 18:29:00 -05:00
int key;
if (processingStdin) {
2008-03-05 09:52:00 -05:00
Console.Write("-- <more> -- ");
key = Console.Read();
2008-11-17 18:29:00 -05:00
if ((char)key == '\n' ) Console.Write("\n");
}
else {
double temp = 0;
if (fileSize != 0) {
temp = (double) (bytesRead * 100) / (double)fileSize;
}
else {
temp = 100;
}
Console.Write("-- <more> ({0}%) -- ", (int)temp);
key = Console.Read();
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
// get rid of the -- <ENTER> line
if ((char)key == '\n') {
terminal.GenerateAndSendEscapeSequence(Pipe.EscapeCodes.UP);
}
Console.Write("\r");
terminal.GenerateAndSendEscapeSequence(Pipe.EscapeCodes.ERASE_FROM_CURSOR);
2008-03-05 09:52:00 -05:00
if (key == -1) return -1;
2008-11-17 18:29:00 -05:00
switch (Char.ToLower((char)key)) {
2008-03-05 09:52:00 -05:00
case 'q':
return -1;
default:
if ((char)key == '\n') counter = PAGELENGTH ; // advance by 1
break;
}
return counter;
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
// PageText - display text a page at a time
2008-11-17 18:29:00 -05:00
static bool PageText(string! workString,
int PAGELENGTH,
int PAGEWIDTH,
bool processingStdin)
2008-03-05 09:52:00 -05:00
{
2008-11-17 18:29:00 -05:00
string[] lines;
2008-03-05 09:52:00 -05:00
int remainder = 0;
int linesinline = 0;
// Split the line into the requisite number of lines
// needed based on page width
2008-11-17 18:29:00 -05:00
if (workString.Length <= PAGEWIDTH) {
2008-03-05 09:52:00 -05:00
lines = new string[1];
2008-11-17 18:29:00 -05:00
lines[0] = workString;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
else {
2008-03-05 09:52:00 -05:00
int fullLines = workString.Length / PAGEWIDTH;
remainder = workString.Length % PAGEWIDTH;
2008-11-17 18:29:00 -05:00
linesinline = fullLines;
2008-03-05 09:52:00 -05:00
if (remainder != 0) linesinline++;
lines = new string[linesinline];
2008-11-17 18:29:00 -05:00
int pos = 0;
for (int i = 0; i < fullLines; i++) {
2008-03-05 09:52:00 -05:00
lines[i] = workString.Substring(pos,PAGEWIDTH);
2008-11-17 18:29:00 -05:00
pos += PAGEWIDTH;
2008-03-05 09:52:00 -05:00
}
if (remainder != 0) {
lines[fullLines] = workString.Substring(pos);
}
}
// write the lines out pausing where necessary
2008-11-17 18:29:00 -05:00
for (int i = 0; i < lines.Length; i++) {
string s = lines[i];
assert s!= null;
Console.WriteLine(s);
pageCounter++;
bytesRead += s.Length;
2008-03-05 09:52:00 -05:00
if (pageCounter >= PAGELENGTH) {
2008-11-17 18:29:00 -05:00
pageCounter = GetInput(PAGELENGTH, processingStdin);
if (pageCounter == -1) return false;
2008-03-05 09:52:00 -05:00
}
}
2008-11-17 18:29:00 -05:00
lines = null;
return true;
2008-03-05 09:52:00 -05:00
} // end of PageText
}
}