diff --git a/crop.cpp b/crop.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00c23d0fab2a506ba544a22d9d122ca6350747bd
--- /dev/null
+++ b/crop.cpp
@@ -0,0 +1,199 @@
+#include <deque>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <cstring>
+#include "simple/file.hpp"
+#include "simple/support/enum.hpp"
+
+using namespace simple;
+using namespace std::literals;
+using std::string;
+
+enum class Options
+{
+	Padding,
+	Color,
+	Source,
+	Format,
+	Invalid
+};
+using Option = support::MappedEnum<Options, Options::Invalid, 2>;
+template <> Option::Guts::map_type Option::Guts::map
+{{
+	{ "-p"s, "--padding"s },
+	{ "-c"s, "--color"s },
+	{ "-i"s, "--source"s },
+	{ "-f"s, "--format"s },
+}};
+
+enum class Formats
+{
+	PlainText,
+	OneLine,
+	Hex,
+	Invalid
+};
+using Format = support::MappedEnum<Formats, Formats::Invalid>;
+template <> Format::Guts::map_type Format::Guts::map
+{{
+	{ "plain"s },
+	{ "one-line"s },
+	{ "hex"s },
+}};
+
+enum class Colors
+{
+	Black,
+	Red,
+	Green,
+	Yellow,
+	Blue,
+	Magenta,
+	Cyan,
+	White,
+	Invalid
+};
+using Color = support::MappedEnum<Colors, Colors::Invalid>;
+template <> Color::Guts::map_type Color::Guts::map
+{{
+	{ "black"s },
+	{ "red"s },
+	{ "green"s },
+	{ "yellow"s },
+	{ "blue"s },
+	{ "magenta"s },
+	{ "cyan"s },
+	{ "white"s }
+}};
+
+std::pair<size_t,size_t> stoull_pair(const std::string& str)
+{
+	size_t separator;
+	auto first = std::stoull(str, &separator, 0);
+	auto second = std::stoull(str.substr(separator+1), nullptr, 0);
+	if(':' == str[separator])
+		second += first;
+	return {first, second};
+}
+
+template <typename Iterator>
+struct iterator_range
+{
+	using iterator_type = Iterator;
+	using array_type = std::array<iterator_type, 2>;
+	iterator_type& begin() { return raw[0]; }
+	iterator_type& end() { return raw[1]; }
+	const iterator_type& begin() const { return raw[0]; }
+	const iterator_type& end() const { return raw[1]; }
+
+	array_type raw;
+};
+template <typename Iterator>
+iterator_range<Iterator> make_iterator_range(Iterator begin, Iterator end)
+{
+	return {begin, end};
+}
+using const_range = iterator_range<file::buffer<>::const_iterator>;
+
+void print(const_range range, Format format, Color color = Colors::Invalid)
+{
+	auto cout_flags = std::cout.flags();
+	std::cout << std::hex;
+	if(Colors::Invalid != color)
+		std::cout << "\33[4" << char('0' + (int)Colors(color)) << 'm';
+	switch(format)
+	{
+		case Formats::Hex:
+			for(auto&& c : range)
+			{
+				if(c <= 0xf)
+					std::cout << '0';
+				std::cout << +c;
+			}
+		break;
+		case Formats::OneLine:
+			for(auto&& c : range)
+			{
+				auto cc = '\n' == c ? 'n' : '\r' == c ? 'r' : c;
+				if(cc != c)
+					std::cout << "\33[7m" << cc << "\33[27m";
+				else
+					std::cout << c;
+			}
+		break;
+		default:
+			for(auto&& c : range)
+				std::cout << c;
+	}
+	if(Colors::Invalid != color)
+		std::cout << "\33[0m";
+	std::cout.flags(cout_flags);
+}
+
+void crop(const string& filename, const string& range, Color color, size_t padding, Format format)
+{
+	auto p = stoull_pair(range);
+	auto source = file::dump(file::bropex(filename));
+	auto lower = std::min(source.begin() + p.first, source.end());
+	auto upper = std::min(source.begin() + p.second, source.end());
+	auto left = lower - std::min(p.first, padding);
+	auto right = upper + std::min<size_t>(source.end() - upper, padding);
+	print({left , lower}, format);
+	print({lower, upper}, format, color);
+	print({upper, right}, format);
+}
+
+void process_arguments(std::deque<string> args)
+{
+	string filename;
+	Color color;
+	Format format;
+	size_t padding = 0;
+	args.pop_front();
+	while(!args.empty())
+	{
+		switch(Option(args.front()))
+		{
+
+			case Options::Padding:
+				args.pop_front();
+				padding = stoull(args.at(0), nullptr, 0);
+			break;
+
+			case Options::Color:
+				args.pop_front();
+				color = Color(args.at(0));
+			break;
+
+			case Options::Source:
+				args.pop_front();
+				filename = args.at(0);
+			break;
+
+			case Options::Format:
+				args.pop_front();
+				format = Format(args.at(0));
+			break;
+
+			default:
+				crop(filename, args.front(), color, padding, format);
+				std::cout << '\n';
+			break;
+
+		}
+		args.pop_front();
+	}
+}
+
+int main(int argc, char const* argv[]) try
+{
+	process_arguments({argv, argv + argc});
+	return 0;
+}
+catch(...)
+{
+	if(errno)
+		std::cout << "Oh nooo! " << std::strerror(errno) << '\n';
+	throw;
+}