aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Truncater.java150
-rw-r--r--ponysaytruncater.c174
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;
+}
+