termites 1.0.22 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.js +119 -8
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -645,6 +645,13 @@ class TermitesServer {
|
|
|
645
645
|
.mobile-toolbar button:active { opacity: 0.6; transform: scale(0.95); }
|
|
646
646
|
.mobile-toolbar button.active { background: var(--btn-active, rgba(255,255,255,0.15)); }
|
|
647
647
|
.mobile-toolbar .sep { width: 1px; background: currentColor; opacity: 0.2; margin: 0 4px; }
|
|
648
|
+
.sel-marker {
|
|
649
|
+
position: absolute; z-index: 50; padding: 4px 8px; border-radius: 4px;
|
|
650
|
+
font-size: 11px; font-weight: bold; cursor: grab; touch-action: none;
|
|
651
|
+
user-select: none; -webkit-user-select: none;
|
|
652
|
+
}
|
|
653
|
+
#sel-start-marker { background: #22c55e; color: #fff; }
|
|
654
|
+
#sel-end-marker { background: #ef4444; color: #fff; }
|
|
648
655
|
</style>
|
|
649
656
|
</head>
|
|
650
657
|
<body>
|
|
@@ -721,10 +728,12 @@ class TermitesServer {
|
|
|
721
728
|
<button data-key="ArrowDown">↓</button>
|
|
722
729
|
<div class="sep"></div>
|
|
723
730
|
<button data-seq="/">/</button>
|
|
724
|
-
<button id="
|
|
731
|
+
<button id="sel-btn" class="mod-btn">Sel</button>
|
|
725
732
|
<button id="copy-btn">Copy</button>
|
|
726
733
|
<button id="paste-btn">Paste</button>
|
|
727
734
|
</div>
|
|
735
|
+
<div id="sel-start-marker" class="sel-marker" style="display:none">▼Start</div>
|
|
736
|
+
<div id="sel-end-marker" class="sel-marker" style="display:none">▲End</div>
|
|
728
737
|
|
|
729
738
|
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
|
|
730
739
|
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
|
|
@@ -1060,14 +1069,116 @@ class TermitesServer {
|
|
|
1060
1069
|
pasteBtn.addEventListener('touchstart', handlePaste, { passive: false });
|
|
1061
1070
|
pasteBtn.addEventListener('click', handlePaste);
|
|
1062
1071
|
|
|
1063
|
-
//
|
|
1064
|
-
|
|
1065
|
-
|
|
1072
|
+
// Selection mode with draggable markers
|
|
1073
|
+
let selMode = false;
|
|
1074
|
+
let selStart = { col: 0, row: 0 };
|
|
1075
|
+
let selEnd = { col: 0, row: 0 };
|
|
1076
|
+
const selBtn = document.getElementById('sel-btn');
|
|
1077
|
+
const startMarker = document.getElementById('sel-start-marker');
|
|
1078
|
+
const endMarker = document.getElementById('sel-end-marker');
|
|
1079
|
+
const termContainer = document.getElementById('terminal-container');
|
|
1080
|
+
|
|
1081
|
+
function getCellSize() {
|
|
1082
|
+
try {
|
|
1083
|
+
return {
|
|
1084
|
+
width: term._core._renderService.dimensions.css.cell.width,
|
|
1085
|
+
height: term._core._renderService.dimensions.css.cell.height
|
|
1086
|
+
};
|
|
1087
|
+
} catch (e) {
|
|
1088
|
+
return { width: 9, height: 17 }; // fallback
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
function updateMarkerPositions() {
|
|
1093
|
+
const cell = getCellSize();
|
|
1094
|
+
const rect = termContainer.getBoundingClientRect();
|
|
1095
|
+
startMarker.style.left = (selStart.col * cell.width + 4) + 'px';
|
|
1096
|
+
startMarker.style.top = (selStart.row * cell.height) + 'px';
|
|
1097
|
+
endMarker.style.left = (selEnd.col * cell.width + 4) + 'px';
|
|
1098
|
+
endMarker.style.top = ((selEnd.row + 1) * cell.height) + 'px';
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
function updateSelection() {
|
|
1102
|
+
const startOffset = selStart.row * term.cols + selStart.col;
|
|
1103
|
+
const endOffset = selEnd.row * term.cols + selEnd.col;
|
|
1104
|
+
const length = endOffset - startOffset + 1;
|
|
1105
|
+
if (length > 0) {
|
|
1106
|
+
term.select(selStart.col, selStart.row, length);
|
|
1107
|
+
}
|
|
1108
|
+
updateMarkerPositions();
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function toggleSelMode(e) {
|
|
1066
1112
|
e.preventDefault();
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1113
|
+
selMode = !selMode;
|
|
1114
|
+
selBtn.classList.toggle('active', selMode);
|
|
1115
|
+
if (selMode) {
|
|
1116
|
+
// Enter selection mode
|
|
1117
|
+
const lastRow = term.buffer.active.cursorY;
|
|
1118
|
+
selStart = { col: 0, row: Math.max(0, lastRow - 2) };
|
|
1119
|
+
selEnd = { col: term.cols - 1, row: lastRow };
|
|
1120
|
+
startMarker.style.display = 'block';
|
|
1121
|
+
endMarker.style.display = 'block';
|
|
1122
|
+
updateSelection();
|
|
1123
|
+
} else {
|
|
1124
|
+
// Exit selection mode
|
|
1125
|
+
startMarker.style.display = 'none';
|
|
1126
|
+
endMarker.style.display = 'none';
|
|
1127
|
+
term.clearSelection();
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
selBtn.addEventListener('touchstart', toggleSelMode, { passive: false });
|
|
1131
|
+
selBtn.addEventListener('click', toggleSelMode);
|
|
1132
|
+
|
|
1133
|
+
// Make markers draggable
|
|
1134
|
+
function setupDraggable(marker, isStart) {
|
|
1135
|
+
let dragging = false;
|
|
1136
|
+
let startX, startY;
|
|
1137
|
+
|
|
1138
|
+
const onStart = (e) => {
|
|
1139
|
+
e.preventDefault();
|
|
1140
|
+
dragging = true;
|
|
1141
|
+
const touch = e.touches ? e.touches[0] : e;
|
|
1142
|
+
startX = touch.clientX;
|
|
1143
|
+
startY = touch.clientY;
|
|
1144
|
+
marker.style.cursor = 'grabbing';
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
const onMove = (e) => {
|
|
1148
|
+
if (!dragging) return;
|
|
1149
|
+
e.preventDefault();
|
|
1150
|
+
const touch = e.touches ? e.touches[0] : e;
|
|
1151
|
+
const cell = getCellSize();
|
|
1152
|
+
const rect = termContainer.getBoundingClientRect();
|
|
1153
|
+
const x = touch.clientX - rect.left - 4;
|
|
1154
|
+
const y = touch.clientY - rect.top;
|
|
1155
|
+
|
|
1156
|
+
const col = Math.max(0, Math.min(term.cols - 1, Math.floor(x / cell.width)));
|
|
1157
|
+
const row = Math.max(0, Math.floor(y / cell.height));
|
|
1158
|
+
|
|
1159
|
+
if (isStart) {
|
|
1160
|
+
selStart = { col, row };
|
|
1161
|
+
} else {
|
|
1162
|
+
selEnd = { col, row: Math.max(0, row - 1) };
|
|
1163
|
+
}
|
|
1164
|
+
updateSelection();
|
|
1165
|
+
};
|
|
1166
|
+
|
|
1167
|
+
const onEnd = () => {
|
|
1168
|
+
dragging = false;
|
|
1169
|
+
marker.style.cursor = 'grab';
|
|
1170
|
+
};
|
|
1171
|
+
|
|
1172
|
+
marker.addEventListener('touchstart', onStart, { passive: false });
|
|
1173
|
+
marker.addEventListener('touchmove', onMove, { passive: false });
|
|
1174
|
+
marker.addEventListener('touchend', onEnd);
|
|
1175
|
+
marker.addEventListener('mousedown', onStart);
|
|
1176
|
+
document.addEventListener('mousemove', onMove);
|
|
1177
|
+
document.addEventListener('mouseup', onEnd);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
setupDraggable(startMarker, true);
|
|
1181
|
+
setupDraggable(endMarker, false);
|
|
1071
1182
|
}
|
|
1072
1183
|
|
|
1073
1184
|
function updateClientList() {
|