@make-u-free/migi 0.4.3 → 0.4.5

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/bin/migi.js +32 -32
  2. package/package.json +1 -1
package/bin/migi.js CHANGED
@@ -86,47 +86,47 @@ async function readChatInput() {
86
86
  const lines = ['']
87
87
  let curLine = 0
88
88
  let drawnLines = 0
89
- let lastLineCount = 0
90
- let cursorLine = 0 // カーソルが実際にいる物理行(drawn area 先頭からの offset)
89
+ let cursorLine = 0 // カーソルの物理行(drawn area 先頭からの offset)
91
90
 
92
91
  emitKeypressEvents(process.stdin)
93
92
  if (process.stdin.isTTY) process.stdin.setRawMode(true)
94
93
 
95
94
  function draw() {
96
95
  const w = process.stdout.columns || 80
97
-
98
- // 行数が変わっていない(通常の文字入力)→ 現在行だけ上書き。セパレーター・ガイドは触らない
99
- if (lines.length === lastLineCount && drawnLines > 0) {
100
- const prefix = curLine === 0 ? PFIRST : PCONT
101
- process.stdout.write('\r\x1b[K' + chalk.cyan(prefix) + lines[curLine])
102
- cursorLine = curLine
103
- return
104
- }
105
-
106
- // 行数変化 or 初回 → 全体を再描画
107
- lastLineCount = lines.length
108
- const allLines = [
96
+ const newLines = [
109
97
  ...lines.map((l, i) => chalk.cyan(i === 0 ? PFIRST : PCONT) + l),
110
- chalk.dim('─'.repeat(w)),
111
- chalk.dim(` ✦ ${model} · Shift+Enterで改行 / Enterで送信`)
98
+ chalk.dim('─'.repeat(w - 1)), // w-1: 行末での自動折り返し防止
99
+ chalk.dim(` ✦ ${model} · Alt+Enterで改行 / Enterで送信`)
112
100
  ]
101
+ const oldDrawnLines = drawnLines
102
+ drawnLines = newLines.length
113
103
 
114
104
  let buf = ''
115
- if (drawnLines > 0) {
116
- // cursorLine = カーソルの現在位置。先頭行まで戻ってから全行クリア
117
- if (cursorLine > 0) buf += `\x1b[${cursorLine}A`
118
- buf += `\x1b[1G`
119
- for (let i = 0; i < drawnLines; i++) buf += '\x1b[2K\n'
120
- buf += `\x1b[${drawnLines}A\x1b[1G`
105
+
106
+ // ① drawn area 先頭まで戻る(cursorLine = カーソルが今いる物理行)
107
+ if (cursorLine > 0) buf += `\x1b[${cursorLine}A`
108
+ buf += '\r'
109
+
110
+ // 各行を上書き。「先クリア→描画」ではなく「描画→行末クリア」でちらつき防止
111
+ for (let i = 0; i < newLines.length; i++) {
112
+ buf += newLines[i] + '\x1b[K'
113
+ if (i < newLines.length - 1) buf += '\r\n'
114
+ }
115
+
116
+ // ③ 行数が減った場合、余分な古い行をクリア
117
+ for (let i = newLines.length; i < oldDrawnLines; i++) {
118
+ buf += '\r\n\x1b[2K'
121
119
  }
122
120
 
123
- drawnLines = allLines.length
124
- buf += allLines.join('\n') + '\n'
121
+ // curLine の行まで戻る
122
+ // step②+③後のカーソル位置は max(新行数, 旧行数)-1 行目
123
+ const linesFromBottom = Math.max(drawnLines, oldDrawnLines) - 1 - curLine
124
+ if (linesFromBottom > 0) buf += `\x1b[${linesFromBottom}A`
125
+ buf += '\r'
125
126
 
126
- const linesBelow = drawnLines - curLine
127
- if (linesBelow > 0) buf += `\x1b[${linesBelow}A`
128
- const col = (curLine === 0 ? PFIRST : PCONT).length + lines[curLine].length + 1
129
- buf += `\x1b[${col}G`
127
+ // カーソルを入力内容の末尾へ
128
+ const prefix = curLine === 0 ? PFIRST : PCONT
129
+ buf += `\x1b[${prefix.length + lines[curLine].length + 1}G`
130
130
 
131
131
  cursorLine = curLine
132
132
  process.stdout.write(buf)
@@ -141,7 +141,7 @@ async function readChatInput() {
141
141
  }
142
142
 
143
143
  if (key.ctrl && key.name === 'c') {
144
- process.stdout.write(`\x1b[${drawnLines - curLine}B\n`)
144
+ process.stdout.write(`\x1b[${drawnLines - 1 - curLine}B\n`)
145
145
  process.stdin.removeListener('keypress', onKey)
146
146
  if (process.stdin.isTTY) process.stdin.setRawMode(false)
147
147
  console.log(chalk.cyan('\n お疲れ様でした!またね。\n'))
@@ -149,8 +149,8 @@ async function readChatInput() {
149
149
  }
150
150
 
151
151
  if (key.name === 'return') {
152
- if (key.shift) {
153
- // Shift+Enter 改行
152
+ // Alt+Enter(macOS: Option+Enter)または Shift+Enter → 改行
153
+ if (key.meta || key.shift) {
154
154
  lines.splice(curLine + 1, 0, '')
155
155
  curLine++
156
156
  draw()
@@ -158,7 +158,7 @@ async function readChatInput() {
158
158
  // Enter → 送信
159
159
  const content = lines.join('\n').trim()
160
160
  if (!content) return
161
- process.stdout.write(`\x1b[${drawnLines - curLine}B\n`)
161
+ process.stdout.write(`\x1b[${drawnLines - 1 - curLine}B\n`)
162
162
  process.stdin.removeListener('keypress', onKey)
163
163
  if (process.stdin.isTTY) process.stdin.setRawMode(false)
164
164
  resolve(content)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@make-u-free/migi",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Your AI right-hand agent. Works anywhere, with any LLM API.",
5
5
  "type": "module",
6
6
  "bin": {