termites 1.0.22 → 1.0.23

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +93 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "termites",
3
- "version": "1.0.22",
3
+ "version": "1.0.23",
4
4
  "description": "Web terminal with server-client architecture for remote shell access",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server.js CHANGED
@@ -721,7 +721,12 @@ class TermitesServer {
721
721
  <button data-key="ArrowDown">↓</button>
722
722
  <div class="sep"></div>
723
723
  <button data-seq="/">/</button>
724
- <button id="select-all-btn">SelAll</button>
724
+ <button id="sel-start-btn">Sel▶</button>
725
+ <button id="sel-left-btn" class="sel-ctrl" style="display:none">◀</button>
726
+ <button id="sel-right-btn" class="sel-ctrl" style="display:none">▶</button>
727
+ <button id="sel-up-btn" class="sel-ctrl" style="display:none">▲</button>
728
+ <button id="sel-down-btn" class="sel-ctrl" style="display:none">▼</button>
729
+ <button id="sel-end-btn" class="sel-ctrl" style="display:none">End</button>
725
730
  <button id="copy-btn">Copy</button>
726
731
  <button id="paste-btn">Paste</button>
727
732
  </div>
@@ -1060,14 +1065,95 @@ class TermitesServer {
1060
1065
  pasteBtn.addEventListener('touchstart', handlePaste, { passive: false });
1061
1066
  pasteBtn.addEventListener('click', handlePaste);
1062
1067
 
1063
- // Select All button
1064
- const selectAllBtn = document.getElementById('select-all-btn');
1065
- const handleSelectAll = (e) => {
1068
+ // Selection mode with start/end control
1069
+ let selMode = false; // false=off, 'start'=adjusting start, 'end'=adjusting end
1070
+ let selStart = { col: 0, row: 0 };
1071
+ let selEnd = { col: 0, row: 0 };
1072
+ const selStartBtn = document.getElementById('sel-start-btn');
1073
+ const selEndBtn = document.getElementById('sel-end-btn');
1074
+ const selLeftBtn = document.getElementById('sel-left-btn');
1075
+ const selRightBtn = document.getElementById('sel-right-btn');
1076
+ const selUpBtn = document.getElementById('sel-up-btn');
1077
+ const selDownBtn = document.getElementById('sel-down-btn');
1078
+ const selCtrls = document.querySelectorAll('.sel-ctrl');
1079
+
1080
+ function updateSelection() {
1081
+ const startOffset = selStart.row * term.cols + selStart.col;
1082
+ const endOffset = selEnd.row * term.cols + selEnd.col;
1083
+ const length = endOffset - startOffset + 1;
1084
+ if (length > 0) {
1085
+ term.select(selStart.col, selStart.row, length);
1086
+ }
1087
+ }
1088
+
1089
+ function showSelCtrls(show) {
1090
+ selCtrls.forEach(el => el.style.display = show ? '' : 'none');
1091
+ selStartBtn.textContent = show ? 'Start' : 'Sel▶';
1092
+ selStartBtn.classList.toggle('active', selMode === 'start');
1093
+ selEndBtn.classList.toggle('active', selMode === 'end');
1094
+ }
1095
+
1096
+ const handleSelStart = (e) => {
1097
+ e.preventDefault();
1098
+ if (!selMode) {
1099
+ // Enter selection mode, start from last line
1100
+ selMode = 'start';
1101
+ const lastRow = term.buffer.active.cursorY;
1102
+ selStart = { col: 0, row: Math.max(0, lastRow - 2) };
1103
+ selEnd = { col: term.cols - 1, row: lastRow };
1104
+ showSelCtrls(true);
1105
+ updateSelection();
1106
+ } else if (selMode === 'end') {
1107
+ // Switch to adjusting start
1108
+ selMode = 'start';
1109
+ selStartBtn.classList.add('active');
1110
+ selEndBtn.classList.remove('active');
1111
+ } else {
1112
+ // Already adjusting start, switch to end
1113
+ selMode = 'end';
1114
+ selStartBtn.classList.remove('active');
1115
+ selEndBtn.classList.add('active');
1116
+ }
1117
+ };
1118
+ selStartBtn.addEventListener('touchstart', handleSelStart, { passive: false });
1119
+ selStartBtn.addEventListener('click', handleSelStart);
1120
+
1121
+ const handleSelEnd = (e) => {
1066
1122
  e.preventDefault();
1067
- term.selectAll();
1123
+ if (selMode === 'start') {
1124
+ selMode = 'end';
1125
+ selStartBtn.classList.remove('active');
1126
+ selEndBtn.classList.add('active');
1127
+ } else {
1128
+ // Exit selection mode
1129
+ selMode = false;
1130
+ showSelCtrls(false);
1131
+ }
1132
+ };
1133
+ selEndBtn.addEventListener('touchstart', handleSelEnd, { passive: false });
1134
+ selEndBtn.addEventListener('click', handleSelEnd);
1135
+
1136
+ // Arrow controls for selection
1137
+ const moveSelection = (dCol, dRow) => {
1138
+ if (selMode === 'start') {
1139
+ selStart.col = Math.max(0, Math.min(term.cols - 1, selStart.col + dCol));
1140
+ selStart.row = Math.max(0, selStart.row + dRow);
1141
+ } else if (selMode === 'end') {
1142
+ selEnd.col = Math.max(0, Math.min(term.cols - 1, selEnd.col + dCol));
1143
+ selEnd.row = Math.max(0, selEnd.row + dRow);
1144
+ }
1145
+ updateSelection();
1146
+ };
1147
+
1148
+ const addSelHandler = (btn, dCol, dRow) => {
1149
+ const handler = (e) => { e.preventDefault(); moveSelection(dCol, dRow); };
1150
+ btn.addEventListener('touchstart', handler, { passive: false });
1151
+ btn.addEventListener('click', handler);
1068
1152
  };
1069
- selectAllBtn.addEventListener('touchstart', handleSelectAll, { passive: false });
1070
- selectAllBtn.addEventListener('click', handleSelectAll);
1153
+ addSelHandler(selLeftBtn, -1, 0);
1154
+ addSelHandler(selRightBtn, 1, 0);
1155
+ addSelHandler(selUpBtn, 0, -1);
1156
+ addSelHandler(selDownBtn, 0, 1);
1071
1157
  }
1072
1158
 
1073
1159
  function updateClientList() {