PageRenderTime 73ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/base/Applications/More/More.cs

#
C# | 260 lines | 197 code | 37 blank | 26 comment | 52 complexity | 5956f8c989e1897b69bda1bba140cbbe MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. using System;
  8. using System.Collections;
  9. using System.Diagnostics;
  10. using System.IO;
  11. using Pipe = Microsoft.Singularity.Io.Tty;
  12. using FileSystem.Utils;
  13. using Microsoft.Contracts;
  14. using Microsoft.SingSharp.Reflection;
  15. using Microsoft.Singularity.Applications;
  16. using Microsoft.Singularity.Io;
  17. using Microsoft.Singularity.Directory;
  18. using Microsoft.Singularity.Configuration;
  19. using Microsoft.Singularity.Channels;
  20. [assembly: Transform(typeof(ApplicationResourceTransform))]
  21. namespace Microsoft.Singularity.Applications
  22. {
  23. [ConsoleCategory(HelpMessage="Display a screen full of text", DefaultAction=true)]
  24. internal class Parameters {
  25. [InputEndpoint("data")]
  26. public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
  27. [OutputEndpoint("data")]
  28. public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
  29. [Endpoint]
  30. public readonly TRef<DirectoryServiceContract.Imp:Start> nsRef;
  31. [StringArrayParameter( "files", HelpMessage="Files to be listed.")]
  32. internal string[] fileSet;
  33. reflective internal Parameters();
  34. internal int AppMain() {
  35. return More.AppMain(this);
  36. }
  37. }
  38. class More
  39. {
  40. internal static int pageCounter;
  41. internal static Terminal! terminal;
  42. internal static long fileSize;
  43. internal static long bytesRead;
  44. [ Conditional("DEBUG_MORE") ]
  45. static void DebugPrint(string format, params object [] args)
  46. {
  47. DebugStub.Print(String.Format(format, args));
  48. }
  49. [ Conditional("DEBUG_MORE") ]
  50. static void DebugWriteLine(string format, params object [] args)
  51. {
  52. DebugPrint(format, args);
  53. DebugStub.Print("\n");
  54. }
  55. [ Conditional("DEBUG_MORE") ]
  56. static void DebugReadLine()
  57. {
  58. Console.ReadLine();
  59. }
  60. internal static int AppMain(Parameters! config) {
  61. // constants
  62. //int szLineCount = 0;
  63. int displayfile = 0;
  64. int consoleWidth = 0;
  65. int consoleHeight = 0;
  66. pageCounter = 0;
  67. terminal = new Terminal();
  68. DirectoryServiceContract.Imp dsRoot = ((!)config.nsRef).Acquire();
  69. if (dsRoot == null) {
  70. throw new Exception("Unable to acquire handle to the Directory Service root");
  71. }
  72. dsRoot.RecvSuccess();
  73. // TODO need to dynamically get window size
  74. consoleHeight = 47; // allow for "activity" line on top of Singularity console....
  75. consoleWidth = 79;
  76. assume config.fileSet != null;
  77. string szSrcLine;
  78. bool ok;
  79. if (config.fileSet.Length <= 0) {
  80. //stdin
  81. while ((szSrcLine = Console.ReadLine()) != null) {
  82. ok = PageText(szSrcLine, consoleHeight, consoleWidth, true);
  83. if (!ok) break;
  84. }
  85. delete dsRoot;
  86. return 0;
  87. }
  88. for (displayfile = 0; displayfile < config.fileSet.Length; displayfile++) {
  89. string filename = config.fileSet[displayfile];
  90. if (filename == null) continue;
  91. // check that file exists
  92. ErrorCode error;
  93. FileAttributesRecord fileAttributes;
  94. ok = FileUtils.GetAttributes(filename, dsRoot, out fileAttributes, out error);
  95. if (ok) {
  96. if (fileAttributes.Type == NodeType.IoMemory || fileAttributes.Type == NodeType.File) {
  97. fileSize = fileAttributes.FileSize;
  98. // Open file RO for now
  99. FileStream fsInput = new FileStream(dsRoot, filename, FileMode.Open, FileAccess.Read);
  100. StreamReader srInput = new StreamReader(fsInput);
  101. while ((szSrcLine = srInput.ReadLine()) != null) {
  102. ok = PageText(szSrcLine, consoleHeight, consoleWidth, false);
  103. if (!ok) break;
  104. }
  105. srInput.Close();
  106. fsInput.Close();
  107. // Display the file by pages
  108. // TODO: change PageText to return between pages so can recheck for
  109. // screen dimension changes (?)
  110. if (displayfile <= config.fileSet.Length - 2) // offset by 2 due to index offset plus increment hasn't happened yet
  111. {
  112. Console.WriteLine("");
  113. Console.Write("-- <ENTER> for next file --");
  114. int key;
  115. do {
  116. key = Console.Read();
  117. if (key == -1) {
  118. delete dsRoot;
  119. return 0;
  120. }
  121. } while ((char)key != '\n');
  122. }
  123. }
  124. else if (fileAttributes.Type == NodeType.Directory) {
  125. // check that it's not a directory
  126. Console.WriteLine("\n{0} - is a directory.", filename);
  127. }
  128. } // ok
  129. else {
  130. // not a directory, but file doesn't exist, print error message
  131. Console.WriteLine("\n{0} - file not found.", filename);
  132. }
  133. }
  134. delete dsRoot;
  135. return 0;
  136. }
  137. //////////////////////////////////////////////////////////////
  138. // Write out prompt and wait for input
  139. // After acquiring the input remove the prompt from the console
  140. //////////////////////////////////////////////////////////////
  141. static int GetInput(int PAGELENGTH, bool processingStdin)
  142. {
  143. int counter = 0;
  144. int key;
  145. if (processingStdin) {
  146. Console.Write("-- <more> -- ");
  147. key = Console.Read();
  148. if ((char)key == '\n' ) Console.Write("\n");
  149. }
  150. else {
  151. double temp = 0;
  152. if (fileSize != 0) {
  153. temp = (double) (bytesRead * 100) / (double)fileSize;
  154. }
  155. else {
  156. temp = 100;
  157. }
  158. Console.Write("-- <more> ({0}%) -- ", (int)temp);
  159. key = Console.Read();
  160. }
  161. // get rid of the -- <ENTER> line
  162. if ((char)key == '\n') {
  163. terminal.GenerateAndSendEscapeSequence(Pipe.EscapeCodes.UP);
  164. }
  165. Console.Write("\r");
  166. terminal.GenerateAndSendEscapeSequence(Pipe.EscapeCodes.ERASE_FROM_CURSOR);
  167. if (key == -1) return -1;
  168. switch (Char.ToLower((char)key)) {
  169. case 'q':
  170. return -1;
  171. default:
  172. if ((char)key == '\n') counter = PAGELENGTH ; // advance by 1
  173. break;
  174. }
  175. return counter;
  176. }
  177. // PageText - display text a page at a time
  178. static bool PageText(string! workString,
  179. int PAGELENGTH,
  180. int PAGEWIDTH,
  181. bool processingStdin)
  182. {
  183. string[] lines;
  184. int remainder = 0;
  185. int linesinline = 0;
  186. // Split the line into the requisite number of lines
  187. // needed based on page width
  188. if (workString.Length <= PAGEWIDTH) {
  189. lines = new string[1];
  190. lines[0] = workString;
  191. }
  192. else {
  193. int fullLines = workString.Length / PAGEWIDTH;
  194. remainder = workString.Length % PAGEWIDTH;
  195. linesinline = fullLines;
  196. if (remainder != 0) linesinline++;
  197. lines = new string[linesinline];
  198. int pos = 0;
  199. for (int i = 0; i < fullLines; i++) {
  200. lines[i] = workString.Substring(pos,PAGEWIDTH);
  201. pos += PAGEWIDTH;
  202. }
  203. if (remainder != 0) {
  204. lines[fullLines] = workString.Substring(pos);
  205. }
  206. }
  207. // write the lines out pausing where necessary
  208. for (int i = 0; i < lines.Length; i++) {
  209. string s = lines[i];
  210. assert s!= null;
  211. Console.WriteLine(s);
  212. pageCounter++;
  213. bytesRead += s.Length;
  214. if (pageCounter >= PAGELENGTH) {
  215. pageCounter = GetInput(PAGELENGTH, processingStdin);
  216. if (pageCounter == -1) return false;
  217. }
  218. }
  219. lines = null;
  220. return true;
  221. } // end of PageText
  222. }
  223. }