diff --git a/static/js/paste_create.js b/static/js/paste_create.js
index b1dbb98..bb65d77 100644
--- a/static/js/paste_create.js
+++ b/static/js/paste_create.js
@@ -36,6 +36,93 @@ document.addEventListener('DOMContentLoaded', function () {
expirySelect.addEventListener('change', () =>
localStorage.setItem('preferred_expiry', expirySelect.value));
+ // ── Indent controls (Tabs / Spaces + size) ───────────────────────────────
+ const indentType = document.getElementById('indent_type');
+ const indentSize = document.getElementById('indent_size');
+
+ // Restore saved preferences
+ const savedIndentType = localStorage.getItem('preferred_indent_type');
+ const savedIndentSize = localStorage.getItem('preferred_indent_size');
+ if (savedIndentType) indentType.value = savedIndentType;
+ if (savedIndentSize) indentSize.value = savedIndentSize;
+
+ // Hide size selector when Tabs is chosen (tabs have no width setting in the input)
+ function syncIndentUI() {
+ indentSize.style.display = indentType.value === 'tabs' ? 'none' : '';
+ }
+ syncIndentUI();
+
+ indentType.addEventListener('change', () => {
+ localStorage.setItem('preferred_indent_type', indentType.value);
+ syncIndentUI();
+ });
+ indentSize.addEventListener('change', () =>
+ localStorage.setItem('preferred_indent_size', indentSize.value));
+
+ // ── Tab key handler ──────────────────────────────────────────────────────
+ textarea.addEventListener('keydown', function (e) {
+ if (e.key !== 'Tab') return;
+ e.preventDefault();
+
+ const useTab = indentType.value === 'tabs';
+ const indent = useTab ? '\t' : ' '.repeat(parseInt(indentSize.value, 10));
+
+ const start = this.selectionStart;
+ const end = this.selectionEnd;
+ const value = this.value;
+
+ if (start === end) {
+ // No selection — insert indent at cursor
+ this.value = value.slice(0, start) + indent + value.slice(end);
+ this.selectionStart = this.selectionEnd = start + indent.length;
+ } else {
+ // Multi-line selection — indent / unindent each line
+ const lineStart = value.lastIndexOf('\n', start - 1) + 1;
+ const selectedText = value.slice(lineStart, end);
+ const lines = selectedText.split('\n');
+
+ let newText;
+ if (e.shiftKey) {
+ // Unindent: remove one level of indent from the start of each line
+ newText = lines.map(line => {
+ if (useTab) return line.startsWith('\t') ? line.slice(1) : line;
+ const spaces = parseInt(indentSize.value, 10);
+ return line.startsWith(' '.repeat(spaces))
+ ? line.slice(spaces)
+ : line.replace(/^ +/, m => m.slice(Math.min(m.length, spaces)));
+ }).join('\n');
+ } else {
+ // Indent: prepend indent to each line
+ newText = lines.map(line => indent + line).join('\n');
+ }
+
+ const removed = selectedText.length - newText.length; // negative when indenting
+ this.value = value.slice(0, lineStart) + newText + value.slice(end);
+ this.selectionStart = lineStart;
+ this.selectionEnd = lineStart + newText.length;
+ }
+ });
+
+ // ── Enter key: auto-indent to match previous line ────────────────────────
+ textarea.addEventListener('keydown', function (e) {
+ if (e.key !== 'Enter') return;
+ e.preventDefault();
+
+ const start = this.selectionStart;
+ const value = this.value;
+
+ // Find the beginning of the current line
+ const lineStart = value.lastIndexOf('\n', start - 1) + 1;
+ const currentLine = value.slice(lineStart, start);
+
+ // Grab the leading whitespace (spaces or tabs) of the current line
+ const leadingWhitespace = currentLine.match(/^(\s*)/)[1];
+
+ const insert = '\n' + leadingWhitespace;
+ this.value = value.slice(0, start) + insert + value.slice(this.selectionEnd);
+ this.selectionStart = this.selectionEnd = start + insert.length;
+ });
+
// ── Ctrl/Cmd+S shortcut ──────────────────────────────────────────────────
document.addEventListener('keydown', e => {
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
diff --git a/templates/index.html b/templates/index.html
index 407de5e..c78c4a4 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -6,6 +6,15 @@
{% block nav_actions %}
+
+