Showing posts with label tech tips. Show all posts
Showing posts with label tech tips. Show all posts

Thursday, January 11, 2007

Seekable LineReader

Recently I need a way in StreamReader to get the position of a line which can be stored and later skip to that line directly. C# StreamReader API does not have any way of doing this, except calling Read() repeatedly and then doing the processing yourself. Which is clumsy. Note that, StreamReader.BaseStream.Position might be wrong due to underlying bufferring. I thought this should be a fairly common requirement and indeed, many people have same question on google groups or other forums. No good answer though. One reason is, such a thing does not really make sense for arbitrary Streams, since it might not be possible to seek in them.

I needed such a thing desparately, so I created an interface:
namespace System.IO {

// A linereader interface
public interface LineReader {

// Returns a position marker, which can be used to navigate the lines.
// Some implementations may only allow moving in the forward direction.
// Might be different from line number or file offset.
// Should only be used for traversal.
long Position {
get;
set;
}

// Reads and returns the next line, null if EOF
string ReadLine ();

// Reads the next line and returns a stringbuilder containing the line
// The StringBuilder returned could be the same one used while reading,
// so it should not be modified and its content might change when readline
// is next called.
// This is the most worst horriblest API I ever designed, for sake of speed
// And thats why this should not be a public API.
StringBuilder ReadLineAsStringBuilder ();

// Skips the next line, return true if successful
bool SkipLine ();

// Skips required number of lines; returns actual number of lines skipped
long SkipLines (long n);

// Close the reader
void Close ();
}
}
Beagle source contains the interface and several implementations.

Monday, July 24, 2006

Ed-ed

Who knew that 'vi' was based on the legendary editor 'ed'. Or, inspired by. Being a die-hard vi-fanboy, it took me no time to get used to ed, at least being able to compose/edit/save simple documents. An ed-documentation page at BUCS provided me with a quick howto listing (all) the important commands. Actually, all the commands, since there are only a few of them. Unlike vi, where you have to know thousands of commands. Its wonderful how much simpler life becomes if we focus on functionality alone without caring for presentation.
If you are comfortable with vi (or even with vim or with gvim but dont use the menu too much), I suggest you to give ed a try. You'll love it.

(From the documentation page) An ed-quickcard:

All the standard ed commands are listed below, together with a brief description of their function. Those commands which may be given with line addresses are shown with the default values of the addresses in the first column. For example, 1,$ for w means that the write command may be given with one or two line addresses to specify a particular line or a range of lines to be written to a file, and that if no address is given the default address is 1,$ (ie, all the lines in the buffer are written out). The default address . represents the current line and $ represents the last line in the buffer.


The Input Commands

Default Address Command Function
. a text Append input text after addressed
line.The last line input becomes the
current line.
.,. c text Replace addressed lines with input
text. The last line input becomes the
current line.
. i text Insert input text before the addressed
line. The last line input becomes the
current line.

The Edit Commands

Default Address Command Function
.,. d Delete the addressed lines from
the buffer. The line after the
last deleted line becomes the
current line.
e file Delete the buffer contents then
read file into the buffer. The
last line read in becomes the
current line.
E file As for e but no warning is given
if a modified buffer has not been
written out.
f file Print current remembered filename
if file not specified, otherwise
set it to file.
1,$ g/R/cmds Perform cmds on all addressed lines
matching regular expression R. Last
line in which a match was found
becomes the current line.
.,.+1 j Join together all the addressed
lines. The resulting line becomes
the current line.
. kx Mark the addressed line with the
single lower case character name x.
The addressed line becomes the
current line.
.,. l List the addressed lines showing
non-printing characters and folding
long lines. The last line listed
becomes the current line.
.,. mA Move addressed lines to follow line
whose address is A. The last line
moved becomes the current line.
.,. p Print the addressed lines. The last
line displayed becomes current line.
q Exit from the editor.
Q Exit from the editor with no warning
if a modified buffer has not been
written out.
$ r file Read file into the buffer after
addressed line. The last line read in
becomes the current line.
.,. s/R/S/{g} Substitute string S for the regular
expression R in the addressed lines.
If g specified substitution is made
globally throughout addressed lines.
.,. tA Copy the addressed lines to follow
line whose address is A. Last line of
the copy becomes the current line.
.,. u Undo the effect of the previous
substitute command. The current line is
reset to its value before that command.
1,$ v/R/cmds Perform cmds on all addressed lines
not matching regular expression R.
1,$ w file Write the addressed lines into named
file. The current line is not reset.
1,$ W file Append the addressed lines to the
named file. Current line not reset.
x Decrypt or encrypt the text according
to an input key. The current line is
not reset.
$ = Print the line number of the addressed
line The current line is not reset.
|cmnd Pass cmnd to the UNIX shell to be
executed. Current line is not reset.
A Where A is one of the legal address
forms listed above: locate addressed
line and display it. The addressed line
becomes current line.
.+1 newline Print the next line. Addressed line
/linefeed becomes the current line.


Obligatory jokes link (not a PJ).