Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 76 additions & 2 deletions layouts/partials/scripts.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,76 @@
<!-- Code for copy to clipboard button -->
<script>
// Smart copy processing function to handle shell prompts
function smartCopyProcessing(text) {
const lines = text.split('\n');
const processedLines = [];
let inMultiLineCommand = false;
let currentCommand = '';

// Regex patterns for different shell prompts
const promptPatterns = [
/^\s*\$\s+(.+)$/, // $ command
/^\s*#\s+(.+)$/, // # command (root)
/^\s*[\w.-]+>\s+(.+)$/, // redis-cli>, rladmin>, etc.
/^\s*[\d.:]+>\s+(.+)$/, // 127.0.0.1:6379> command
];

for (let line of lines) {
let isPromptLine = false;
let commandPart = '';

// Check if this line matches any prompt pattern
for (let pattern of promptPatterns) {
const match = line.match(pattern);
if (match) {
isPromptLine = true;
commandPart = match[1];
break;
}
}

if (isPromptLine) {
// Handle multi-line commands with backslash continuation
if (commandPart.endsWith('\\')) {
inMultiLineCommand = true;
currentCommand = commandPart.slice(0, -1).trim() + ' ';
} else {
if (inMultiLineCommand) {
// End of multi-line command
currentCommand += commandPart;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
} else {
// Single line command
processedLines.push(commandPart);
}
}
} else if (inMultiLineCommand) {
// Continuation line of a multi-line command
const trimmedLine = line.trim();
if (trimmedLine.endsWith('\\')) {
currentCommand += trimmedLine.slice(0, -1).trim() + ' ';
} else {
currentCommand += trimmedLine;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
}
} else {
// Regular line (output, comments, etc.) - copy as-is
processedLines.push(line);
}
}

// Handle case where multi-line command was not completed
if (inMultiLineCommand && currentCommand) {
processedLines.push(currentCommand.trim());
}

return processedLines.join('\n');
}

document.addEventListener("DOMContentLoaded", function () {

// Add copy buttons to code blocks (but skip those inside codetabs)
Expand Down Expand Up @@ -48,9 +119,12 @@
// Handle copy logic
button.addEventListener('click', () => {
const lines = block.querySelectorAll('span.cl');
const text = Array.from(lines).map(line => line.textContent).join('');
const rawText = Array.from(lines).map(line => line.textContent).join('');

// Smart copy: detect shell prompts and extract commands
const processedText = smartCopyProcessing(rawText);

navigator.clipboard.writeText(text).then(() => {
navigator.clipboard.writeText(processedText).then(() => {
tooltip.style.display = 'block';
setTimeout(() => {
tooltip.style.display = 'none';
Expand Down
84 changes: 79 additions & 5 deletions static/js/agent-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -823,27 +823,101 @@ public class ${formData.agentName.replace(/\s+/g, '')}
return `${cleanName}_agent${extensions[formData.programmingLanguage]}`;
}

// Smart copy processing function to handle shell prompts
function smartCopyProcessing(text) {
const lines = text.split('\n');
const processedLines = [];
let inMultiLineCommand = false;
let currentCommand = '';

// Regex patterns for different shell prompts
const promptPatterns = [
/^\s*\$\s+(.+)$/, // $ command
/^\s*#\s+(.+)$/, // # command (root)
/^\s*[\w.-]+>\s+(.+)$/, // redis-cli>, rladmin>, etc.
/^\s*[\d.:]+>\s+(.+)$/, // 127.0.0.1:6379> command
];

for (let line of lines) {
let isPromptLine = false;
let commandPart = '';

// Check if this line matches any prompt pattern
for (let pattern of promptPatterns) {
const match = line.match(pattern);
if (match) {
isPromptLine = true;
commandPart = match[1];
break;
}
}

if (isPromptLine) {
// Handle multi-line commands with backslash continuation
if (commandPart.endsWith('\\')) {
inMultiLineCommand = true;
currentCommand = commandPart.slice(0, -1).trim() + ' ';
} else {
if (inMultiLineCommand) {
// End of multi-line command
currentCommand += commandPart;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
} else {
// Single line command
processedLines.push(commandPart);
}
}
} else if (inMultiLineCommand) {
// Continuation line of a multi-line command
const trimmedLine = line.trim();
if (trimmedLine.endsWith('\\')) {
currentCommand += trimmedLine.slice(0, -1).trim() + ' ';
} else {
currentCommand += trimmedLine;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
}
} else {
// Regular line (output, comments, etc.) - copy as-is
processedLines.push(line);
}
}

// Handle case where multi-line command was not completed
if (inMultiLineCommand && currentCommand) {
processedLines.push(currentCommand.trim());
}

return processedLines.join('\n');
}

function copyCode() {
// Get the raw code from the dataset (not the highlighted version)
const code = elements.codeSection.dataset.code;
const rawCode = elements.codeSection.dataset.code;
const copyBtn = document.getElementById('copy-code-btn');

if (!code) {
if (!rawCode) {
alert('No code available to copy');
return;
}

// Process the code with smart copy functionality
const processedCode = smartCopyProcessing(rawCode);

// Try to copy to clipboard
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(code).then(() => {
navigator.clipboard.writeText(processedCode).then(() => {
showCopyFeedback(copyBtn, true);
}).catch(err => {
console.error('Failed to copy to clipboard:', err);
fallbackCopyToClipboard(code, copyBtn);
fallbackCopyToClipboard(processedCode, copyBtn);
});
} else {
// Fallback for older browsers
fallbackCopyToClipboard(code, copyBtn);
fallbackCopyToClipboard(processedCode, copyBtn);
}
}

Expand Down
81 changes: 77 additions & 4 deletions static/js/codetabs.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,81 @@
// TODO: URI-able tabs

// Smart copy processing function to handle shell prompts
function smartCopyProcessing(text) {
const lines = text.split('\n');
const processedLines = [];
let inMultiLineCommand = false;
let currentCommand = '';

// Regex patterns for different shell prompts
const promptPatterns = [
/^\s*\$\s+(.+)$/, // $ command
/^\s*#\s+(.+)$/, // # command (root)
/^\s*[\w.-]+>\s+(.+)$/, // redis-cli>, rladmin>, etc.
/^\s*[\d.:]+>\s+(.+)$/, // 127.0.0.1:6379> command
];

for (let line of lines) {
let isPromptLine = false;
let commandPart = '';

// Check if this line matches any prompt pattern
for (let pattern of promptPatterns) {
const match = line.match(pattern);
if (match) {
isPromptLine = true;
commandPart = match[1];
break;
}
}

if (isPromptLine) {
// Handle multi-line commands with backslash continuation
if (commandPart.endsWith('\\')) {
inMultiLineCommand = true;
currentCommand = commandPart.slice(0, -1).trim() + ' ';
} else {
if (inMultiLineCommand) {
// End of multi-line command
currentCommand += commandPart;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
} else {
// Single line command
processedLines.push(commandPart);
}
}
} else if (inMultiLineCommand) {
// Continuation line of a multi-line command
const trimmedLine = line.trim();
if (trimmedLine.endsWith('\\')) {
currentCommand += trimmedLine.slice(0, -1).trim() + ' ';
} else {
currentCommand += trimmedLine;
processedLines.push(currentCommand.trim());
inMultiLineCommand = false;
currentCommand = '';
}
} else {
// Regular line (output, comments, etc.) - copy as-is
processedLines.push(line);
}
}

// Handle case where multi-line command was not completed
if (inMultiLineCommand && currentCommand) {
processedLines.push(currentCommand.trim());
}

return processedLines.join('\n');
}

function copyCodeToClipboard(panelId) {
// Get the last <code>, path depends on highlighter options
const code = [...document.querySelectorAll(`${panelId} code`)].pop().textContent;
navigator.clipboard.writeText(code);
const rawCode = [...document.querySelectorAll(`${panelId} code`)].pop().textContent;
const processedCode = smartCopyProcessing(rawCode);
navigator.clipboard.writeText(processedCode);

// Toggle tooltip
const tooltip = document.querySelector(`${panelId} .tooltiptext`);
Expand All @@ -22,8 +94,9 @@ function copyCodeToClipboardForCodetabs(button) {
if (!visiblePanel) return;

// Get the code from the visible panel
const code = [...visiblePanel.querySelectorAll('code')].pop().textContent;
navigator.clipboard.writeText(code);
const rawCode = [...visiblePanel.querySelectorAll('code')].pop().textContent;
const processedCode = smartCopyProcessing(rawCode);
navigator.clipboard.writeText(processedCode);

// Toggle tooltip
const tooltip = button.querySelector('.tooltiptext');
Expand Down