diff options
-rw-r--r-- | Truncater.java | 150 | ||||
-rw-r--r-- | ponysaytruncater.c | 174 |
2 files changed, 174 insertions, 150 deletions
diff --git a/Truncater.java b/Truncater.java deleted file mode 100644 index a5eb99d..0000000 --- a/Truncater.java +++ /dev/null @@ -1,150 +0,0 @@ -import java.io.*; - -public class Truncater -{ - public static void main(final String... args) throws IOException - { - final int width; - if ((width = getWidth()) > 15) //sanity - { - final OutputStream stdout = new BufferedOutputStream(System.out); - OutputStream out = new OutputStream() - { - /** - * The number of column on the current line - */ - private int x = 0; - - /** - * Escape sequence state - */ - private int esc = 0; - - /** - * Last bytes as written - */ - private boolean ok = true; - - - /** - * {@inheritDoc} - */ - @Override - public void write(final int b) throws IOException - { - if (this.esc == 0) - { - if (b == '\n') - { - if (x >= width) - { - write('\033'); - write('['); - write('4'); - write('9'); - write('m'); - } - this.x = -1; - } - else if (b == '\t') - { - int nx = 8 - (x & 7); - for (int i = 0; i < nx; i++) - write(' '); - return; //(!) - } - else if (b == '\033') - this.esc = 1; - } - else if (this.esc == 1) - { - if (b == '[') this.esc = 2; - else if (b == ']') this.esc = 3; - else this.esc = 10; - } - else if (this.esc == 2) - { - if ((('a' <= b) && (b <= 'z')) || (('A' <= b) && (b <= 'Z'))) - this.esc = 10; - } - else if ((this.esc == 3) && (b == 'P')) - { - this.esc = ~0; - } - else if (this.esc < 0) - { - this.esc--; - if (this.esc == ~7) - this.esc = 10; - } - else - this.esc = 10; - - if ((x < width) || (this.esc != 0) || (ok && ((b & 0xC0) == 0x80))) - { - stdout.write(b); - if (this.esc == 0) - if ((b & 0xC0) != 0x80) - x++; - ok = true; - } - else - ok = false; - if (this.esc == 10) - this.esc = 0; - } - - /** - * {@inheritDoc} - */ - @Override - public void flush() throws IOException - { - stdout.flush(); - } - }; - - System.setOut(new PrintStream(out)); - } - - - InputStream in = System.in; - OutputStream out = System.out; - - for (int d; (d = in.read()) != -1;) - out.write(d); - out.flush(); - } - - /** - * Gets the width of the terminal - * - * @return The width of the terminal - */ - public static int getWidth() - { - try - { - Process process = (new ProcessBuilder("/bin/sh", "-c", "tput cols 2> " + (new File("/dev/stderr")).getCanonicalPath())).start(); - String rcs = new String(); - InputStream stream = process.getInputStream(); - int c; - while (((c = stream.read()) != '\n') && (c != -1)) - rcs += (char)c; - try - { - stream.close(); - } - catch (final Throwable err) - { - //Ignore - } - return Integer.parseInt(rcs); - } - catch (final Throwable err) - { - return -1; - } - } -} - diff --git a/ponysaytruncater.c b/ponysaytruncater.c new file mode 100644 index 0000000..9c7191e --- /dev/null +++ b/ponysaytruncater.c @@ -0,0 +1,174 @@ +/** + * ponysaytruncater — Output truncater used by ponysay to stop large ponies from being printed badly. + * + * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + * See COPYING for details + */ +#include <stdio.h> + + +#define String char* +#define boolean char + +#define true 1 +#define false 0 + + + +/** + * Stdin file descriptor ID + */ +#define STDIN 0 + + + +/** + * The number of columns on the current line + */ +static int x = 0; + +/** + * Escape sequence state + */ +static int esc = 0; + +/** + * Last bytes as written + */ +static boolean ok = true; + + + + +void write(char b, int width); +int toInt(String string); + + + +/** + * <p>Mane method!</p> + * <p> + * The only argument, in addition to the executed file, + * should be the width of the terminal which you get by + * adding <code>`tput cols || echo 0`</code> as and argument. + * </p> + * + * @param argc The number of startup arguments + * @param argv The startup arguments, the first is the file itself + * + * @author Mattias Andrée, maandree@kth.se + */ +void main(int argc, String* argv) +{ + int width = 0; + if (argc > 1) + width = toInt(*(argv + 1)); + + char b = 0; + + if (width > 15) //sanity + while (read(STDIN, &b, 1)) + write(b, width); + else + while (read(STDIN, &b, 1)) + printf("%c", b); +} + + +/** + * Writes a character to stdout, iff it fits within the terminal + * + * @param b The character (byte) to write + * @param width The width of the terminal + */ +void write(char b, int width) +{ + int i; + char nx; + + if (esc == 0) + { + if (b == '\n') + { + if (x >= width) + { + // Reset background colour + write('\e', width); + write('[', width); + write('4', width); + write('9', width); + write('m', width); + } + x = -1; + } + else if (b == '\t') + { + // Tab to next pos ≡₈ 0 + nx = 8 - (x & 7); + for (i = 0; i < nx; i++) + write(' ', width); + return; //(!) + } + else if (b == '\e') + esc = 1; + } + else if (esc == 1) + { + if (b == '[') esc = 2; //CSI ends with a letter, m is for colour + else if (b == ']') esc = 3; //OSI, OSI P is for palett editing in Linux VT + else esc = 10; //Nothing to see here, move along + } + else if (esc == 2) + { + if ((('a' <= b) && (b <= 'z')) || (('A' <= b) && (b <= 'Z'))) + esc = 10; + } + else if ((esc == 3) && (b == 'P')) + { + esc = ~0; + } + else if (esc < 0) + { + esc--; + if (esc == ~7) + esc = 10; + } + else + esc = 10; + + if ( // Can be printed: + (x < width) || // within bounds ∨ + (esc != 0) || // ∨ escape sequence ∨ + (ok && ((b & 0xC0) == 0x80))) // ∨ last with printed ∧ not first byte in character + { + printf("%c", b); + if ((esc == 0) && ((b & 0xC0) != 0x80)) // Count up columns of not in escape sequnce and + x++; // the byte is not the first byte in the character + ok = true; + } + else + ok = false; + + if (esc == 10) + esc = 0; +} + + +/** + * Converts a string to an integer + * + * @param string The string to convert + * @return The integer represented by the string + */ +int toInt(String string) +{ + int rc = 0; + String str = string; + char c = 0; + + while ((c = *str++) != 0) + rc = (rc << 1) + (rc << 3) - (c & 15); + + return -rc; +} + |