|
| 1 | +# UnsignedInt TUI |
| 2 | + |
| 3 | +## Purpose |
| 4 | + |
| 5 | +`data_structures/tui/unsigned_int_app.py` is an interactive terminal app for exploring how unsigned integers are represented in binary, hexadecimal, and octal. It lets you manipulate individual bits, shift and rotate, apply logical operations, and immediately see how every change ripples through all three representations simultaneously. |
| 6 | + |
| 7 | +The visualization panel shows three aligned rows — binary, hex, and octal — at all times. Group boundaries in the binary row are colour-coded so you can see where octal groups (every 3 bits) and hex nibbles (every 4 bits) begin and end, including positions where both coincide (every 12 bits). |
| 8 | + |
| 9 | +## Running the App |
| 10 | + |
| 11 | +Install dependencies first: |
| 12 | + |
| 13 | +```bash |
| 14 | +make install |
| 15 | +``` |
| 16 | + |
| 17 | +Run the TUI: |
| 18 | + |
| 19 | +```bash |
| 20 | +make run-uint-app |
| 21 | +``` |
| 22 | + |
| 23 | +You can also run the module directly with an initial bit width: |
| 24 | + |
| 25 | +```bash |
| 26 | +.venv/bin/python -m data_structures.tui.unsigned_int_app |
| 27 | +.venv/bin/python -m data_structures.tui.unsigned_int_app --size 16 |
| 28 | +``` |
| 29 | + |
| 30 | +## Command-Line Options |
| 31 | + |
| 32 | +### `--size 4|8|16|32|64` |
| 33 | + |
| 34 | +Set the initial bit width (default: `8`). You can also change the width at runtime with `/size`. |
| 35 | + |
| 36 | +## Layout |
| 37 | + |
| 38 | +The interface has three parts: |
| 39 | + |
| 40 | +1. **Visualization panel** (top) — the current value shown as aligned binary, hex, and octal box rows, plus a summary line with the decimal, binary, octal, and hex values. |
| 41 | +2. **Log panel** (middle) — records each command's result, overflow warnings, and execution time. |
| 42 | +3. **Input box** (bottom) — where commands are entered. |
| 43 | + |
| 44 | +### Boundary colour key |
| 45 | + |
| 46 | +In the binary row: |
| 47 | + |
| 48 | +| Colour | Separator | Meaning | |
| 49 | +|---|---|---| |
| 50 | +| Yellow | `┃` | Octal group boundary (every 3 bits from the right) | |
| 51 | +| Cyan | `║` | Hex group boundary (every 4 bits from the right) | |
| 52 | +| Magenta | `┃` | Both coincide (LCM = 12 bits) | |
| 53 | + |
| 54 | +## Commands |
| 55 | + |
| 56 | +### Value |
| 57 | + |
| 58 | +| Command | Description | |
| 59 | +|---|---| |
| 60 | +| `/set N` | Set the value; accepts decimal, `0b` binary, `0o` octal, or `0x` hex | |
| 61 | +| `/random` | Set a random value uniformly across the full bit range | |
| 62 | +| `/clear` | Reset all bits to zero | |
| 63 | +| `/size 4\|8\|16\|32\|64` | Change the bit width (resets value to zero) | |
| 64 | + |
| 65 | +### Display |
| 66 | + |
| 67 | +| Command | Description | |
| 68 | +|---|---| |
| 69 | +| `/show` | Display the value in all four bases | |
| 70 | +| `/dec` | Display decimal value | |
| 71 | +| `/bin` | Display binary value | |
| 72 | +| `/oct` | Display octal value | |
| 73 | +| `/hex` | Display hexadecimal value | |
| 74 | + |
| 75 | +### Bit operations |
| 76 | + |
| 77 | +| Command | Description | |
| 78 | +|---|---| |
| 79 | +| `/set-bit POS` | Set the bit at position `POS` to 1 (0 = LSB) | |
| 80 | +| `/reset-bit POS` | Set the bit at position `POS` to 0 | |
| 81 | +| `/toggle-bit POS` | Flip the bit at position `POS` | |
| 82 | + |
| 83 | +### Shift, rotate, and logical |
| 84 | + |
| 85 | +| Command | Description | |
| 86 | +|---|---| |
| 87 | +| `/shl N` | Shift left N bits; overflow is reported in yellow if any 1-bits are lost | |
| 88 | +| `/shr N` | Logical shift right N bits; zeros fill from the left | |
| 89 | +| `/rol N` | Rotate left N bits; bits wrap around, nothing is lost | |
| 90 | +| `/ror N` | Rotate right N bits; bits wrap around, nothing is lost | |
| 91 | +| `/not` | Bitwise complement (flip all bits within the current width) | |
| 92 | +| `/and CONST` | Bitwise AND with a constant | |
| 93 | +| `/or CONST` | Bitwise OR with a constant | |
| 94 | +| `/xor CONST` | Bitwise XOR with a constant | |
| 95 | + |
| 96 | +Constants for `/and`, `/or`, `/xor` accept any Python-style prefix: `0b101010`, `0o17`, `0xFF`, or plain decimal. The constant must fit within the current bit width. |
| 97 | + |
| 98 | +### Group operations |
| 99 | + |
| 100 | +| Command | Description | |
| 101 | +|---|---| |
| 102 | +| `/set-octal GRP DIGIT` | Set the octal group at `GRP` (0 = rightmost) to `DIGIT` (0–7) | |
| 103 | +| `/set-hex GRP DIGIT` | Set the hex nibble at `GRP` (0 = rightmost) to `DIGIT` (0–15) | |
| 104 | + |
| 105 | +### Session |
| 106 | + |
| 107 | +| Command | Description | |
| 108 | +|---|---| |
| 109 | +| `/save PATH` | Save the current bit width and value to a JSON file | |
| 110 | +| `/load PATH` | Restore the bit width and value from a saved file | |
| 111 | +| `/undo` | Restore the previous state | |
| 112 | +| `/redo` | Reapply the most recently undone state | |
| 113 | +| `/help` | Show the command summary | |
| 114 | +| `/quit` or `Ctrl+D` | Exit the app | |
| 115 | + |
| 116 | +## Typical Session |
| 117 | + |
| 118 | +```text |
| 119 | +/size 8 |
| 120 | +/set 0b10110101 |
| 121 | +/show |
| 122 | +/set-bit 0 |
| 123 | +/toggle-bit 7 |
| 124 | +/not |
| 125 | +/shl 1 |
| 126 | +/shr 1 |
| 127 | +/rol 4 |
| 128 | +/and 0xF0 |
| 129 | +/or 0x0F |
| 130 | +/xor 0xAA |
| 131 | +/set-octal 0 7 |
| 132 | +/set-hex 1 10 |
| 133 | +/random |
| 134 | +/save /tmp/session.json |
| 135 | +/undo |
| 136 | +/redo |
| 137 | +/size 16 |
| 138 | +/set 0xABCD |
| 139 | +/load /tmp/session.json |
| 140 | +/quit |
| 141 | +``` |
| 142 | + |
| 143 | +## Overflow Reporting |
| 144 | + |
| 145 | +`/shl N` checks whether any 1-bits will be lost before shifting. If so, the log records a yellow warning showing how many bits were shifted out and their combined value: |
| 146 | + |
| 147 | +``` |
| 148 | +shl(1) → 0b01100100 dec=100 |
| 149 | +overflow: 1 bit(s) shifted out — lost value 0b1 |
| 150 | +``` |
| 151 | + |
| 152 | +Rotate operations (`/rol`, `/ror`) never produce overflow because bits wrap around. |
| 153 | + |
| 154 | +## Errors and Edge Cases |
| 155 | + |
| 156 | +- `/set` raises an error if the value exceeds the current bit width's maximum. |
| 157 | +- `/set-bit`, `/reset-bit`, `/toggle-bit` require a position in `[0, size-1]`. |
| 158 | +- `/set-octal` validates that the digit fits within the group; the MSB group may have a smaller maximum when phantom bits are present. |
| 159 | +- `/set-hex` validates that the digit is in `[0, 15]` and the group index is valid. |
| 160 | +- `/and`, `/or`, `/xor` require the constant to fit within the current bit width. |
| 161 | +- `/shl` and `/shr` with `N >= size` clear the value (with overflow reported for `/shl` if the value was non-zero). |
| 162 | +- `/load` restores both the saved bit width and the saved value, replacing the current configuration. |
| 163 | +- Any mutating command after `/undo` clears the redo history. |
| 164 | + |
| 165 | +## Verification |
| 166 | + |
| 167 | +The data structure and rendering logic are covered by `tests/test_unsigned_int.py` (60 tests). TUI-level construction, snapshot, and parser behaviour are covered by `tests/test_unsigned_int_app.py` (11 tests). |
0 commit comments