ASCII Table — Ruby source
A searchable, filterable reference for all 128 ASCII code points. See the decimal, hex, octal, and binary form of every character, narrow to printable characters only, clamp the code-point range, and click any row to copy. Runs 100% client-side.
This is the Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.
# frozen_string_literal: true
# ASCII Table — pure logic (Ruby port): the 128-entry ASCII reference table with
# search and range filters.
#
# Language: Ruby 3.2 — standard library only (core classes; no gems).
# Source: CosmoDev polyglot showcase port; canonical = src/lib/ascii-table.ts
# + this tool's python.py / rust.rs.
# License: display source — part of CosmoDev's polyglot tool pages.
#
# Each of the 128 ASCII code points is described by its decimal / hex / octal /
# binary forms, a display glyph, a human name, whether it is printable, whether
# it is a control character, and (for control chars that have one) a C-style
# escape sequence.
module AsciiTable
# A single ASCII code point and its derived representations.
#
# dec — Integer, decimal code point, 0–127.
# hex — String, uppercase hex, e.g. "0x41".
# oct — String, zero-padded 3-digit octal, e.g. "101".
# binary — String, zero-padded 8-bit binary, e.g. "01000001".
# char — String, display glyph: the literal char for printables, a
# control-picture glyph otherwise.
# name — String, human-readable name, e.g. "Line Feed (LF)".
# printable — true for 32–126 (visible or space).
# control — true for 0–31 and 127.
# escape — String, C-style escape for control chars that have one
# (e.g. "\\n"); nil otherwise.
Entry = Struct.new(
:dec, :hex, :oct, :binary, :char, :name, :printable, :control, :escape,
keyword_init: true
)
# Official ASCII control-character names (0–31 and 127).
CONTROL_NAMES = {
0 => "Null (NUL)",
1 => "Start of Heading (SOH)",
2 => "Start of Text (STX)",
3 => "End of Text (ETX)",
4 => "End of Transmission (EOT)",
5 => "Enquiry (ENQ)",
6 => "Acknowledge (ACK)",
7 => "Bell (BEL)",
8 => "Backspace (BS)",
9 => "Horizontal Tab (HT)",
10 => "Line Feed (LF)",
11 => "Vertical Tab (VT)",
12 => "Form Feed (FF)",
13 => "Carriage Return (CR)",
14 => "Shift Out (SO)",
15 => "Shift In (SI)",
16 => "Data Link Escape (DLE)",
17 => "Device Control 1 (DC1)",
18 => "Device Control 2 (DC2)",
19 => "Device Control 3 (DC3)",
20 => "Device Control 4 (DC4)",
21 => "Negative Acknowledge (NAK)",
22 => "Synchronous Idle (SYN)",
23 => "End of Transmission Block (ETB)",
24 => "Cancel (CAN)",
25 => "End of Medium (EM)",
26 => "Substitute (SUB)",
27 => "Escape (ESC)",
28 => "File Separator (FS)",
29 => "Group Separator (GS)",
30 => "Record Separator (RS)",
31 => "Unit Separator (US)",
127 => "Delete (DEL)"
}.freeze
# C-style escape sequences for the control chars that have a standard/common
# one. Each value is the literal 2-character source token (backslash + letter).
ESCAPES = {
0 => "\\0",
7 => "\\a",
8 => "\\b",
9 => "\\t",
10 => "\\n",
11 => "\\v",
12 => "\\f",
13 => "\\r",
27 => "\\e"
}.freeze
# Names for printable punctuation & symbols; letter and digit names are derived.
SYMBOL_NAMES = {
32 => "Space",
33 => "Exclamation mark",
34 => "Quotation mark",
35 => "Number sign",
36 => "Dollar sign",
37 => "Percent sign",
38 => "Ampersand",
39 => "Apostrophe",
40 => "Left parenthesis",
41 => "Right parenthesis",
42 => "Asterisk",
43 => "Plus sign",
44 => "Comma",
45 => "Hyphen / Minus",
46 => "Full stop",
47 => "Slash",
58 => "Colon",
59 => "Semicolon",
60 => "Less-than sign",
61 => "Equals sign",
62 => "Greater-than sign",
63 => "Question mark",
64 => "At sign",
91 => "Left bracket",
92 => "Backslash",
93 => "Right bracket",
94 => "Circumflex / Caret",
95 => "Underscore",
96 => "Grave accent",
123 => "Left brace",
124 => "Vertical bar",
125 => "Right brace",
126 => "Tilde"
}.freeze
class << self
# Derive a name for a printable letter or digit.
def letter_name(code)
case code
when 48..57 then "Digit #{code - 48}" # '0'..'9'
when 65..90 then "Uppercase #{code.chr}" # 'A'..'Z'
when 97..122 then "Lowercase #{code.chr}" # 'a'..'z'
else code.chr
end
end
# Build a single entry from its code point (0–127).
def make_entry(code)
control = code <= 31 || code == 127
# Control-picture glyph: U+2400 for 0–31, U+2421 ("symbol for delete") for DEL.
char = if control
(code == 127 ? 0x2421 : 0x2400 + code).chr(Encoding::UTF_8)
else
code.chr(Encoding::UTF_8)
end
name = if control
CONTROL_NAMES.fetch(code)
else
SYMBOL_NAMES.fetch(code) { letter_name(code) }
end
Entry.new(
dec: code,
hex: format("0x%02X", code),
oct: format("%03o", code),
binary: format("%08b", code),
char: char,
name: name,
printable: !control,
control: control,
escape: control ? ESCAPES[code] : nil
)
end
# The full 128-entry ASCII table, indexed by code point.
#
# Built once and cached for the process lifetime. The array is frozen and
# every entry is immutable by convention, so sharing it is safe for all
# callers (the Ruby equivalent of Rust's OnceLock).
def entries
@entries ||= Array.new(128) { |i| make_entry(i) }.freeze
end
# Look up a single entry by code point.
#
# Returns nil for out-of-range or non-Integer input. Ruby's true/false are
# not Integers, so the explicit boolean rejection the Python port needs is
# unnecessary here — Integer#is_a? already excludes them.
def get_entry(code)
return nil unless code.is_a?(Integer)
return nil unless code.between?(0, 127)
entries[code]
end
# Filter the table.
#
# `query` is a case-insensitive substring matched against dec / hex / oct /
# binary / name / char / escape. `printable_only` hides controls.
# `min` / `max` clamp the decimal range (defaults 0–127).
def filter_table(query: "", printable_only: false, min: 0, max: 127)
q = query.to_s.strip.downcase
entries.select do |e|
next false if printable_only && !e.printable
next false if e.dec < min || e.dec > max
next true if q.empty?
haystacks = [
e.dec.to_s, e.hex.downcase, e.oct, e.binary,
e.name.downcase, e.char.downcase, e.escape.to_s
]
haystacks.any? { |h| h.include?(q) }
end
end
end
end
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →