From 92fd55bb2aa701b93d0c4cbb88bbeddad3d0c1b1 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sun, 11 Jan 2026 23:36:17 +0800 Subject: [PATCH 01/33] release: Update release message for 1.11.0 --- CodeApp/Localization/de.lproj/Localizable.strings | 6 ++++-- CodeApp/Localization/en.lproj/Localizable.strings | 5 ++++- CodeApp/Localization/ja.lproj/Localizable.strings | 6 ++++-- CodeApp/Localization/ko.lproj/Localizable.strings | 6 ++++-- CodeApp/Localization/ru.lproj/Localizable.strings | 6 ++++-- CodeApp/Localization/zh-Hans.lproj/Localizable.strings | 6 ++++-- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 012d7d008..1bb406328 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (Oktober 2025)** +##### **v1.11.0 (Januar 2026)** #### Start [Neue Datei](https://thebaselab.com/code/newfile) [Datei öffnen](https://thebaselab.com/code/openfile) @@ -22,7 +22,9 @@ "; "Changelog.message" = -" +"### 1.11.0 (Januar 2026) +- Liquid Glass-Benutzeroberfläche übernommen + ### 1.10.4 (September 2025) - Fehlerbehebungen im Zusammenhang mit dem Diff-Editor diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index df5f20f33..42a510f90 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (October 2025)** +##### **v1.11.0 (January 2026)** #### Start [New file](https://thebaselab.com/code/newfile) [Open file](https://thebaselab.com/code/openfile) @@ -23,6 +23,9 @@ "Changelog.message" = " +### 1.11.0 (January 2026) +- Adopt Liquid Glass UI + ### 1.10.4 (September 2025) - Bug fixes regarding diff editor diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index 9e128b596..f866f329b 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2025年10月)** +##### **v1.11.0 (2026 年 1 月)** #### 開始 [新しいファイル](https://thebaselab.com/code/newfile) [ファイルを開く](https://thebaselab.com/code/openfile) @@ -22,7 +22,9 @@ "; "Changelog.message" = -" +"### 1.11.0 (2026 年 1 月) +- Liquid Glass UI の採用 + ### 1.10.4 (2025 年 9 月) - diff エディターに関するバグ修正 diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index 36318b1b1..adbecfc8b 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2025년 10월)** +##### **v1.11.0 (2026년 1월)** #### 시작 [새 파일...](https://thebaselab.com/code/newfile) [파일 열기...](https://thebaselab.com/code/openfile) @@ -22,7 +22,9 @@ "; "Changelog.message" = -" +"### 1.11.0 (2026년 1월) +- Liquid Glass UI 채택 + ### 1.10.4 (2025년 9월) - diff 에디터 관련 버그 수정 diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index c1c95882a..691b96534 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (Октябрь 2025)** +##### **v1.11.0 (Январь 2026)** #### Начало [Новый файл](https://thebaselab.com/code/newfile) [Открыть файл](https://thebaselab.com/code/openfile) @@ -22,7 +22,9 @@ "; "Changelog.message" = -" +"### 1.11.0 (Январь 2026) +- Принята Liquid Glass UI + ### 1.10.4 (Сентябрь 2025) - Исправлены ошибки, связанные с редактором различий diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index 2b7b45c35..42062cb51 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2025 年 10 月)** +##### **v1.11.0 (2026 年 1 月)** #### 开始 [新文件](https://thebaselab.com/code/newfile) [打开文件](https://thebaselab.com/code/openfile) @@ -22,7 +22,9 @@ "; "Changelog.message" = -" +"### 1.11.0 (2026 年 1 月) +- 采用 Liquid Glass 用户界面 + ### 1.10.4 (2025 年 9 月) - 修复了 diff 编辑器相关的错误 From 10bd8c526786bba20d908a77a34b733407ef23e7 Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Sun, 11 Jan 2026 14:42:36 -0600 Subject: [PATCH 02/33] Add Esc, Del and Ctrl and Alt modifier support to terminal toolbar Introduces Escape, Delete, and Control and Alt modifier buttons to the terminal keyboard toolbar, allowing users to send modified key sequences. Updates the Swift and JavaScript code to track modifier state, apply modifiers to terminal input, and synchronize state between the UI and the terminal. Modifier states are reset after use, and notifications are used to keep the UI in sync. --- CodeApp/Managers/TerminalInstance.swift | 27 ++++ CodeApp/Views/TerminalKeyboardToolbar.swift | 116 +++++++++++++++- Dependencies/terminal.bundle/index.html | 140 ++++++++++++++++++++ 3 files changed, 276 insertions(+), 7 deletions(-) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 015318310..25fde8095 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -233,6 +233,20 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { if let input = result["Input"] as? String { ts.write(data: "\(input)".data(using: .utf8)!) } + case "ControlReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalControlReset, + object: self, + userInfo: ["generation": generation] + ) + case "AltReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalAltReset, + object: self, + userInfo: ["generation": generation] + ) default: return } @@ -499,4 +513,17 @@ extension TerminalInstance { func moveCursor(codeSequence: String) { executeScript("term.input(String.fromCharCode(0x1b)+'\(codeSequence)')") } + + func setControlActive(_ active: Bool, generation: Int) { + executeScript("setControlActive(\(active), \(generation))") + } + + func setAltActive(_ active: Bool, generation: Int) { + executeScript("setAltActive(\(active), \(generation))") + } +} + +extension Notification.Name { + static let terminalControlReset = Notification.Name("terminalControlReset") + static let terminalAltReset = Notification.Name("terminalAltReset") } diff --git a/CodeApp/Views/TerminalKeyboardToolbar.swift b/CodeApp/Views/TerminalKeyboardToolbar.swift index 8cd6327ba..b528d685c 100644 --- a/CodeApp/Views/TerminalKeyboardToolbar.swift +++ b/CodeApp/Views/TerminalKeyboardToolbar.swift @@ -12,6 +12,27 @@ struct TerminalKeyboardToolBar: View { @EnvironmentObject var App: MainApp @Environment(\.horizontalSizeClass) var horizontalSizeClass @State var pasteBoardHasContent = false + @State var controlActive = false + @State var controlGeneration = 0 + @State var altActive = false + @State var altGeneration = 0 + + private func resetModifierStates() { + controlActive = false + App.terminalInstance.setControlActive(false, generation: controlGeneration) + altActive = false + App.terminalInstance.setAltActive(false, generation: altGeneration) + } + + private func typeAndResetModifiers(text: String) { + App.terminalInstance.type(text: text) + resetModifierStates() + } + + private func moveCursorAndResetModifiers(codeSequence: String) { + App.terminalInstance.moveCursor(codeSequence: codeSequence) + resetModifierStates() + } var body: some View { HStack(spacing: horizontalSizeClass == .compact ? 8 : 14) { @@ -20,7 +41,7 @@ struct TerminalKeyboardToolBar: View { Button( action: { if let string = UIPasteboard.general.string { - App.terminalInstance.type(text: string) + typeAndResetModifiers(text: string) } }, label: { @@ -29,11 +50,65 @@ struct TerminalKeyboardToolBar: View { } Button( action: { - App.terminalInstance.type(text: "\t") + typeAndResetModifiers(text: "\u{1b}") + }, + label: { + Text("Esc") + } + ) + .accessibilityLabel("Escape") + Button( + action: { + typeAndResetModifiers(text: "\t") }, label: { Text("↹") }) + Button( + action: { + controlActive.toggle() + controlGeneration += 1 + App.terminalInstance.setControlActive( + controlActive, generation: controlGeneration) + }, + label: { + Text("Ctrl") + .padding(.horizontal, 4) + .background( + controlActive ? Color.accentColor.opacity(0.3) : Color.clear + ) + .cornerRadius(4) + } + ) + .accessibilityLabel("Control") + .accessibilityValue(controlActive ? "Active" : "Inactive") + Button( + action: { + altActive.toggle() + altGeneration += 1 + App.terminalInstance.setAltActive( + altActive, generation: altGeneration) + }, + label: { + Text("Alt") + .padding(.horizontal, 4) + .background( + altActive ? Color.accentColor.opacity(0.3) : Color.clear + ) + .cornerRadius(4) + } + ) + .accessibilityLabel("Alt") + .accessibilityValue(altActive ? "Active" : "Inactive") + Button( + action: { + typeAndResetModifiers(text: "\u{1b}[3~") + }, + label: { + Text("Del") + } + ) + .accessibilityLabel("Delete") } Spacer() @@ -41,34 +116,35 @@ struct TerminalKeyboardToolBar: View { Group { Button( action: { - App.terminalInstance.moveCursor(codeSequence: "[A") + moveCursorAndResetModifiers(codeSequence: "[A") }, label: { Image(systemName: "arrow.up") }) Button( action: { - App.terminalInstance.moveCursor(codeSequence: "[B") + moveCursorAndResetModifiers(codeSequence: "[B") }, label: { Image(systemName: "arrow.down") }) Button( action: { - App.terminalInstance.moveCursor(codeSequence: "[D") + moveCursorAndResetModifiers(codeSequence: "[D") }, label: { Image(systemName: "arrow.left") }) Button( action: { - App.terminalInstance.moveCursor(codeSequence: "[C") + moveCursorAndResetModifiers(codeSequence: "[C") }, label: { Image(systemName: "arrow.right") }) Button( action: { + resetModifierStates() App.terminalInstance.blur() }, label: { @@ -84,12 +160,38 @@ struct TerminalKeyboardToolBar: View { .ignoresSafeArea() .onReceive( NotificationCenter.default.publisher(for: UIPasteboard.changedNotification), - perform: { val in + perform: { _ in if UIPasteboard.general.hasStrings { pasteBoardHasContent = true } else { pasteBoardHasContent = false } + } + ) + .onReceive( + NotificationCenter.default.publisher( + for: .terminalControlReset, + object: App.terminalInstance + ), + perform: { notification in + if let generation = notification.userInfo?["generation"] as? Int, + generation == controlGeneration + { + controlActive = false + } + } + ) + .onReceive( + NotificationCenter.default.publisher( + for: .terminalAltReset, + object: App.terminalInstance + ), + perform: { notification in + if let generation = notification.userInfo?["generation"] as? Int, + generation == altGeneration + { + altActive = false + } }) } } diff --git a/Dependencies/terminal.bundle/index.html b/Dependencies/terminal.bundle/index.html index 494ca9024..2e1d915ba 100644 --- a/Dependencies/terminal.bundle/index.html +++ b/Dependencies/terminal.bundle/index.html @@ -154,6 +154,145 @@ localEcho.addAutocompleteHandler(autocompleteCommonCommands); localEcho.addAutocompleteHandler(autocompleteCommonFiles); + var controlActive = false; + var controlGeneration = 0; + var altActive = false; + var altGeneration = 0; + + function setControlActive(active, generation) { + controlActive = active; + controlGeneration = generation; + } + + function setAltActive(active, generation) { + altActive = active; + altGeneration = generation; + } + + function shouldApplyModifierToCsi(final, params) { + if (final >= "A" && final <= "D") { + return true; + } + if (final === "F" || final === "H") { + return true; + } + if (final === "~") { + var primaryParam = params.split(";")[0]; + var keycode = parseInt(primaryParam, 10); + if (isNaN(keycode)) { + return false; + } + return keycode !== 200 && keycode !== 201; + } + return false; + } + + function applyModifierToEscapeSequence(data, wasControlActive, wasAltActive) { + var modifier = 1 + (wasAltActive ? 2 : 0) + (wasControlActive ? 4 : 0); + + // CSI sequences (ESC [ ...). + var csiMatch = data.match(/^\x1b\[([0-9;]*)([@-~])$/); + if (csiMatch) { + var params = csiMatch[1]; + var final = csiMatch[2]; + + if (!shouldApplyModifierToCsi(final, params)) { + return data; + } + + var parts = params.length ? params.split(";") : []; + if (parts.length === 0) { + parts = ["1", String(modifier)]; + } else if (parts.length === 1) { + parts.push(String(modifier)); + } else { + var lastIndex = parts.length - 1; + var existing = parseInt(parts[lastIndex], 10); + if (!isNaN(existing)) { + var modBits = Math.max(existing, 1) - 1; + if (wasAltActive) { + modBits |= 2; + } + if (wasControlActive) { + modBits |= 4; + } + parts[lastIndex] = String(modBits + 1); + } else { + parts.push(String(modifier)); + } + } + + return "\x1b[" + parts.join(";") + final; + } + + // SS3 sequences (ESC O ...). + var ss3Match = data.match(/^\x1bO([A-Za-z])$/); + if (ss3Match) { + var final = ss3Match[1]; + if ( + (final >= "A" && final <= "D") || + final === "F" || + final === "H" || + (final >= "P" && final <= "S") + ) { + return "\x1b[1;" + String(modifier) + final; + } + } + + return data; + } + + function applyModifierStates(data) { + // Capture which modifiers are active before resetting + var wasControlActive = controlActive; + var wasAltActive = altActive; + + if (!wasControlActive && !wasAltActive) { + return data; + } + + // Reset all active modifiers and notify Swift + if (wasControlActive) { + controlActive = false; + window.webkit.messageHandlers.toggleMessageHandler2.postMessage({ + Event: "ControlReset", + Generation: controlGeneration, + }); + } + if (wasAltActive) { + altActive = false; + window.webkit.messageHandlers.toggleMessageHandler2.postMessage({ + Event: "AltReset", + Generation: altGeneration, + }); + } + + var result = data; + + if (data.length === 1) { + // Apply Control: convert to control character (A-Z, @, [, \, ], ^, _) + if (wasControlActive) { + const code = result.toUpperCase().charCodeAt(0); + if (code >= 0x40 && code <= 0x5f) { + result = String.fromCharCode(code & 0x1f); + } + } + + // Apply Alt: prepend ESC (meta key behavior) + if (wasAltActive) { + result = "\x1b" + result; + } + } else if (data.charCodeAt(0) === 0x1b) { + result = applyModifierToEscapeSequence( + data, + wasControlActive, + wasAltActive + ); + } + + return result; + } + function startInteractive() { localEcho.detach(); } @@ -163,6 +302,7 @@ } term.onData((data) => { + data = applyModifierStates(data); window.webkit.messageHandlers.toggleMessageHandler2.postMessage({ Event: "Data", Input: data, From 70e4aa794cec7c9e88f26a417c3d79714436b9ea Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Sun, 11 Jan 2026 14:59:59 -0600 Subject: [PATCH 03/33] Prevent modification of bracketed paste sequences Added a check to exclude ESC[200~ and ESC[201~ keycodes from being modified, preserving the integrity of the bracketed paste protocol in the terminal. --- Dependencies/terminal.bundle/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dependencies/terminal.bundle/index.html b/Dependencies/terminal.bundle/index.html index 2e1d915ba..cadc19f25 100644 --- a/Dependencies/terminal.bundle/index.html +++ b/Dependencies/terminal.bundle/index.html @@ -182,6 +182,8 @@ if (isNaN(keycode)) { return false; } + // Exclude bracketed paste mode sequences (ESC[200~ and ESC[201~). + // Modifying these would corrupt the paste protocol. return keycode !== 200 && keycode !== 201; } return false; From ea7a2b93b322a1f698aee85d374671bbb8cc914b Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Fri, 16 Jan 2026 15:55:35 -0600 Subject: [PATCH 04/33] Add support for ControlReset and AltReset events in terminal TerminalInstance now handles 'ControlReset' and 'AltReset' events, posting notifications with generation info. Also refactored cursor movement to use inputWithModifiers, with corresponding helper added in terminal.bundle/index.html. --- CodeApp/Managers/TerminalInstance.swift | 39 +++++++++++++++++++++++-- Dependencies/terminal.bundle/index.html | 4 +++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 25fde8095..4a3be6664 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -253,8 +253,27 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { return } - if self.executor?.state == .interactive && event == "Data" { - self.executor?.sendInput(input: result["Input"] as! String) + if self.executor?.state == .interactive { + switch event { + case "Data": + self.executor?.sendInput(input: result["Input"] as! String) + case "ControlReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalControlReset, + object: self, + userInfo: ["generation": generation] + ) + case "AltReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalAltReset, + object: self, + userInfo: ["generation": generation] + ) + default: + break + } return } @@ -382,6 +401,20 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { executor?.kill() } } + case "ControlReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalControlReset, + object: self, + userInfo: ["generation": generation] + ) + case "AltReset": + let generation = result["Generation"] as? Int ?? 0 + NotificationCenter.default.post( + name: .terminalAltReset, + object: self, + userInfo: ["generation": generation] + ) default: print("\(result) Event not handled") } @@ -511,7 +544,7 @@ extension TerminalInstance { } func moveCursor(codeSequence: String) { - executeScript("term.input(String.fromCharCode(0x1b)+'\(codeSequence)')") + executeScript("inputWithModifiers(String.fromCharCode(0x1b)+'\(codeSequence)')") } func setControlActive(_ active: Bool, generation: Int) { diff --git a/Dependencies/terminal.bundle/index.html b/Dependencies/terminal.bundle/index.html index cadc19f25..52e842eec 100644 --- a/Dependencies/terminal.bundle/index.html +++ b/Dependencies/terminal.bundle/index.html @@ -295,6 +295,10 @@ return result; } + function inputWithModifiers(data) { + term.input(applyModifierStates(data)); + } + function startInteractive() { localEcho.detach(); } From 5958c03de89ceea2806de6497768cab53978dd8d Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Fri, 16 Jan 2026 16:51:10 -0600 Subject: [PATCH 05/33] Use inputWithModifiers for terminal input Replaces the call to term.input with inputWithModifiers in the type(text:) method to handle input with modifier keys. This may improve support for complex input scenarios in the terminal. Add lock functionality for Ctrl and Alt modifiers in terminal Introduces the ability to lock the Control and Alt modifier keys in the terminal keyboard toolbar via double-tap, with visual feedback and state management. Updates Swift and JavaScript code to support locked states, ensuring modifiers remain active until explicitly unlocked, and modifies reset logic to respect locked states. --- CodeApp/Managers/TerminalInstance.swift | 10 ++- CodeApp/Views/TerminalKeyboardToolbar.swift | 99 ++++++++++++++++++--- Dependencies/terminal.bundle/index.html | 18 +++- 3 files changed, 110 insertions(+), 17 deletions(-) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 4a3be6664..6c5819bd1 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -540,7 +540,7 @@ extension TerminalInstance: WKUIDelegate { extension TerminalInstance { func type(text: String) { guard let base64 = text.base64Encoded() else { return } - executeScript("term.input(base64ToString(`\(base64)`))") + executeScript("inputWithModifiers(base64ToString(`\(base64)`))") } func moveCursor(codeSequence: String) { @@ -551,9 +551,17 @@ extension TerminalInstance { executeScript("setControlActive(\(active), \(generation))") } + func setControlLocked(_ locked: Bool) { + executeScript("setControlLocked(\(locked))") + } + func setAltActive(_ active: Bool, generation: Int) { executeScript("setAltActive(\(active), \(generation))") } + + func setAltLocked(_ locked: Bool) { + executeScript("setAltLocked(\(locked))") + } } extension Notification.Name { diff --git a/CodeApp/Views/TerminalKeyboardToolbar.swift b/CodeApp/Views/TerminalKeyboardToolbar.swift index b528d685c..f6ba152d7 100644 --- a/CodeApp/Views/TerminalKeyboardToolbar.swift +++ b/CodeApp/Views/TerminalKeyboardToolbar.swift @@ -13,25 +13,97 @@ struct TerminalKeyboardToolBar: View { @Environment(\.horizontalSizeClass) var horizontalSizeClass @State var pasteBoardHasContent = false @State var controlActive = false + @State var controlLocked = false + @State var controlLastTapTime: Date? @State var controlGeneration = 0 @State var altActive = false + @State var altLocked = false + @State var altLastTapTime: Date? @State var altGeneration = 0 + private let doubleTapInterval: TimeInterval = 0.3 + private func resetModifierStates() { controlActive = false + controlLocked = false App.terminalInstance.setControlActive(false, generation: controlGeneration) + App.terminalInstance.setControlLocked(false) altActive = false + altLocked = false App.terminalInstance.setAltActive(false, generation: altGeneration) + App.terminalInstance.setAltLocked(false) + } + + private func resetUnlockedModifiers() { + // Reset modifiers only if they are not locked + if !controlLocked { + controlActive = false + App.terminalInstance.setControlActive(false, generation: controlGeneration) + } + if !altLocked { + altActive = false + App.terminalInstance.setAltActive(false, generation: altGeneration) + } + } + + private func handleControlTap() { + let now = Date() + let isDoubleTap = + controlLastTapTime.map { now.timeIntervalSince($0) < doubleTapInterval } ?? false + controlLastTapTime = now + + if controlLocked { + // Single tap while locked: unlock and deactivate + controlLocked = false + controlActive = false + controlGeneration += 1 + App.terminalInstance.setControlLocked(false) + App.terminalInstance.setControlActive(false, generation: controlGeneration) + } else if isDoubleTap && controlActive { + // Double tap while active: lock + controlLocked = true + App.terminalInstance.setControlLocked(true) + } else { + // Single tap: toggle active state + controlActive.toggle() + controlGeneration += 1 + App.terminalInstance.setControlActive(controlActive, generation: controlGeneration) + } + } + + private func handleAltTap() { + let now = Date() + let isDoubleTap = + altLastTapTime.map { now.timeIntervalSince($0) < doubleTapInterval } ?? false + altLastTapTime = now + + if altLocked { + // Single tap while locked: unlock and deactivate + altLocked = false + altActive = false + altGeneration += 1 + App.terminalInstance.setAltLocked(false) + App.terminalInstance.setAltActive(false, generation: altGeneration) + } else if isDoubleTap && altActive { + // Double tap while active: lock + altLocked = true + App.terminalInstance.setAltLocked(true) + } else { + // Single tap: toggle active state + altActive.toggle() + altGeneration += 1 + App.terminalInstance.setAltActive(altActive, generation: altGeneration) + } } private func typeAndResetModifiers(text: String) { App.terminalInstance.type(text: text) - resetModifierStates() + resetUnlockedModifiers() } private func moveCursorAndResetModifiers(codeSequence: String) { App.terminalInstance.moveCursor(codeSequence: codeSequence) - resetModifierStates() + resetUnlockedModifiers() } var body: some View { @@ -66,10 +138,7 @@ struct TerminalKeyboardToolBar: View { }) Button( action: { - controlActive.toggle() - controlGeneration += 1 - App.terminalInstance.setControlActive( - controlActive, generation: controlGeneration) + handleControlTap() }, label: { Text("Ctrl") @@ -78,16 +147,18 @@ struct TerminalKeyboardToolBar: View { controlActive ? Color.accentColor.opacity(0.3) : Color.clear ) .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(Color.accentColor, lineWidth: controlLocked ? 2 : 0) + ) } ) .accessibilityLabel("Control") - .accessibilityValue(controlActive ? "Active" : "Inactive") + .accessibilityValue( + controlLocked ? "Locked" : (controlActive ? "Active" : "Inactive")) Button( action: { - altActive.toggle() - altGeneration += 1 - App.terminalInstance.setAltActive( - altActive, generation: altGeneration) + handleAltTap() }, label: { Text("Alt") @@ -96,10 +167,14 @@ struct TerminalKeyboardToolBar: View { altActive ? Color.accentColor.opacity(0.3) : Color.clear ) .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(Color.accentColor, lineWidth: altLocked ? 2 : 0) + ) } ) .accessibilityLabel("Alt") - .accessibilityValue(altActive ? "Active" : "Inactive") + .accessibilityValue(altLocked ? "Locked" : (altActive ? "Active" : "Inactive")) Button( action: { typeAndResetModifiers(text: "\u{1b}[3~") diff --git a/Dependencies/terminal.bundle/index.html b/Dependencies/terminal.bundle/index.html index 52e842eec..7dfd65bef 100644 --- a/Dependencies/terminal.bundle/index.html +++ b/Dependencies/terminal.bundle/index.html @@ -155,8 +155,10 @@ localEcho.addAutocompleteHandler(autocompleteCommonFiles); var controlActive = false; + var controlLocked = false; var controlGeneration = 0; var altActive = false; + var altLocked = false; var altGeneration = 0; function setControlActive(active, generation) { @@ -164,11 +166,19 @@ controlGeneration = generation; } + function setControlLocked(locked) { + controlLocked = locked; + } + function setAltActive(active, generation) { altActive = active; altGeneration = generation; } + function setAltLocked(locked) { + altLocked = locked; + } + function shouldApplyModifierToCsi(final, params) { if (final >= "A" && final <= "D") { return true; @@ -245,7 +255,7 @@ } function applyModifierStates(data) { - // Capture which modifiers are active before resetting + // Capture which modifiers are active before potentially resetting var wasControlActive = controlActive; var wasAltActive = altActive; @@ -253,15 +263,15 @@ return data; } - // Reset all active modifiers and notify Swift - if (wasControlActive) { + // Reset modifiers only if not locked, and notify Swift + if (wasControlActive && !controlLocked) { controlActive = false; window.webkit.messageHandlers.toggleMessageHandler2.postMessage({ Event: "ControlReset", Generation: controlGeneration, }); } - if (wasAltActive) { + if (wasAltActive && !altLocked) { altActive = false; window.webkit.messageHandlers.toggleMessageHandler2.postMessage({ Event: "AltReset", From 192a8ce8372e9f1fd4f2cefdf807a7cb5f346d44 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 17 Jan 2026 11:30:33 +0800 Subject: [PATCH 06/33] Adjust orders of editor keyboard toolbar items --- CodeApp/Views/TerminalKeyboardToolbar.swift | 40 ++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/CodeApp/Views/TerminalKeyboardToolbar.swift b/CodeApp/Views/TerminalKeyboardToolbar.swift index f6ba152d7..193e8fbb4 100644 --- a/CodeApp/Views/TerminalKeyboardToolbar.swift +++ b/CodeApp/Views/TerminalKeyboardToolbar.swift @@ -109,17 +109,6 @@ struct TerminalKeyboardToolBar: View { var body: some View { HStack(spacing: horizontalSizeClass == .compact ? 8 : 14) { Group { - if UIPasteboard.general.hasStrings || pasteBoardHasContent { - Button( - action: { - if let string = UIPasteboard.general.string { - typeAndResetModifiers(text: string) - } - }, - label: { - Image(systemName: "doc.on.clipboard") - }) - } Button( action: { typeAndResetModifiers(text: "\u{1b}") @@ -134,7 +123,7 @@ struct TerminalKeyboardToolBar: View { typeAndResetModifiers(text: "\t") }, label: { - Text("↹") + Text("Tab") }) Button( action: { @@ -142,7 +131,7 @@ struct TerminalKeyboardToolBar: View { }, label: { Text("Ctrl") - .padding(.horizontal, 4) + .padding(.horizontal, 2) .background( controlActive ? Color.accentColor.opacity(0.3) : Color.clear ) @@ -162,7 +151,7 @@ struct TerminalKeyboardToolBar: View { }, label: { Text("Alt") - .padding(.horizontal, 4) + .padding(.horizontal, 2) .background( altActive ? Color.accentColor.opacity(0.3) : Color.clear ) @@ -175,20 +164,31 @@ struct TerminalKeyboardToolBar: View { ) .accessibilityLabel("Alt") .accessibilityValue(altLocked ? "Locked" : (altActive ? "Active" : "Inactive")) + } + + Spacer() + + Group { Button( action: { typeAndResetModifiers(text: "\u{1b}[3~") }, label: { - Text("Del") + Image(systemName: "delete.right") } ) .accessibilityLabel("Delete") - } - - Spacer() - - Group { + if UIPasteboard.general.hasStrings || pasteBoardHasContent { + Button( + action: { + if let string = UIPasteboard.general.string { + typeAndResetModifiers(text: string) + } + }, + label: { + Image(systemName: "doc.on.clipboard") + }) + } Button( action: { moveCursorAndResetModifiers(codeSequence: "[A") From db5f28247087637fa2f1ca5e8e9cc5e3bdbce0d6 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 17 Jan 2026 11:34:46 +0800 Subject: [PATCH 07/33] update app version to 1.12.0 --- Code.xcodeproj/project.pbxproj | 8 ++++---- CodeApp/Localization/de.lproj/Localizable.strings | 2 +- CodeApp/Localization/en.lproj/Localizable.strings | 2 +- CodeApp/Localization/ja.lproj/Localizable.strings | 2 +- CodeApp/Localization/ko.lproj/Localizable.strings | 2 +- CodeApp/Localization/ru.lproj/Localizable.strings | 2 +- CodeApp/Localization/zh-Hans.lproj/Localizable.strings | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Code.xcodeproj/project.pbxproj b/Code.xcodeproj/project.pbxproj index 48a821d3e..ca1f8ae55 100644 --- a/Code.xcodeproj/project.pbxproj +++ b/Code.xcodeproj/project.pbxproj @@ -4045,7 +4045,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - MARKETING_VERSION = 1.11.0; + MARKETING_VERSION = 1.12.0; OTHER_SWIFT_FLAGS = "-Xcc -Wno-incomplete-umbrella"; PRODUCT_BUNDLE_IDENTIFIER = "thebaselab.VS-Code"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4093,7 +4093,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - MARKETING_VERSION = 1.11.0; + MARKETING_VERSION = 1.12.0; OTHER_SWIFT_FLAGS = "-Xcc -Wno-incomplete-umbrella"; PRODUCT_BUNDLE_IDENTIFIER = "thebaselab.VS-Code"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4330,7 +4330,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - MARKETING_VERSION = 1.11.0; + MARKETING_VERSION = 1.12.0; OTHER_SWIFT_FLAGS = "-Xcc -Wno-incomplete-umbrella"; PRODUCT_BUNDLE_IDENTIFIER = "thebaselab.VS-Code"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -4377,7 +4377,7 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = "$(inherited)"; - MARKETING_VERSION = 1.11.0; + MARKETING_VERSION = 1.12.0; OTHER_SWIFT_FLAGS = "-Xcc -Wno-incomplete-umbrella"; PRODUCT_BUNDLE_IDENTIFIER = "thebaselab.VS-Code"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 1bb406328..2bd496206 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (Januar 2026)** +##### **v1.12.0 (Januar 2026)** #### Start [Neue Datei](https://thebaselab.com/code/newfile) [Datei öffnen](https://thebaselab.com/code/openfile) diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index 42a510f90..be3db0739 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (January 2026)** +##### **v1.12.0 (January 2026)** #### Start [New file](https://thebaselab.com/code/newfile) [Open file](https://thebaselab.com/code/openfile) diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index f866f329b..6a3701ae6 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2026 年 1 月)** +##### **v1.12.0 (2026 年 1 月)** #### 開始 [新しいファイル](https://thebaselab.com/code/newfile) [ファイルを開く](https://thebaselab.com/code/openfile) diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index adbecfc8b..e35463815 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2026년 1월)** +##### **v1.12.0 (2026년 1월)** #### 시작 [새 파일...](https://thebaselab.com/code/newfile) [파일 열기...](https://thebaselab.com/code/openfile) diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index 691b96534..4ff9c7d0a 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (Январь 2026)** +##### **v1.12.0 (Январь 2026)** #### Начало [Новый файл](https://thebaselab.com/code/newfile) [Открыть файл](https://thebaselab.com/code/openfile) diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index 42062cb51..c3f8cbba7 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.11.0 (2026 年 1 月)** +##### **v1.12.0 (2026 年 1 月)** #### 开始 [新文件](https://thebaselab.com/code/newfile) [打开文件](https://thebaselab.com/code/openfile) From 6f610d8c526b8937293a795144dc1421e7bf1989 Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Mon, 19 Jan 2026 00:31:13 -0600 Subject: [PATCH 08/33] Improve terminal management and cleanup logic Refactors terminal data routing to use a tracked remote terminal for consistency, adds a cleanup method to TerminalInstance for resource management, and enhances TerminalManager with unique terminal naming and remote terminal tracking. Also updates TerminalTabBar for better accessibility and code organization, and removes the unused 'Go to Parent Folder' action from ExplorerFileTreeSection. Add multi-terminal support with TerminalManager Introduces TerminalManager to manage multiple terminal instances, refactors codebase to use terminalManager instead of a single terminalInstance, and adds a TerminalTabBar UI for switching between terminals. Updates related views, containers, and extensions to support multi-terminal workflows, including keyboard toolbar and local execution. Maintains backward compatibility for terminalInstance references and ensures UI updates on terminal changes. Improve terminal management and UX for busy terminals Adds confirmation dialog when killing a terminal with a running process, improves cleanup of terminal resources, and optimizes rendering to only show the active terminal. Also refactors terminal options handling and enhances data routing for remote terminals. Improve terminal management and add logging Refactored terminal options loading to use a helper for safer initialization. Added main thread assertions in TerminalManager for thread safety in debug builds. Enhanced terminal naming with localization support and improved duplicate handling. Introduced os.log-based logging for dropped remote terminal data and general terminal management events. Improve terminal naming and UI interactions TerminalManager now generates unique terminal names by reusing gaps from closed terminals, ensuring the lowest available number is used. Terminal actions in ToolbarView now target the active terminal, and MultiTerminalView adds a smooth animation for the tab bar when multiple terminals are present. Add session identifier and service provider support Executor now accepts a customizable sessionIdentifier, allowing unique identification for each terminal instance. TerminalManager tracks and propagates a TerminalServiceProvider to all TerminalInstance objects, improving remote connection handling and service management. Improve terminal management logging and error handling Adds detailed logging to terminal creation, closing, and switching in TerminalManager for better traceability. Enhances error handling in LocalExecutionExtension by providing user notifications for missing or busy executors. Refactors TerminalExtension to avoid repeated lookups of the active terminal when executing scripts. Improve terminal initialization and accessibility handling Adds a displayName property to Executor.State for better user messages, ensures terminal fitAddon is called only when ready, and posts a notification when a terminal is initialized. Refines accessibility labels for terminal tabs and improves active terminal management logic. Also prevents redundant open editor configuration in MainApp. Refactor terminal management and rendering logic Updated TerminalManager to set the terminal service provider only on the active terminal and improved remote terminal tracking. Refactored MultiTerminalView to render all terminals in a ZStack, showing only the active one, to support better view transitions and state management. Improve terminal management and accessibility handling Refactored terminal cleanup and service provider logic for better resource management and reliability. Enhanced terminal naming to avoid duplicates and added logging for failed active terminal assignments. Updated accessibility label construction in TerminalTabBar for clarity. Fixed command evaluation in LocalExecutionExtension to use the correct executor. --- Code.xcodeproj/project.pbxproj | 12 + CodeApp/Containers/MainScene.swift | 6 +- CodeApp/Containers/RemoteContainer.swift | 5 +- CodeApp/Managers/Executor.swift | 20 +- CodeApp/Managers/MainApp.swift | 69 +++- CodeApp/Managers/TerminalInstance.swift | 40 ++- CodeApp/Managers/TerminalManager.swift | 295 ++++++++++++++++++ CodeApp/Views/ActivityBar.swift | 2 +- CodeApp/Views/TerminalKeyboardToolbar.swift | 48 +-- CodeApp/Views/TerminalTabBar.swift | 133 ++++++++ .../LocalExecutionExtension.swift | 24 +- .../TerminalService/TerminalExtension.swift | 134 +++++--- 12 files changed, 694 insertions(+), 94 deletions(-) create mode 100644 CodeApp/Managers/TerminalManager.swift create mode 100644 CodeApp/Views/TerminalTabBar.swift diff --git a/Code.xcodeproj/project.pbxproj b/Code.xcodeproj/project.pbxproj index ca1f8ae55..ba96d6436 100644 --- a/Code.xcodeproj/project.pbxproj +++ b/Code.xcodeproj/project.pbxproj @@ -631,6 +631,8 @@ 947BBCF82C12F5AA00FFD0C5 /* TreeSitterYAMLRunestone in Frameworks */ = {isa = PBXBuildFile; productRef = 947BBCF72C12F5AA00FFD0C5 /* TreeSitterYAMLRunestone */; }; 947BF349262453040015DAEB /* SearchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 947BF348262453040015DAEB /* SearchManager.swift */; }; 94801F93266FB5E400B29D80 /* TerminalInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94801F92266FB5E400B29D80 /* TerminalInstance.swift */; }; + 94801F97266FB5E500B29D80 /* TerminalManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94801F96266FB5E500B29D80 /* TerminalManager.swift */; }; + 94801F98266FB5E500B29D80 /* TerminalManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94801F96266FB5E500B29D80 /* TerminalManager.swift */; }; 94801F95266FBC3500B29D80 /* ViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94801F94266FBC3500B29D80 /* ViewRepresentable.swift */; }; 948488F92BE61684004D4A70 /* TerminalKeyboardToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948488F82BE61684004D4A70 /* TerminalKeyboardToolbar.swift */; }; 948488FA2BE61684004D4A70 /* TerminalKeyboardToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948488F82BE61684004D4A70 /* TerminalKeyboardToolbar.swift */; }; @@ -723,6 +725,8 @@ 94A77829257BC951008FE7B2 /* DocumentPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A77828257BC951008FE7B2 /* DocumentPickerView.swift */; }; 94A7782D257BCEE2008FE7B2 /* getRootDirectory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A7782C257BCEE2008FE7B2 /* getRootDirectory.swift */; }; 94A77830257BD680008FE7B2 /* EditorTabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A7782F257BD680008FE7B2 /* EditorTabs.swift */; }; + 94A77831257BD681008FE7B2 /* TerminalTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A77830257BD681008FE7B2 /* TerminalTabBar.swift */; }; + 94A77832257BD682008FE7B2 /* TerminalTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A77830257BD681008FE7B2 /* TerminalTabBar.swift */; }; 94A77832257BDC50008FE7B2 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A77831257BDC50008FE7B2 /* SafariView.swift */; }; 94A77834257BE2D8008FE7B2 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A77833257BE2D8008FE7B2 /* EditorView.swift */; }; 94A7FFB3268D085300369147 /* BottomBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94A7FFB2268D085300369147 /* BottomBar.swift */; }; @@ -1833,6 +1837,7 @@ 947A9D8827D3C562007680C3 /* UIApplication+getSafeArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+getSafeArea.swift"; sourceTree = ""; }; 947BF348262453040015DAEB /* SearchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchManager.swift; sourceTree = ""; }; 94801F92266FB5E400B29D80 /* TerminalInstance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalInstance.swift; sourceTree = ""; }; + 94801F96266FB5E500B29D80 /* TerminalManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalManager.swift; sourceTree = ""; }; 94801F94266FBC3500B29D80 /* ViewRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewRepresentable.swift; sourceTree = ""; }; 948488F82BE61684004D4A70 /* TerminalKeyboardToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalKeyboardToolbar.swift; sourceTree = ""; }; 9484BDD02B46FAEE003BCB8A /* injection.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = injection.js; sourceTree = ""; }; @@ -1902,6 +1907,7 @@ 94A77828257BC951008FE7B2 /* DocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPickerView.swift; sourceTree = ""; }; 94A7782C257BCEE2008FE7B2 /* getRootDirectory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = getRootDirectory.swift; sourceTree = ""; }; 94A7782F257BD680008FE7B2 /* EditorTabs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorTabs.swift; sourceTree = ""; }; + 94A77830257BD681008FE7B2 /* TerminalTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalTabBar.swift; sourceTree = ""; }; 94A77831257BDC50008FE7B2 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = ""; }; 94A77833257BE2D8008FE7B2 /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorView.swift; sourceTree = ""; }; 94A7FFB2268D085300369147 /* BottomBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomBar.swift; sourceTree = ""; }; @@ -2958,6 +2964,7 @@ 94A045FD2804853200182275 /* DescriptionText.swift */, 948E478126502B6900A6110D /* EditorTab.swift */, 94A7782F257BD680008FE7B2 /* EditorTabs.swift */, + 94A77830257BD681008FE7B2 /* TerminalTabBar.swift */, 94F6B50F280EFD07000DBAE2 /* FileDisplayName.swift */, 94A77791257AB805008FE7B2 /* FileIcon.swift */, 94A046002804865000182275 /* SideBarButton.swift */, @@ -3140,6 +3147,7 @@ 94A777BD257B74EE008FE7B2 /* NotificationManager.swift */, 942ACB9C281312900067114D /* SpellChecker.swift */, 94801F92266FB5E400B29D80 /* TerminalInstance.swift */, + 94801F96266FB5E500B29D80 /* TerminalManager.swift */, 9F046C312922203E00BDE4E9 /* ToolbarManager.swift */, 9F046C3429222D8E00BDE4E9 /* ExtensionManager.swift */, 9FA1225B2A8B209500E7B417 /* CodeAppContributionPointManager.swift */, @@ -3696,6 +3704,7 @@ 942ACB9E281312900067114D /* SpellChecker.swift in Sources */, 94E6CC7C2806FBAF00939E4F /* SFTPFileSystemProvider.swift in Sources */, 94196973280316C7008AAEB2 /* EditorTabs.swift in Sources */, + 94A77832257BD682008FE7B2 /* TerminalTabBar.swift in Sources */, 94196974280316C7008AAEB2 /* LocalGitServiceProvider.swift in Sources */, 9474D2982B6B4B1300CCC530 /* EditorImplemenationView.swift in Sources */, 94196975280316C7008AAEB2 /* SourceControlIdentityConfiguration.swift in Sources */, @@ -3739,6 +3748,7 @@ 947313132BDFB80D004A9960 /* ExtensionCommunicationHelper.swift in Sources */, 94196986280316C7008AAEB2 /* node.swift in Sources */, 94196988280316C7008AAEB2 /* TerminalInstance.swift in Sources */, + 94801F98266FB5E500B29D80 /* TerminalManager.swift in Sources */, 94196989280316C7008AAEB2 /* convertCArguments.swift in Sources */, 94FF337528435158003DE5DD /* SettingsFontPicker.swift in Sources */, 9F062FEA2B58D416006210AA /* TableView.swift in Sources */, @@ -3888,6 +3898,7 @@ 942ACB9D281312900067114D /* SpellChecker.swift in Sources */, 94E6CC7B2806FBAF00939E4F /* SFTPFileSystemProvider.swift in Sources */, 94A77830257BD680008FE7B2 /* EditorTabs.swift in Sources */, + 94A77831257BD681008FE7B2 /* TerminalTabBar.swift in Sources */, 944FC3FF25C543CD00C7C43C /* LocalGitServiceProvider.swift in Sources */, 9474D2972B6B4B1300CCC530 /* EditorImplemenationView.swift in Sources */, 9494A3A52587479F004A103E /* SourceControlIdentityConfiguration.swift in Sources */, @@ -3931,6 +3942,7 @@ 947313122BDFB80D004A9960 /* ExtensionCommunicationHelper.swift in Sources */, 949B3CC725DEAAA700BC83B5 /* node.swift in Sources */, 94801F93266FB5E400B29D80 /* TerminalInstance.swift in Sources */, + 94801F97266FB5E500B29D80 /* TerminalManager.swift in Sources */, 94F2FEA926A2EB0E007EBC6D /* convertCArguments.swift in Sources */, 94FF337428435158003DE5DD /* SettingsFontPicker.swift in Sources */, 9F062FE92B58D416006210AA /* TableView.swift in Sources */, diff --git a/CodeApp/Containers/MainScene.swift b/CodeApp/Containers/MainScene.swift index 9fe7b35ce..6a2f3df8a 100644 --- a/CodeApp/Containers/MainScene.swift +++ b/CodeApp/Containers/MainScene.swift @@ -119,7 +119,7 @@ struct MainScene: View { } App.monacoInstance.theme = EditorTheme( dark: ThemeManager.darkTheme, light: ThemeManager.lightTheme) - App.terminalInstance.applyTheme(rawTheme: theme.dictionary) + App.terminalManager.applyThemeToAll(rawTheme: theme.dictionary) } ) } @@ -154,7 +154,7 @@ private struct MainView: View { panelHeight = 200 } isPanelVisible.toggle() - App.terminalInstance.webView.becomeFirstResponder() + App.terminalManager.activeTerminal?.webView.becomeFirstResponder() } var body: some View { @@ -232,7 +232,7 @@ private struct MainView: View { App.setUpEditorInstance() } .onChange(of: terminalOptions) { newValue in - App.terminalInstance.options = newValue.value + App.terminalManager.applyOptionsToAll(newValue.value) } .hiddenScrollableContentBackground() .onAppear { diff --git a/CodeApp/Containers/RemoteContainer.swift b/CodeApp/Containers/RemoteContainer.swift index 176cb0f24..e521dde82 100644 --- a/CodeApp/Containers/RemoteContainer.swift +++ b/CodeApp/Containers/RemoteContainer.swift @@ -179,8 +179,9 @@ struct RemoteContainer: View { App.loadRepository(url: hostUrl) App.notificationManager.showInformationMessage( "remote.connected") - App.terminalInstance.terminalServiceProvider = - App.workSpaceStorage.terminalServiceProvider + // Set terminal service provider for the active terminal + App.terminalManager.setTerminalServiceProviderForAll( + App.workSpaceStorage.terminalServiceProvider) } continuation.resume(returning: ()) } diff --git a/CodeApp/Managers/Executor.swift b/CodeApp/Managers/Executor.swift index b056e8d37..7b71221b1 100644 --- a/CodeApp/Managers/Executor.swift +++ b/CodeApp/Managers/Executor.swift @@ -16,7 +16,7 @@ class Executor { case interactive } - private let persistentIdentifier = "com.thebaselab.terminal" + private let persistentIdentifier: String private var pid: pid_t? = nil private var stdin_file: UnsafeMutablePointer? @@ -40,10 +40,13 @@ class Executor { } init( - root: URL, onStdout: @escaping ((_ data: Data) -> Void), + root: URL, + sessionIdentifier: String = "com.thebaselab.terminal", + onStdout: @escaping ((_ data: Data) -> Void), onStderr: @escaping ((_ data: Data) -> Void), onRequestInput: @escaping ((_ prompt: String) -> Void) ) { + persistentIdentifier = sessionIdentifier currentWorkingDirectory = root prompt = "\(root.lastPathComponent) $ " receivedStdout = onStdout @@ -283,3 +286,16 @@ class Executor { } } } + +extension Executor.State { + var displayName: String { + switch self { + case .idle: + return NSLocalizedString("Idle", comment: "Executor state label") + case .running: + return NSLocalizedString("Running", comment: "Executor state label") + case .interactive: + return NSLocalizedString("Interactive", comment: "Executor state label") + } + } +} diff --git a/CodeApp/Managers/MainApp.swift b/CodeApp/Managers/MainApp.swift index 080d540a7..575378796 100644 --- a/CodeApp/Managers/MainApp.swift +++ b/CodeApp/Managers/MainApp.swift @@ -7,11 +7,14 @@ import Combine import CoreSpotlight +import os.log import SwiftGit2 import SwiftUI import UniformTypeIdentifiers import ios_system +private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Code", category: "MainApp") + struct CheckoutDestination: Identifiable { var id = UUID() var reference: ReferenceType @@ -191,8 +194,13 @@ class MainApp: ObservableObject { var editorShortcuts: [MonacoEditorAction] = [] var monacoStateToRestore: String? = nil - var terminalInstance: TerminalInstance! = nil + let terminalManager: TerminalManager var monacoInstance: EditorImplementation! = nil + + // Backward compatibility: returns the active terminal + var terminalInstance: TerminalInstance! { + terminalManager.activeTerminal + } var editorTypesMonitor: FolderMonitor? = nil let deviceSupportsBiometricAuth: Bool = biometricAuthSupported() let sceneIdentifier = UUID() @@ -202,6 +210,8 @@ class MainApp: ObservableObject { private var searchCancellable: AnyCancellable? = nil private var textSearchCancellable: AnyCancellable? = nil private var workSpaceCancellable: AnyCancellable? = nil + private var cancellables = Set() + private var isConfiguringOpenEditors = false @AppStorage("alwaysOpenInNewTab") var alwaysOpenInNewTab: Bool = false @AppStorage("explorer.confirmBeforeDelete") var confirmBeforeDelete = false @@ -221,18 +231,23 @@ class MainApp: ObservableObject { self.workSpaceStorage = WorkSpaceStorage(url: rootDir) - terminalInstance = TerminalInstance(root: rootDir, options: terminalOptions.value) + // Use helper to read options before self is fully initialized + let options = TerminalManager.readTerminalOptionsFromDefaults() + self.terminalManager = TerminalManager(rootURL: rootDir, options: options) setUpEditorInstance() - terminalInstance.openEditor = { [weak self] url in - if url.isDirectory { - DispatchQueue.main.async { - self?.loadFolder(url: url) - } - } else { - self?.openFile(url: url) + // Set up openEditor callback for initial terminal + configureOpenEditorForTerminals() + + // Forward terminalManager changes to MainApp so UI updates + terminalManager.objectWillChange.sink { [weak self] _ in + DispatchQueue.main.async { + guard let self = self else { return } + self.objectWillChange.send() + // Set up openEditor for any new terminals + self.scheduleConfigureOpenEditorForTerminals() } - } + }.store(in: &cancellables) // TODO: Support deleted files detection for remote files workSpaceStorage.onDirectoryChange { [weak self] url in @@ -248,7 +263,13 @@ class MainApp: ObservableObject { } } workSpaceStorage.onTerminalData { [weak self] data in - self?.terminalInstance.write(data: data) + guard let self = self else { return } + // Use the tracked remote terminal for consistent data routing + if let terminal = self.terminalManager.remoteTerminal { + terminal.write(data: data) + } else { + logger.warning("Remote terminal data dropped: no remote terminal available (\(data.count) bytes)") + } } loadRepository(url: rootDir) @@ -300,6 +321,30 @@ class MainApp: ObservableObject { } } + private func configureOpenEditorForTerminals() { + for terminal in terminalManager.terminals where terminal.openEditor == nil { + terminal.openEditor = { [weak self] url in + if url.isDirectory { + DispatchQueue.main.async { + self?.loadFolder(url: url) + } + } else { + self?.openFile(url: url) + } + } + } + } + + private func scheduleConfigureOpenEditorForTerminals() { + guard !isConfiguringOpenEditors else { return } + isConfiguringOpenEditors = true + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.configureOpenEditorForTerminals() + self.isConfiguringOpenEditors = false + } + } + private func updateActiveEditor() async { guard let activeTextEditor else { Task { @@ -937,7 +982,7 @@ class MainApp: ObservableObject { if resetEditors { DispatchQueue.main.async { self.closeAllEditors() - self.terminalInstance.resetAndSetNewRootDirectory(url: url) + self.terminalManager.resetAndSetNewRootDirectory(url: url) } } extensionManager.onWorkSpaceStorageChanged(newUrl: url) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 6c5819bd1..62db1ae13 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -18,7 +18,11 @@ struct TerminalOptions: Codable { // subsequent options must be made optional } -class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { +class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate, Identifiable { + + let id: UUID + var name: String + private(set) var isReady = false var options: TerminalOptions { didSet { @@ -34,11 +38,10 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { if terminalServiceProvider != nil { self.startInteractive() } - terminalServiceProvider?.onDisconnect(callback: { + if terminalServiceProvider == nil && oldValue != nil { self.stopInteractive() - self.terminalServiceProvider = nil self.clearLine() - }) + } } } public var webView: WebViewBase = WebViewBase() @@ -383,6 +386,8 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { self.applyTheme(rawTheme: darkTheme.dictionary) } configureCustomOptions() + isReady = true + NotificationCenter.default.post(name: .terminalDidInitialize, object: self) case "window.size.change": let cols = result["Cols"] as! Int let rows = result["Rows"] as! Int @@ -440,11 +445,14 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate { } } - init(root: URL, options: TerminalOptions) { + init(root: URL, options: TerminalOptions, name: String = "Terminal", id: UUID = UUID()) { + self.id = id + self.name = name self.options = options super.init() self.executor = Executor( root: root, + sessionIdentifier: "com.thebaselab.terminal.\(id.uuidString)", onStdout: { [weak self] data in self?.writeToLocalTerminal(data: data) }, @@ -535,6 +543,27 @@ extension TerminalInstance: WKUIDelegate { } } +// Cleanup method + +extension TerminalInstance { + /// Cleans up resources before the terminal is deallocated. + /// Call this method before removing the terminal from TerminalManager. + func cleanup() { + if executor?.state != .idle { + executor?.kill() + } + terminalServiceProvider?.kill() + terminalServiceProvider = nil + webView.stopLoading() + webView.navigationDelegate = nil + webView.uiDelegate = nil + webView.removeFromSuperview() + webView.configuration.userContentController.removeAllScriptMessageHandlers() + executor = nil + openEditor = nil + } +} + // Keyboard toolbar methods extension TerminalInstance { @@ -567,4 +596,5 @@ extension TerminalInstance { extension Notification.Name { static let terminalControlReset = Notification.Name("terminalControlReset") static let terminalAltReset = Notification.Name("terminalAltReset") + static let terminalDidInitialize = Notification.Name("terminalDidInitialize") } diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift new file mode 100644 index 000000000..2f8fc289b --- /dev/null +++ b/CodeApp/Managers/TerminalManager.swift @@ -0,0 +1,295 @@ +// +// TerminalManager.swift +// Code +// +// Created by Thales Matheus Mendonça Santos - January 2026 +// + +import SwiftUI +import os.log + +private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Code", category: "TerminalManager") + +/// Manages multiple terminal instances. +/// - Important: Access this class only from the main thread. Debug builds will assert this. +class TerminalManager: ObservableObject { + @Published var terminals: [TerminalInstance] = [] + @Published var activeTerminalId: UUID? + + /// Tracks the terminal that initiated a remote connection for proper data routing + @Published private(set) var remoteTerminalId: UUID? + + private var rootURL: URL + private var options: TerminalOptions + private var terminalServiceProvider: TerminalServiceProvider? + private var terminalCounter: Int = 1 + + /// Asserts that we're on the main thread in debug builds + private func assertMainThread(_ function: String = #function) { + assert(Thread.isMainThread, "TerminalManager.\(function) must be called on the main thread") + } + + static let maxTerminals = 10 + + /// Reads terminal options from UserDefaults. + /// Useful during initialization when @AppStorage properties aren't yet accessible. + static func readTerminalOptionsFromDefaults() -> TerminalOptions { + if let rawValue = UserDefaults.standard.string(forKey: "terminalOptions"), + let data = rawValue.data(using: .utf8), + let decoded = try? JSONDecoder().decode(TerminalOptions.self, from: data) { + return decoded + } + return TerminalOptions() + } + + var activeTerminal: TerminalInstance? { + get { + guard let id = activeTerminalId else { return terminals.first } + return terminals.first { $0.id == id } ?? terminals.first + } + set { + guard + let id = newValue?.id, + terminals.contains(where: { $0.id == id }) + else { + let attemptedId = newValue?.id.uuidString ?? "nil" + let availableIds = terminals.map { $0.id.uuidString }.joined(separator: ", ") + logger.warning( + "active terminal set failed: attempted id: \(attemptedId, privacy: .public), available ids: [\(availableIds, privacy: .public)]" + ) + setActiveTerminalId(nil) + return + } + setActiveTerminalId(id) + } + } + + /// Returns the terminal designated for remote data. + var remoteTerminal: TerminalInstance? { + if let id = remoteTerminalId { + return terminals.first { $0.id == id } + } + return terminals.first { $0.terminalServiceProvider != nil } + } + + init(rootURL: URL, options: TerminalOptions) { + self.rootURL = rootURL + self.options = options + self.terminalServiceProvider = nil + + // Create the initial terminal + let initialName = String( + format: NSLocalizedString("Terminal %d", comment: "Terminal name with number"), + 1 + ) + let initialTerminal = createTerminalInstance(name: initialName) + terminals.append(initialTerminal) + setActiveTerminalId(initialTerminal.id) + } + + private func createTerminalInstance(name: String) -> TerminalInstance { + let terminal = TerminalInstance(root: rootURL, options: options, name: name) + if let provider = terminalServiceProvider, terminal.id == remoteTerminalId { + terminal.terminalServiceProvider = provider + } + return terminal + } + + /// Generates a unique terminal name by finding the lowest available number. + /// This reuses gaps from closed terminals (e.g., if "Terminal 2" was closed, the next terminal uses "Terminal 2"). + private func generateUniqueTerminalName() -> String { + let existingNames = Set(terminals.map { $0.name }) + + // Find the lowest available terminal number + var number = 1 + while number <= TerminalManager.maxTerminals + 1 { + let candidateName = String( + format: NSLocalizedString("Terminal %d", comment: "Terminal name with number"), + number + ) + if !existingNames.contains(candidateName) { + return candidateName + } + number += 1 + } + + // Fallback: use counter with suffix (should rarely happen) + terminalCounter += 1 + let baseName = String( + format: NSLocalizedString("Terminal %d", comment: "Terminal name with number"), + terminalCounter + ) + let maxAttempts = TerminalManager.maxTerminals + 1 + var suffix = 1 + var candidateName = String( + format: NSLocalizedString("%@ (%d)", comment: "Terminal name with duplicate suffix"), + baseName, suffix + ) + while existingNames.contains(candidateName) && suffix < maxAttempts { + suffix += 1 + candidateName = String( + format: NSLocalizedString("%@ (%d)", comment: "Terminal name with duplicate suffix"), + baseName, suffix + ) + } + if existingNames.contains(candidateName) { + terminalCounter += 1 + candidateName = String( + format: NSLocalizedString( + "%@ (%d-%d)", + comment: "Terminal name with duplicate suffix and unique token" + ), + baseName, + suffix, + terminalCounter + ) + } + return candidateName + } + + @discardableResult + func createTerminal(name: String? = nil) -> TerminalInstance { + assertMainThread() + guard terminals.count < TerminalManager.maxTerminals else { + logger.debug("create blocked: max reached (count: \(self.terminals.count, privacy: .public), max: \(TerminalManager.maxTerminals, privacy: .public))") + // Return the active terminal if at max capacity + // Invariant: terminals array is never empty after init (enforced by closeTerminal guard) + precondition(!terminals.isEmpty, "TerminalManager must always have at least one terminal") + return activeTerminal ?? terminals.first! + } + + let terminalName = name ?? generateUniqueTerminalName() + let terminal = createTerminalInstance(name: terminalName) + terminals.append(terminal) + setActiveTerminalId(terminal.id) + logger.info("created terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + return terminal + } + + func closeTerminal(id: UUID) { + assertMainThread() + // Don't allow closing the last terminal + guard terminals.count > 1 else { + logger.debug("close blocked: last terminal (count: \(self.terminals.count, privacy: .public)) id: \(id, privacy: .public)") + return + } + + guard let index = terminals.firstIndex(where: { $0.id == id }) else { + logger.debug("close failed: terminal not found id: \(id, privacy: .public)") + return + } + + // If closing active terminal, switch to another one + if activeTerminalId == id { + if index > 0 { + setActiveTerminalId(terminals[index - 1].id) + } else { + setActiveTerminalId(terminals[1].id) + } + } + // Clean up the terminal's resources using the cleanup method + let terminal = terminals[index] + terminal.cleanup() + + terminals.remove(at: index) + syncRemoteTerminalId() + logger.info("closed terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + } + + /// Check if a terminal has a running process + func isTerminalBusy(id: UUID) -> Bool { + guard let terminal = terminals.first(where: { $0.id == id }) else { return false } + return terminal.executor?.state == .running || terminal.executor?.state == .interactive + } + + func setActiveTerminal(id: UUID) { + assertMainThread() + guard let terminal = terminals.first(where: { $0.id == id }) else { + logger.debug("switch failed: terminal not found id: \(id, privacy: .public)") + return + } + setActiveTerminalId(terminal.id) + logger.info("switched terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + } + + func renameTerminal(id: UUID, name: String) { + assertMainThread() + guard let terminal = terminals.first(where: { $0.id == id }) else { return } + objectWillChange.send() + terminal.name = name + } + + func applyThemeToAll(rawTheme: [String: Any]) { + assertMainThread() + for terminal in terminals { + terminal.applyTheme(rawTheme: rawTheme) + } + } + + func applyOptionsToAll(_ options: TerminalOptions) { + assertMainThread() + self.options = options + for terminal in terminals { + terminal.options = options + } + } + + func resetAndSetNewRootDirectory(url: URL) { + assertMainThread() + rootURL = url + for terminal in terminals { + terminal.resetAndSetNewRootDirectory(url: url) + } + } + + /// Sets the terminal service provider on the active terminal only. + func setTerminalServiceProviderForAll(_ provider: TerminalServiceProvider?) { + assertMainThread() + terminalServiceProvider = provider + let targetId = activeTerminalId ?? terminals.first?.id + for terminal in terminals { + terminal.terminalServiceProvider = + terminal.id == targetId ? provider : nil + } + // Track the active terminal as the remote terminal when connecting + if let provider = provider { + provider.onDisconnect { [weak self] in + DispatchQueue.main.async { + self?.setTerminalServiceProviderForAll(nil) + } + } + remoteTerminalId = targetId + } else { + remoteTerminalId = nil + } + syncRemoteTerminalId() + } + + var canCreateNewTerminal: Bool { + terminals.count < TerminalManager.maxTerminals + } + + private func setActiveTerminalId(_ id: UUID?) { + activeTerminalId = id + syncRemoteTerminalId() + } + + private func syncRemoteTerminalId() { + guard terminalServiceProvider != nil else { + remoteTerminalId = nil + return + } + + if let active = activeTerminal, active.terminalServiceProvider != nil { + remoteTerminalId = active.id + return + } + + if let currentId = remoteTerminalId, + terminals.contains(where: { $0.id == currentId && $0.terminalServiceProvider != nil }) { + return + } + + remoteTerminalId = terminals.first { $0.terminalServiceProvider != nil }?.id + } +} diff --git a/CodeApp/Views/ActivityBar.swift b/CodeApp/Views/ActivityBar.swift index cb3e760be..465254a6a 100644 --- a/CodeApp/Views/ActivityBar.swift +++ b/CodeApp/Views/ActivityBar.swift @@ -80,7 +80,7 @@ struct ActivityBar: View { func removeFocus() { Task { await App.monacoInstance.blur() } - App.terminalInstance.executeScript( + App.terminalManager.activeTerminal?.executeScript( "document.getElementById('overlay').focus()") } diff --git a/CodeApp/Views/TerminalKeyboardToolbar.swift b/CodeApp/Views/TerminalKeyboardToolbar.swift index 193e8fbb4..6237dc29e 100644 --- a/CodeApp/Views/TerminalKeyboardToolbar.swift +++ b/CodeApp/Views/TerminalKeyboardToolbar.swift @@ -21,28 +21,38 @@ struct TerminalKeyboardToolBar: View { @State var altLastTapTime: Date? @State var altGeneration = 0 + // Optional terminal ID - if nil, uses active terminal + var terminalId: UUID? + + private var terminal: TerminalInstance? { + if let id = terminalId { + return App.terminalManager.terminals.first { $0.id == id } + } + return App.terminalManager.activeTerminal + } + private let doubleTapInterval: TimeInterval = 0.3 private func resetModifierStates() { controlActive = false controlLocked = false - App.terminalInstance.setControlActive(false, generation: controlGeneration) - App.terminalInstance.setControlLocked(false) + terminal?.setControlActive(false, generation: controlGeneration) + terminal?.setControlLocked(false) altActive = false altLocked = false - App.terminalInstance.setAltActive(false, generation: altGeneration) - App.terminalInstance.setAltLocked(false) + terminal?.setAltActive(false, generation: altGeneration) + terminal?.setAltLocked(false) } private func resetUnlockedModifiers() { // Reset modifiers only if they are not locked if !controlLocked { controlActive = false - App.terminalInstance.setControlActive(false, generation: controlGeneration) + terminal?.setControlActive(false, generation: controlGeneration) } if !altLocked { altActive = false - App.terminalInstance.setAltActive(false, generation: altGeneration) + terminal?.setAltActive(false, generation: altGeneration) } } @@ -57,17 +67,17 @@ struct TerminalKeyboardToolBar: View { controlLocked = false controlActive = false controlGeneration += 1 - App.terminalInstance.setControlLocked(false) - App.terminalInstance.setControlActive(false, generation: controlGeneration) + terminal?.setControlLocked(false) + terminal?.setControlActive(false, generation: controlGeneration) } else if isDoubleTap && controlActive { // Double tap while active: lock controlLocked = true - App.terminalInstance.setControlLocked(true) + terminal?.setControlLocked(true) } else { // Single tap: toggle active state controlActive.toggle() controlGeneration += 1 - App.terminalInstance.setControlActive(controlActive, generation: controlGeneration) + terminal?.setControlActive(controlActive, generation: controlGeneration) } } @@ -82,27 +92,27 @@ struct TerminalKeyboardToolBar: View { altLocked = false altActive = false altGeneration += 1 - App.terminalInstance.setAltLocked(false) - App.terminalInstance.setAltActive(false, generation: altGeneration) + terminal?.setAltLocked(false) + terminal?.setAltActive(false, generation: altGeneration) } else if isDoubleTap && altActive { // Double tap while active: lock altLocked = true - App.terminalInstance.setAltLocked(true) + terminal?.setAltLocked(true) } else { // Single tap: toggle active state altActive.toggle() altGeneration += 1 - App.terminalInstance.setAltActive(altActive, generation: altGeneration) + terminal?.setAltActive(altActive, generation: altGeneration) } } private func typeAndResetModifiers(text: String) { - App.terminalInstance.type(text: text) + terminal?.type(text: text) resetUnlockedModifiers() } private func moveCursorAndResetModifiers(codeSequence: String) { - App.terminalInstance.moveCursor(codeSequence: codeSequence) + terminal?.moveCursor(codeSequence: codeSequence) resetUnlockedModifiers() } @@ -220,7 +230,7 @@ struct TerminalKeyboardToolBar: View { Button( action: { resetModifierStates() - App.terminalInstance.blur() + terminal?.blur() }, label: { Image(systemName: "keyboard.chevron.compact.down") @@ -246,7 +256,7 @@ struct TerminalKeyboardToolBar: View { .onReceive( NotificationCenter.default.publisher( for: .terminalControlReset, - object: App.terminalInstance + object: terminal ), perform: { notification in if let generation = notification.userInfo?["generation"] as? Int, @@ -259,7 +269,7 @@ struct TerminalKeyboardToolBar: View { .onReceive( NotificationCenter.default.publisher( for: .terminalAltReset, - object: App.terminalInstance + object: terminal ), perform: { notification in if let generation = notification.userInfo?["generation"] as? Int, diff --git a/CodeApp/Views/TerminalTabBar.swift b/CodeApp/Views/TerminalTabBar.swift new file mode 100644 index 000000000..998c8b6d9 --- /dev/null +++ b/CodeApp/Views/TerminalTabBar.swift @@ -0,0 +1,133 @@ +// +// TerminalTabBar.swift +// Code +// +// Created by Thales Matheus Mendonça Santos - January 2026 +// + +import SwiftUI + +private enum TerminalTabBarConstants { + static let tabBarWidth: CGFloat = 50 + static let rowHeight: CGFloat = 36 + static let iconSize: CGFloat = 14 + static let activeIndicatorWidth: CGFloat = 2 +} + +struct TerminalTabBar: View { + @EnvironmentObject var App: MainApp + + var body: some View { + VStack(spacing: 0) { + // Terminal list + ScrollView(.vertical, showsIndicators: false) { + LazyVStack(spacing: 0) { + ForEach(App.terminalManager.terminals) { terminal in + TerminalTabRow( + terminal: terminal, + isActive: terminal.id == App.terminalManager.activeTerminalId, + canClose: App.terminalManager.terminals.count > 1, + onSelect: { + App.terminalManager.setActiveTerminal(id: terminal.id) + }, + onClose: { + App.terminalManager.closeTerminal(id: terminal.id) + } + ) + } + } + } + } + .frame(width: TerminalTabBarConstants.tabBarWidth) + .background(Color(id: "sideBar.background")) + } +} + +struct TerminalTabRow: View { + @EnvironmentObject var App: MainApp + + let terminal: TerminalInstance + let isActive: Bool + let canClose: Bool + let onSelect: () -> Void + let onClose: () -> Void + + @State private var showingKillConfirmation = false + + private var isTerminalBusy: Bool { + App.terminalManager.isTerminalBusy(id: terminal.id) + } + + private var accessibilityLabel: String { + let activeLabel = NSLocalizedString( + "Active", + comment: "Accessibility label for active terminal" + ) + let runningLabel = NSLocalizedString( + "Running", + comment: "Accessibility label for running terminal" + ) + var parts = [terminal.name] + if isActive { + parts.append(activeLabel) + } + if isTerminalBusy { + parts.append(runningLabel) + } + return parts.joined(separator: ", ") + } + + var body: some View { + HStack(spacing: 0) { + Spacer() + // Icon + Image(systemName: "terminal") + .font(.system(size: TerminalTabBarConstants.iconSize)) + .foregroundColor(isActive ? Color(id: "list.activeSelectionForeground") : Color(id: "foreground")) + .frame(width: 20, height: 20) + Spacer() + } + .frame(height: TerminalTabBarConstants.rowHeight) + .overlay( + // Left border indicator for active tab (VS Code style) + HStack { + if isActive { + Rectangle() + .fill(Color.accentColor) + .frame(width: TerminalTabBarConstants.activeIndicatorWidth) + } + Spacer() + } + ) + .contentShape(Rectangle()) + .onTapGesture { + onSelect() + } + .accessibilityElement(children: .ignore) + .accessibilityLabel(accessibilityLabel) + .accessibilityAddTraits(isActive ? [.isSelected, .isButton] : [.isButton]) + .accessibilityHint(NSLocalizedString("Double tap to switch to this terminal", comment: "Accessibility hint for terminal tab")) + .contextMenu { + if canClose { + Button(NSLocalizedString("Kill Terminal", comment: ""), role: .destructive) { + if isTerminalBusy { + showingKillConfirmation = true + } else { + onClose() + } + } + } + } + .alert( + NSLocalizedString("Kill Terminal?", comment: ""), + isPresented: $showingKillConfirmation + ) { + Button(NSLocalizedString("Cancel", comment: ""), role: .cancel) {} + Button(NSLocalizedString("Kill", comment: ""), role: .destructive) { + onClose() + } + } message: { + Text(NSLocalizedString("This terminal has a running process. Are you sure you want to kill it?", comment: "")) + } + } +} diff --git a/Extensions/LocalExecution/LocalExecutionExtension.swift b/Extensions/LocalExecution/LocalExecutionExtension.swift index a2acb2d74..9ee0f184c 100644 --- a/Extensions/LocalExecution/LocalExecutionExtension.swift +++ b/Extensions/LocalExecution/LocalExecutionExtension.swift @@ -44,7 +44,23 @@ class LocalExecutionExtension: CodeAppExtension { private func runCodeLocally(app: MainApp) async { - guard app.terminalInstance.executor?.state == .idle else { return } + guard let activeTerminal = app.terminalManager.activeTerminal else { + app.notificationManager.showErrorMessage("Cannot run: no active terminal.") + return + } + + guard let executor = activeTerminal.executor else { + app.notificationManager.showErrorMessage( + "Cannot run: terminal '\(activeTerminal.name)' has no executor.") + return + } + + guard executor.state == .idle else { + app.notificationManager.showWarningMessage( + "Cannot run: terminal '\(activeTerminal.name)' executor is \(executor.state.displayName) (expected idle)." + ) + return + } guard let activeTextEditor = app.activeTextEditor else { return @@ -71,14 +87,14 @@ class LocalExecutionExtension: CodeAppExtension { } if app.terminalOptions.value.shouldShowCompilerPath { - app.terminalInstance.executeScript( + activeTerminal.executeScript( "localEcho.println(`\(parsedCommands.joined(separator: " && "))`);readLine('');") } else { let commandName = parsedCommands.first?.components(separatedBy: " ").first ?? activeTextEditor.languageIdentifier - app.terminalInstance.executeScript("localEcho.println(`\(commandName)`);readLine('');") + activeTerminal.executeScript("localEcho.println(`\(commandName)`);readLine('');") } - app.terminalInstance.executor?.evaluateCommands(parsedCommands) + executor.evaluateCommands(parsedCommands) } } diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index ea14039d7..4cafb6d5a 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -11,7 +11,7 @@ class TerminalExtension: CodeAppExtension { override func onInitialize(app: MainApp, contribution: CodeAppExtension.Contribution) { let panel = Panel( labelId: "TERMINAL", - mainView: AnyView(TerminalView()), + mainView: AnyView(MultiTerminalView()), toolBarView: AnyView(ToolbarView()) ) contribution.panel.registerPanel(panel: panel) @@ -23,9 +23,17 @@ private struct ToolbarView: View { var body: some View { HStack(spacing: 12) { + Button(action: { + App.terminalManager.createTerminal() + }) { + Image(systemName: "plus") + } + .disabled(!App.terminalManager.canCreateNewTerminal) + .help("New Terminal") + Button( action: { - App.terminalInstance.sendInterrupt() + App.terminalManager.activeTerminal?.sendInterrupt() }, label: { Text("^C") @@ -34,7 +42,7 @@ private struct ToolbarView: View { Button( action: { - App.terminalInstance.reset() + App.terminalManager.activeTerminal?.reset() }, label: { Image(systemName: "trash") @@ -45,13 +53,13 @@ private struct ToolbarView: View { } private struct _TerminalView: UIViewRepresentable { - var implementation: TerminalInstance + let terminal: TerminalInstance @EnvironmentObject var App: MainApp private func injectBarButtons(webView: WebViewBase) { let toolbar = UIHostingController( - rootView: TerminalKeyboardToolBar().environmentObject(App)) + rootView: TerminalKeyboardToolBar(terminalId: terminal.id).environmentObject(App)) toolbar.view.frame = CGRect( x: 0, y: 0, width: (webView.bounds.width), height: 40) @@ -63,63 +71,97 @@ private struct _TerminalView: UIViewRepresentable { } func makeUIView(context: Context) -> UIView { - if implementation.options.toolbarEnabled { - injectBarButtons(webView: implementation.webView) + if terminal.options.toolbarEnabled { + injectBarButtons(webView: terminal.webView) } - return implementation.webView + return terminal.webView } func updateUIView(_ uiView: UIView, context: Context) { - if implementation.options.toolbarEnabled { - injectBarButtons(webView: implementation.webView) + if terminal.options.toolbarEnabled { + injectBarButtons(webView: terminal.webView) } else { - removeBarButtons(webView: implementation.webView) + removeBarButtons(webView: terminal.webView) } } - } -private struct TerminalView: View { +private struct MultiTerminalView: View { @EnvironmentObject var App: MainApp @AppStorage("consoleFontSize") var consoleFontSize: Int = 14 + private func fitTerminalIfReady(_ terminal: TerminalInstance) { + guard terminal.isReady else { return } + terminal.executeScript("fitAddon.fit()") + } + var body: some View { - ZStack { - _TerminalView(implementation: App.terminalInstance) - .onTapGesture { - let notification = Notification( - name: Notification.Name("terminal.focus"), - userInfo: ["sceneIdentifier": App.sceneIdentifier] - ) - NotificationCenter.default.post(notification) + HStack(spacing: 0) { + ZStack { + ForEach(App.terminalManager.terminals) { terminal in + let isActive = terminal.id == App.terminalManager.activeTerminalId + _TerminalView(terminal: terminal) + .opacity(isActive ? 1 : 0) + .allowsHitTesting(isActive) + .accessibilityHidden(!isActive) } - .onReceive( - NotificationCenter.default.publisher( - for: Notification.Name("editor.focus"), - object: nil), - perform: { notification in - App.terminalInstance.blur() - } - ) - .onReceive( - NotificationCenter.default.publisher( - for: Notification.Name("terminal.focus"), - object: nil), - perform: { notification in - guard - let sceneIdentifier = notification.userInfo?["sceneIdentifier"] - as? UUID, - sceneIdentifier != App.sceneIdentifier - else { return } - App.terminalInstance.blur() - } + } + .contentShape(Rectangle()) + .onTapGesture { + let notification = Notification( + name: Notification.Name("terminal.focus"), + userInfo: ["sceneIdentifier": App.sceneIdentifier] ) - .onAppear(perform: { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - App.terminalInstance.executeScript("fitAddon.fit()") - } - }) + NotificationCenter.default.post(notification) + } + .onReceive( + NotificationCenter.default.publisher( + for: Notification.Name("editor.focus"), + object: nil), + perform: { _ in + App.terminalManager.activeTerminal?.blur() + } + ) + .onReceive( + NotificationCenter.default.publisher( + for: Notification.Name("terminal.focus"), + object: nil), + perform: { notification in + guard + let sceneIdentifier = notification.userInfo?["sceneIdentifier"] as? UUID, + sceneIdentifier != App.sceneIdentifier + else { return } + App.terminalManager.activeTerminal?.blur() + } + ) + .onAppear(perform: { + guard let terminal = App.terminalManager.activeTerminal else { return } + fitTerminalIfReady(terminal) + }) + .onChange(of: App.terminalManager.activeTerminalId) { _ in + guard let terminal = App.terminalManager.activeTerminal else { + return + } + fitTerminalIfReady(terminal) + } + .onReceive( + NotificationCenter.default.publisher(for: .terminalDidInitialize), + perform: { notification in + guard + let terminal = notification.object as? TerminalInstance, + terminal.id == App.terminalManager.activeTerminalId + else { return } + fitTerminalIfReady(terminal) + } + ) + + // Tab bar on the right (only show if more than one terminal) + if App.terminalManager.terminals.count > 1 { + TerminalTabBar() + .transition(.move(edge: .trailing).combined(with: .opacity)) + } } + .animation(.easeInOut(duration: 0.2), value: App.terminalManager.terminals.count > 1) .foregroundColor(.clear) } } From 1d1df5dca5bfd05b833f695eff8bdfac8feb2182 Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Mon, 19 Jan 2026 03:16:32 -0600 Subject: [PATCH 09/33] Reformat long lines for readability in terminal code Refactored several long lines in MainApp.swift, TerminalManager.swift, and TerminalTabBar.swift to improve readability and maintain consistent code style. No functional changes were made. --- CodeApp/Managers/MainApp.swift | 6 +++-- CodeApp/Managers/TerminalManager.swift | 37 ++++++++++++++++++-------- CodeApp/Views/TerminalTabBar.swift | 15 ++++++++--- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/CodeApp/Managers/MainApp.swift b/CodeApp/Managers/MainApp.swift index 575378796..867cdb201 100644 --- a/CodeApp/Managers/MainApp.swift +++ b/CodeApp/Managers/MainApp.swift @@ -7,11 +7,11 @@ import Combine import CoreSpotlight -import os.log import SwiftGit2 import SwiftUI import UniformTypeIdentifiers import ios_system +import os.log private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Code", category: "MainApp") @@ -268,7 +268,9 @@ class MainApp: ObservableObject { if let terminal = self.terminalManager.remoteTerminal { terminal.write(data: data) } else { - logger.warning("Remote terminal data dropped: no remote terminal available (\(data.count) bytes)") + logger.warning( + "Remote terminal data dropped: no remote terminal available (\(data.count) bytes)" + ) } } loadRepository(url: rootDir) diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 2f8fc289b..c2553dcbe 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -8,7 +8,8 @@ import SwiftUI import os.log -private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "Code", category: "TerminalManager") +private let logger = Logger( + subsystem: Bundle.main.bundleIdentifier ?? "Code", category: "TerminalManager") /// Manages multiple terminal instances. /// - Important: Access this class only from the main thread. Debug builds will assert this. @@ -35,8 +36,9 @@ class TerminalManager: ObservableObject { /// Useful during initialization when @AppStorage properties aren't yet accessible. static func readTerminalOptionsFromDefaults() -> TerminalOptions { if let rawValue = UserDefaults.standard.string(forKey: "terminalOptions"), - let data = rawValue.data(using: .utf8), - let decoded = try? JSONDecoder().decode(TerminalOptions.self, from: data) { + let data = rawValue.data(using: .utf8), + let decoded = try? JSONDecoder().decode(TerminalOptions.self, from: data) + { return decoded } return TerminalOptions() @@ -128,7 +130,8 @@ class TerminalManager: ObservableObject { while existingNames.contains(candidateName) && suffix < maxAttempts { suffix += 1 candidateName = String( - format: NSLocalizedString("%@ (%d)", comment: "Terminal name with duplicate suffix"), + format: NSLocalizedString( + "%@ (%d)", comment: "Terminal name with duplicate suffix"), baseName, suffix ) } @@ -151,10 +154,13 @@ class TerminalManager: ObservableObject { func createTerminal(name: String? = nil) -> TerminalInstance { assertMainThread() guard terminals.count < TerminalManager.maxTerminals else { - logger.debug("create blocked: max reached (count: \(self.terminals.count, privacy: .public), max: \(TerminalManager.maxTerminals, privacy: .public))") + logger.debug( + "create blocked: max reached (count: \(self.terminals.count, privacy: .public), max: \(TerminalManager.maxTerminals, privacy: .public))" + ) // Return the active terminal if at max capacity // Invariant: terminals array is never empty after init (enforced by closeTerminal guard) - precondition(!terminals.isEmpty, "TerminalManager must always have at least one terminal") + precondition( + !terminals.isEmpty, "TerminalManager must always have at least one terminal") return activeTerminal ?? terminals.first! } @@ -162,7 +168,9 @@ class TerminalManager: ObservableObject { let terminal = createTerminalInstance(name: terminalName) terminals.append(terminal) setActiveTerminalId(terminal.id) - logger.info("created terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + logger.info( + "created terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)" + ) return terminal } @@ -170,7 +178,9 @@ class TerminalManager: ObservableObject { assertMainThread() // Don't allow closing the last terminal guard terminals.count > 1 else { - logger.debug("close blocked: last terminal (count: \(self.terminals.count, privacy: .public)) id: \(id, privacy: .public)") + logger.debug( + "close blocked: last terminal (count: \(self.terminals.count, privacy: .public)) id: \(id, privacy: .public)" + ) return } @@ -193,7 +203,9 @@ class TerminalManager: ObservableObject { terminals.remove(at: index) syncRemoteTerminalId() - logger.info("closed terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + logger.info( + "closed terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)" + ) } /// Check if a terminal has a running process @@ -209,7 +221,9 @@ class TerminalManager: ObservableObject { return } setActiveTerminalId(terminal.id) - logger.info("switched terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)") + logger.info( + "switched terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)" + ) } func renameTerminal(id: UUID, name: String) { @@ -286,7 +300,8 @@ class TerminalManager: ObservableObject { } if let currentId = remoteTerminalId, - terminals.contains(where: { $0.id == currentId && $0.terminalServiceProvider != nil }) { + terminals.contains(where: { $0.id == currentId && $0.terminalServiceProvider != nil }) + { return } diff --git a/CodeApp/Views/TerminalTabBar.swift b/CodeApp/Views/TerminalTabBar.swift index 998c8b6d9..118e462cb 100644 --- a/CodeApp/Views/TerminalTabBar.swift +++ b/CodeApp/Views/TerminalTabBar.swift @@ -83,7 +83,9 @@ struct TerminalTabRow: View { // Icon Image(systemName: "terminal") .font(.system(size: TerminalTabBarConstants.iconSize)) - .foregroundColor(isActive ? Color(id: "list.activeSelectionForeground") : Color(id: "foreground")) + .foregroundColor( + isActive ? Color(id: "list.activeSelectionForeground") : Color(id: "foreground") + ) .frame(width: 20, height: 20) Spacer() } @@ -106,7 +108,11 @@ struct TerminalTabRow: View { .accessibilityElement(children: .ignore) .accessibilityLabel(accessibilityLabel) .accessibilityAddTraits(isActive ? [.isSelected, .isButton] : [.isButton]) - .accessibilityHint(NSLocalizedString("Double tap to switch to this terminal", comment: "Accessibility hint for terminal tab")) + .accessibilityHint( + NSLocalizedString( + "Double tap to switch to this terminal", + comment: "Accessibility hint for terminal tab") + ) .contextMenu { if canClose { Button(NSLocalizedString("Kill Terminal", comment: ""), role: .destructive) { @@ -127,7 +133,10 @@ struct TerminalTabRow: View { onClose() } } message: { - Text(NSLocalizedString("This terminal has a running process. Are you sure you want to kill it?", comment: "")) + Text( + NSLocalizedString( + "This terminal has a running process. Are you sure you want to kill it?", + comment: "")) } } } From 3c7f54f9d0785f8d448e10c59eab310ad047157d Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Sun, 25 Jan 2026 14:27:44 -0600 Subject: [PATCH 10/33] Remove Python venv scripts and update lock files Deleted Python virtual environment scripts and related files from LanguageResources/Library/lib/python3.9/venv. Updated npm package-lock files, removing several dependencies, likely as a result of cleaning up unused or deprecated packages. --- .../node_modules/.package-lock.json | 431 ---------- Dependencies/npm.bundle/package-lock.json | 764 ------------------ .../Library/lib/python3.9/venv/__init__.py | 499 ------------ .../Library/lib/python3.9/venv/__main__.py | 10 - .../venv/scripts/common/Activate.ps1 | 241 ------ .../python3.9/venv/scripts/common/activate | 66 -- .../python3.9/venv/scripts/posix/activate.csh | 25 - .../venv/scripts/posix/activate.fish | 64 -- 8 files changed, 2100 deletions(-) delete mode 100644 LanguageResources/Library/lib/python3.9/venv/__init__.py delete mode 100644 LanguageResources/Library/lib/python3.9/venv/__main__.py delete mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 delete mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/common/activate delete mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh delete mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish diff --git a/Dependencies/npm.bundle/node_modules/.package-lock.json b/Dependencies/npm.bundle/node_modules/.package-lock.json index 4ff98aa84..87f92d0ac 100644 --- a/Dependencies/npm.bundle/node_modules/.package-lock.json +++ b/Dependencies/npm.bundle/node_modules/.package-lock.json @@ -438,27 +438,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/ajv": { - "version": "6.12.6", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", "inBundle": true, @@ -510,47 +489,11 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/asn1": { - "version": "0.2.4", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/npm/node_modules/assert-plus": { - "version": "1.0.0", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/asynckit": { - "version": "0.4.0", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/npm/node_modules/aws-sign2": { - "version": "0.7.0", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/aws4": { - "version": "1.11.0", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/npm/node_modules/bin-links": { "version": "3.0.0", "inBundle": true, @@ -617,10 +560,6 @@ "node": ">= 10" } }, - "node_modules/npm/node_modules/caseless": { - "version": "0.12.0", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/npm/node_modules/chalk": { "version": "4.1.2", "inBundle": true, @@ -708,21 +647,9 @@ "colors": "1.4.0" } }, - "node_modules/npm/node_modules/cli-table3/node_modules/ansi-regex": { - "extraneous": true, - "inBundle": true - }, - "node_modules/npm/node_modules/cli-table3/node_modules/is-fullwidth-code-point": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/cli-table3/node_modules/string-width": { "inBundle": true }, - "node_modules/npm/node_modules/cli-table3/node_modules/strip-ansi": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/clone": { "version": "1.0.4", "inBundle": true, @@ -742,13 +669,6 @@ "node": ">=10" } }, - "node_modules/npm/node_modules/code-point-at": { - "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", "inBundle": true, @@ -813,16 +733,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/combined-stream": { - "version": "1.0.8", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", "inBundle": true, @@ -838,20 +748,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/core-util-is": { - "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/npm/node_modules/dashdash": { - "version": "1.14.1", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/npm/node_modules/debug": { "version": "4.3.3", "inBundle": true, @@ -889,13 +785,6 @@ "clone": "^1.0.2" } }, - "node_modules/npm/node_modules/delayed-stream": { - "version": "1.0.0", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/npm/node_modules/delegates": { "version": "1.0.0", "inBundle": true, @@ -926,14 +815,6 @@ "node": ">=0.3.1" } }, - "node_modules/npm/node_modules/ecc-jsbn": { - "version": "0.1.2", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", "inBundle": true, @@ -961,49 +842,11 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/extend": { - "version": "3.0.2", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/npm/node_modules/extsprintf": { - "version": "1.3.0", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/npm/node_modules/fast-deep-equal": { - "version": "3.1.3", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/npm/node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.12", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/forever-agent": { - "version": "0.6.1", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/form-data": { - "version": "2.3.3", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/npm/node_modules/fs-minipass": { "version": "2.1.0", "inBundle": true, @@ -1055,10 +898,6 @@ "node_modules/npm/node_modules/gauge/node_modules/aproba": { "inBundle": true }, - "node_modules/npm/node_modules/gauge/node_modules/is-fullwidth-code-point": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/gauge/node_modules/string-width": { "inBundle": true }, @@ -1073,13 +912,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/getpass": { - "version": "0.1.7", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/npm/node_modules/glob": { "version": "7.2.0", "inBundle": true, @@ -1104,25 +936,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/har-schema": { - "version": "2.0.0", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/har-validator": { - "version": "5.1.5", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/npm/node_modules/has": { "version": "1.0.3", "inBundle": true, @@ -1176,19 +989,6 @@ "node": ">= 6" } }, - "node_modules/npm/node_modules/http-signature": { - "version": "1.2.0", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "5.0.0", "inBundle": true, @@ -1345,36 +1145,16 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/isarray": { - "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/isstream": { - "version": "0.1.2", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/npm/node_modules/jsbn": { - "version": "0.1.1", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/json-schema": { - "version": "0.2.3", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/npm/node_modules/json-schema-traverse": { - "version": "0.4.1", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", "inBundle": true, @@ -1383,10 +1163,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm/node_modules/json-stringify-safe": { - "version": "5.0.1", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", "engines": [ @@ -1395,19 +1171,6 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/jsprim": { - "version": "1.4.1", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "node_modules/npm/node_modules/just-diff": { "version": "5.0.1", "inBundle": true, @@ -1619,23 +1382,6 @@ "node": ">=12" } }, - "node_modules/npm/node_modules/mime-db": { - "version": "1.47.0", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/mime-types": { - "version": "2.1.30", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", - "dependencies": { - "mime-db": "1.47.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/npm/node_modules/minimatch": { "version": "3.0.4", "inBundle": true, @@ -2006,27 +1752,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/npm/node_modules/number-is-nan": { - "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/oauth-sign": { - "version": "0.9.0", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/object-assign": { - "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/once": { "version": "1.4.0", "inBundle": true, @@ -2112,14 +1837,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/path-parse": { - "version": "1.0.6", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "node_modules/npm/node_modules/performance-now": { - "version": "2.1.0", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/npm/node_modules/proc-log": { "version": "2.0.0", "inBundle": true, @@ -2128,10 +1845,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/npm/node_modules/process-nextick-args": { - "version": "2.0.1", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", "inBundle": true, @@ -2173,17 +1886,6 @@ "read": "1" } }, - "node_modules/npm/node_modules/psl": { - "version": "1.8.0", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/npm/node_modules/punycode": { - "version": "2.1.1", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", "inBundle": true, @@ -2191,13 +1893,6 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, - "node_modules/npm/node_modules/qs": { - "version": "6.5.2", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/npm/node_modules/read": { "version": "1.0.7", "inBundle": true, @@ -2264,58 +1959,6 @@ "once": "^1.3.0" } }, - "node_modules/npm/node_modules/request": { - "version": "2.88.2", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/resolve": { - "version": "1.20.0", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, @@ -2450,29 +2093,6 @@ "inBundle": true, "license": "CC0-1.0" }, - "node_modules/npm/node_modules/sshpk": { - "version": "1.16.1", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/ssri": { "version": "8.0.1", "inBundle": true, @@ -2529,16 +2149,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -2581,20 +2191,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/tunnel-agent": { - "version": "0.6.0", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/tweetnacl": { - "version": "0.14.5", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/npm/node_modules/typedarray-to-buffer": { "version": "4.0.0", "funding": [ @@ -2630,26 +2226,11 @@ "imurmurhash": "^0.1.4" } }, - "node_modules/npm/node_modules/uri-js": { - "version": "4.4.1", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/uuid": { - "version": "3.4.0", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", "inBundle": true, @@ -2667,18 +2248,6 @@ "builtins": "^1.0.3" } }, - "node_modules/npm/node_modules/verror": { - "version": "1.10.0", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/npm/node_modules/walk-up-path": { "version": "1.0.0", "inBundle": true, diff --git a/Dependencies/npm.bundle/package-lock.json b/Dependencies/npm.bundle/package-lock.json index c0966654e..7795449e6 100644 --- a/Dependencies/npm.bundle/package-lock.json +++ b/Dependencies/npm.bundle/package-lock.json @@ -443,27 +443,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/ajv": { - "version": "6.12.6", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", "inBundle": true, @@ -515,47 +494,11 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/asn1": { - "version": "0.2.4", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/npm/node_modules/assert-plus": { - "version": "1.0.0", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/asynckit": { - "version": "0.4.0", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/npm/node_modules/aws-sign2": { - "version": "0.7.0", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/aws4": { - "version": "1.11.0", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/npm/node_modules/bin-links": { "version": "3.0.0", "inBundle": true, @@ -622,10 +565,6 @@ "node": ">= 10" } }, - "node_modules/npm/node_modules/caseless": { - "version": "0.12.0", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/npm/node_modules/chalk": { "version": "4.1.2", "inBundle": true, @@ -713,21 +652,9 @@ "colors": "1.4.0" } }, - "node_modules/npm/node_modules/cli-table3/node_modules/ansi-regex": { - "extraneous": true, - "inBundle": true - }, - "node_modules/npm/node_modules/cli-table3/node_modules/is-fullwidth-code-point": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/cli-table3/node_modules/string-width": { "inBundle": true }, - "node_modules/npm/node_modules/cli-table3/node_modules/strip-ansi": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/clone": { "version": "1.0.4", "inBundle": true, @@ -747,13 +674,6 @@ "node": ">=10" } }, - "node_modules/npm/node_modules/code-point-at": { - "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", "inBundle": true, @@ -818,16 +738,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/combined-stream": { - "version": "1.0.8", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", "inBundle": true, @@ -843,20 +753,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/core-util-is": { - "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/npm/node_modules/dashdash": { - "version": "1.14.1", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/npm/node_modules/debug": { "version": "4.3.3", "inBundle": true, @@ -894,13 +790,6 @@ "clone": "^1.0.2" } }, - "node_modules/npm/node_modules/delayed-stream": { - "version": "1.0.0", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/npm/node_modules/delegates": { "version": "1.0.0", "inBundle": true, @@ -931,14 +820,6 @@ "node": ">=0.3.1" } }, - "node_modules/npm/node_modules/ecc-jsbn": { - "version": "0.1.2", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", "inBundle": true, @@ -966,49 +847,11 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/extend": { - "version": "3.0.2", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/npm/node_modules/extsprintf": { - "version": "1.3.0", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/npm/node_modules/fast-deep-equal": { - "version": "3.1.3", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/npm/node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.12", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/forever-agent": { - "version": "0.6.1", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/form-data": { - "version": "2.3.3", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/npm/node_modules/fs-minipass": { "version": "2.1.0", "inBundle": true, @@ -1060,10 +903,6 @@ "node_modules/npm/node_modules/gauge/node_modules/aproba": { "inBundle": true }, - "node_modules/npm/node_modules/gauge/node_modules/is-fullwidth-code-point": { - "extraneous": true, - "inBundle": true - }, "node_modules/npm/node_modules/gauge/node_modules/string-width": { "inBundle": true }, @@ -1078,13 +917,6 @@ "node": ">=8" } }, - "node_modules/npm/node_modules/getpass": { - "version": "0.1.7", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/npm/node_modules/glob": { "version": "7.2.0", "inBundle": true, @@ -1109,25 +941,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/har-schema": { - "version": "2.0.0", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/har-validator": { - "version": "5.1.5", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/npm/node_modules/has": { "version": "1.0.3", "inBundle": true, @@ -1181,19 +994,6 @@ "node": ">= 6" } }, - "node_modules/npm/node_modules/http-signature": { - "version": "1.2.0", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "5.0.0", "inBundle": true, @@ -1350,36 +1150,16 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/isarray": { - "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/isstream": { - "version": "0.1.2", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/npm/node_modules/jsbn": { - "version": "0.1.1", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/json-schema": { - "version": "0.2.3", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/npm/node_modules/json-schema-traverse": { - "version": "0.4.1", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", "inBundle": true, @@ -1388,10 +1168,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm/node_modules/json-stringify-safe": { - "version": "5.0.1", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", "engines": [ @@ -1400,19 +1176,6 @@ "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/jsprim": { - "version": "1.4.1", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "node_modules/npm/node_modules/just-diff": { "version": "5.0.1", "inBundle": true, @@ -1624,23 +1387,6 @@ "node": ">=12" } }, - "node_modules/npm/node_modules/mime-db": { - "version": "1.47.0", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/mime-types": { - "version": "2.1.30", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", - "dependencies": { - "mime-db": "1.47.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/npm/node_modules/minimatch": { "version": "3.0.4", "inBundle": true, @@ -2011,27 +1757,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/npm/node_modules/number-is-nan": { - "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/oauth-sign": { - "version": "0.9.0", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/object-assign": { - "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/once": { "version": "1.4.0", "inBundle": true, @@ -2117,14 +1842,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/path-parse": { - "version": "1.0.6", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "node_modules/npm/node_modules/performance-now": { - "version": "2.1.0", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/npm/node_modules/proc-log": { "version": "2.0.0", "inBundle": true, @@ -2133,10 +1850,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/npm/node_modules/process-nextick-args": { - "version": "2.0.1", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", "inBundle": true, @@ -2178,17 +1891,6 @@ "read": "1" } }, - "node_modules/npm/node_modules/psl": { - "version": "1.8.0", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/npm/node_modules/punycode": { - "version": "2.1.1", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", "inBundle": true, @@ -2196,13 +1898,6 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, - "node_modules/npm/node_modules/qs": { - "version": "6.5.2", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/npm/node_modules/read": { "version": "1.0.7", "inBundle": true, @@ -2269,58 +1964,6 @@ "once": "^1.3.0" } }, - "node_modules/npm/node_modules/request": { - "version": "2.88.2", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/npm/node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/npm/node_modules/resolve": { - "version": "1.20.0", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, @@ -2455,29 +2098,6 @@ "inBundle": true, "license": "CC0-1.0" }, - "node_modules/npm/node_modules/sshpk": { - "version": "1.16.1", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/ssri": { "version": "8.0.1", "inBundle": true, @@ -2534,16 +2154,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -2586,20 +2196,6 @@ "inBundle": true, "license": "ISC" }, - "node_modules/npm/node_modules/tunnel-agent": { - "version": "0.6.0", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/npm/node_modules/tweetnacl": { - "version": "0.14.5", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/npm/node_modules/typedarray-to-buffer": { "version": "4.0.0", "funding": [ @@ -2635,26 +2231,11 @@ "imurmurhash": "^0.1.4" } }, - "node_modules/npm/node_modules/uri-js": { - "version": "4.4.1", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, - "node_modules/npm/node_modules/uuid": { - "version": "3.4.0", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", "inBundle": true, @@ -2672,18 +2253,6 @@ "builtins": "^1.0.3" } }, - "node_modules/npm/node_modules/verror": { - "version": "1.10.0", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/npm/node_modules/walk-up-path": { "version": "1.0.0", "inBundle": true, @@ -3025,20 +2594,6 @@ "indent-string": "^4.0.0" } }, - "ajv": { - "version": "6.12.6", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "2.1.1", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, "ansi-styles": { "version": "4.3.0", "bundled": true, @@ -3074,40 +2629,10 @@ "version": "2.0.6", "bundled": true }, - "asn1": { - "version": "0.2.4", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "0.4.0", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "balanced-match": { "version": "1.0.2", "bundled": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "bin-links": { "version": "3.0.0", "bundled": true, @@ -3160,10 +2685,6 @@ "unique-filename": "^1.1.1" } }, - "caseless": { - "version": "0.12.0", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "4.1.2", "bundled": true, @@ -3216,20 +2737,8 @@ "string-width": "^4.2.0" }, "dependencies": { - "ansi-regex": { - "bundled": true, - "extraneous": true - }, - "is-fullwidth-code-point": { - "bundled": true, - "extraneous": true - }, "string-width": { "bundled": true - }, - "strip-ansi": { - "bundled": true, - "extraneous": true } } }, @@ -3244,10 +2753,6 @@ "mkdirp-infer-owner": "^2.0.0" } }, - "code-point-at": { - "version": "1.1.0", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, "color-convert": { "version": "2.0.1", "bundled": true, @@ -3289,13 +2794,6 @@ } } }, - "combined-stream": { - "version": "1.0.8", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "common-ancestor-path": { "version": "1.0.1", "bundled": true @@ -3308,17 +2806,6 @@ "version": "1.1.0", "bundled": true }, - "core-util-is": { - "version": "1.0.2", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "dashdash": { - "version": "1.14.1", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "4.3.3", "bundled": true, @@ -3343,10 +2830,6 @@ "clone": "^1.0.2" } }, - "delayed-stream": { - "version": "1.0.0", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, "delegates": { "version": "1.0.0", "bundled": true @@ -3367,14 +2850,6 @@ "version": "5.0.0", "bundled": true }, - "ecc-jsbn": { - "version": "0.1.2", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "emoji-regex": { "version": "8.0.0", "bundled": true @@ -3395,39 +2870,10 @@ "version": "2.0.3", "bundled": true }, - "extend": { - "version": "3.0.2", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "fastest-levenshtein": { "version": "1.0.12", "bundled": true }, - "forever-agent": { - "version": "0.6.1", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fs-minipass": { "version": "2.1.0", "bundled": true, @@ -3465,10 +2911,6 @@ "aproba": { "bundled": true }, - "is-fullwidth-code-point": { - "bundled": true, - "extraneous": true - }, "string-width": { "bundled": true }, @@ -3481,13 +2923,6 @@ } } }, - "getpass": { - "version": "0.1.7", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.2.0", "bundled": true, @@ -3504,18 +2939,6 @@ "version": "4.2.9", "bundled": true }, - "har-schema": { - "version": "2.0.0", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "bundled": true, @@ -3551,15 +2974,6 @@ "debug": "4" } }, - "http-signature": { - "version": "1.2.0", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-proxy-agent": { "version": "5.0.0", "bundled": true, @@ -3665,56 +3079,22 @@ "version": "1.0.0", "bundled": true }, - "isarray": { - "version": "1.0.0", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "isexe": { "version": "2.0.0", "bundled": true }, - "isstream": { - "version": "0.1.2", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "json-parse-even-better-errors": { "version": "2.3.1", "bundled": true }, - "json-schema": { - "version": "0.2.3", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, "json-stringify-nice": { "version": "1.1.4", "bundled": true }, - "json-stringify-safe": { - "version": "5.0.1", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "jsonparse": { "version": "1.3.1", "bundled": true }, - "jsprim": { - "version": "1.4.1", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "just-diff": { "version": "5.0.1", "bundled": true @@ -3870,17 +3250,6 @@ } } }, - "mime-db": { - "version": "1.47.0", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" - }, - "mime-types": { - "version": "2.1.30", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", - "requires": { - "mime-db": "1.47.0" - } - }, "minimatch": { "version": "3.0.4", "bundled": true, @@ -4133,18 +3502,6 @@ "set-blocking": "^2.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "oauth-sign": { - "version": "0.9.0", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, "once": { "version": "1.4.0", "bundled": true, @@ -4203,22 +3560,10 @@ "version": "1.0.1", "bundled": true }, - "path-parse": { - "version": "1.0.6", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "performance-now": { - "version": "2.1.0", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "proc-log": { "version": "2.0.0", "bundled": true }, - "process-nextick-args": { - "version": "2.0.1", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "promise-all-reject-late": { "version": "1.0.1", "bundled": true @@ -4246,22 +3591,10 @@ "read": "1" } }, - "psl": { - "version": "1.8.0", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "punycode": { - "version": "2.1.1", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, "qrcode-terminal": { "version": "0.12.0", "bundled": true }, - "qs": { - "version": "6.5.2", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, "read": { "version": "1.0.7", "bundled": true, @@ -4310,50 +3643,6 @@ "once": "^1.3.0" } }, - "request": { - "version": "2.88.2", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } - } - }, - "resolve": { - "version": "1.20.0", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } - }, "retry": { "version": "0.12.0", "bundled": true @@ -4434,21 +3723,6 @@ "version": "3.0.11", "bundled": true }, - "sshpk": { - "version": "1.16.1", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "8.0.1", "bundled": true, @@ -4489,13 +3763,6 @@ "version": "1.0.1", "bundled": true }, - "strip-ansi": { - "version": "3.0.1", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "7.2.0", "bundled": true, @@ -4527,17 +3794,6 @@ "version": "1.0.4", "bundled": true }, - "tunnel-agent": { - "version": "0.6.0", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "typedarray-to-buffer": { "version": "4.0.0", "bundled": true @@ -4556,21 +3812,10 @@ "imurmurhash": "^0.1.4" } }, - "uri-js": { - "version": "4.4.1", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, "util-deprecate": { "version": "1.0.2", "bundled": true }, - "uuid": { - "version": "3.4.0", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, "validate-npm-package-license": { "version": "3.0.4", "bundled": true, @@ -4586,15 +3831,6 @@ "builtins": "^1.0.3" } }, - "verror": { - "version": "1.10.0", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "walk-up-path": { "version": "1.0.0", "bundled": true diff --git a/LanguageResources/Library/lib/python3.9/venv/__init__.py b/LanguageResources/Library/lib/python3.9/venv/__init__.py deleted file mode 100644 index 8009deb3e..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/__init__.py +++ /dev/null @@ -1,499 +0,0 @@ -""" -Virtual environment (venv) package for Python. Based on PEP 405. - -Copyright (C) 2011-2014 Vinay Sajip. -Licensed to the PSF under a contributor agreement. -""" -import logging -import os -import shutil -import subprocess -import sys -import sysconfig -import types - - -CORE_VENV_DEPS = ('pip', 'setuptools') -logger = logging.getLogger(__name__) - - -class EnvBuilder: - """ - This class exists to allow virtual environment creation to be - customized. The constructor parameters determine the builder's - behaviour when called upon to create a virtual environment. - - By default, the builder makes the system (global) site-packages dir - *un*available to the created environment. - - If invoked using the Python -m option, the default is to use copying - on Windows platforms but symlinks elsewhere. If instantiated some - other way, the default is to *not* use symlinks. - - :param system_site_packages: If True, the system (global) site-packages - dir is available to created environments. - :param clear: If True, delete the contents of the environment directory if - it already exists, before environment creation. - :param symlinks: If True, attempt to symlink rather than copy files into - virtual environment. - :param upgrade: If True, upgrade an existing virtual environment. - :param with_pip: If True, ensure pip is installed in the virtual - environment - :param prompt: Alternative terminal prefix for the environment. - :param upgrade_deps: Update the base venv modules to the latest on PyPI - """ - - def __init__(self, system_site_packages=False, clear=False, - symlinks=False, upgrade=False, with_pip=False, prompt=None, - upgrade_deps=False): - self.system_site_packages = system_site_packages - self.clear = clear - self.symlinks = symlinks - self.upgrade = upgrade - self.with_pip = with_pip - if prompt == '.': # see bpo-38901 - prompt = os.path.basename(os.getcwd()) - self.prompt = prompt - self.upgrade_deps = upgrade_deps - - def create(self, env_dir): - """ - Create a virtual environment in a directory. - - :param env_dir: The target directory to create an environment in. - - """ - env_dir = os.path.abspath(env_dir) - context = self.ensure_directories(env_dir) - # See issue 24875. We need system_site_packages to be False - # until after pip is installed. - true_system_site_packages = self.system_site_packages - self.system_site_packages = False - self.create_configuration(context) - self.setup_python(context) - if self.with_pip: - self._setup_pip(context) - if not self.upgrade: - self.setup_scripts(context) - self.post_setup(context) - if true_system_site_packages: - # We had set it to False before, now - # restore it and rewrite the configuration - self.system_site_packages = True - self.create_configuration(context) - if self.upgrade_deps: - self.upgrade_dependencies(context) - - def clear_directory(self, path): - for fn in os.listdir(path): - fn = os.path.join(path, fn) - if os.path.islink(fn) or os.path.isfile(fn): - os.remove(fn) - elif os.path.isdir(fn): - shutil.rmtree(fn) - - def ensure_directories(self, env_dir): - """ - Create the directories for the environment. - - Returns a context object which holds paths in the environment, - for use by subsequent logic. - """ - - def create_if_needed(d): - if not os.path.exists(d): - os.makedirs(d) - elif os.path.islink(d) or os.path.isfile(d): - raise ValueError('Unable to create directory %r' % d) - - if os.path.exists(env_dir) and self.clear: - self.clear_directory(env_dir) - context = types.SimpleNamespace() - context.env_dir = env_dir - context.env_name = os.path.split(env_dir)[1] - prompt = self.prompt if self.prompt is not None else context.env_name - context.prompt = '(%s) ' % prompt - create_if_needed(env_dir) - executable = sys._base_executable - dirname, exename = os.path.split(os.path.abspath(executable)) - context.executable = executable - context.python_dir = dirname - context.python_exe = exename - if sys.platform == 'win32': - binname = 'Scripts' - incpath = 'Include' - libpath = os.path.join(env_dir, 'Lib', 'site-packages') - else: - binname = 'bin' - incpath = 'include' - libpath = os.path.join(env_dir, 'lib', - 'python%d.%d' % sys.version_info[:2], - 'site-packages') - context.inc_path = path = os.path.join(env_dir, incpath) - create_if_needed(path) - create_if_needed(libpath) - # Issue 21197: create lib64 as a symlink to lib on 64-bit non-OS X POSIX - if ((sys.maxsize > 2**32) and (os.name == 'posix') and - (sys.platform != 'darwin')): - link_path = os.path.join(env_dir, 'lib64') - if not os.path.exists(link_path): # Issue #21643 - os.symlink('lib', link_path) - context.bin_path = binpath = os.path.join(env_dir, binname) - context.bin_name = binname - context.env_exe = os.path.join(binpath, exename) - create_if_needed(binpath) - return context - - def create_configuration(self, context): - """ - Create a configuration file indicating where the environment's Python - was copied from, and whether the system site-packages should be made - available in the environment. - - :param context: The information for the environment creation request - being processed. - """ - context.cfg_path = path = os.path.join(context.env_dir, 'pyvenv.cfg') - with open(path, 'w', encoding='utf-8') as f: - f.write('home = %s\n' % context.python_dir) - if self.system_site_packages: - incl = 'true' - else: - incl = 'false' - f.write('include-system-site-packages = %s\n' % incl) - f.write('version = %d.%d.%d\n' % sys.version_info[:3]) - if self.prompt is not None: - f.write(f'prompt = {self.prompt!r}\n') - - if os.name != 'nt': - def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): - """ - Try symlinking a file, and if that fails, fall back to copying. - """ - force_copy = not self.symlinks - if not force_copy: - try: - if not os.path.islink(dst): # can't link to itself! - if relative_symlinks_ok: - assert os.path.dirname(src) == os.path.dirname(dst) - os.symlink(os.path.basename(src), dst) - else: - os.symlink(src, dst) - except Exception: # may need to use a more specific exception - logger.warning('Unable to symlink %r to %r', src, dst) - force_copy = True - if force_copy: - shutil.copyfile(src, dst) - else: - def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): - """ - Try symlinking a file, and if that fails, fall back to copying. - """ - bad_src = os.path.lexists(src) and not os.path.exists(src) - if self.symlinks and not bad_src and not os.path.islink(dst): - try: - if relative_symlinks_ok: - assert os.path.dirname(src) == os.path.dirname(dst) - os.symlink(os.path.basename(src), dst) - else: - os.symlink(src, dst) - return - except Exception: # may need to use a more specific exception - logger.warning('Unable to symlink %r to %r', src, dst) - - # On Windows, we rewrite symlinks to our base python.exe into - # copies of venvlauncher.exe - basename, ext = os.path.splitext(os.path.basename(src)) - srcfn = os.path.join(os.path.dirname(__file__), - "scripts", - "nt", - basename + ext) - # Builds or venv's from builds need to remap source file - # locations, as we do not put them into Lib/venv/scripts - if sysconfig.is_python_build(True) or not os.path.isfile(srcfn): - if basename.endswith('_d'): - ext = '_d' + ext - basename = basename[:-2] - if basename == 'python': - basename = 'venvlauncher' - elif basename == 'pythonw': - basename = 'venvwlauncher' - src = os.path.join(os.path.dirname(src), basename + ext) - else: - src = srcfn - if not os.path.exists(src): - if not bad_src: - logger.warning('Unable to copy %r', src) - return - - shutil.copyfile(src, dst) - - def setup_python(self, context): - """ - Set up a Python executable in the environment. - - :param context: The information for the environment creation request - being processed. - """ - binpath = context.bin_path - path = context.env_exe - copier = self.symlink_or_copy - dirname = context.python_dir - if os.name != 'nt': - copier(context.executable, path) - if not os.path.islink(path): - os.chmod(path, 0o755) - for suffix in ('python', 'python3', f'python3.{sys.version_info[1]}'): - path = os.path.join(binpath, suffix) - if not os.path.exists(path): - # Issue 18807: make copies if - # symlinks are not wanted - copier(context.env_exe, path, relative_symlinks_ok=True) - if not os.path.islink(path): - os.chmod(path, 0o755) - else: - if self.symlinks: - # For symlinking, we need a complete copy of the root directory - # If symlinks fail, you'll get unnecessary copies of files, but - # we assume that if you've opted into symlinks on Windows then - # you know what you're doing. - suffixes = [ - f for f in os.listdir(dirname) if - os.path.normcase(os.path.splitext(f)[1]) in ('.exe', '.dll') - ] - if sysconfig.is_python_build(True): - suffixes = [ - f for f in suffixes if - os.path.normcase(f).startswith(('python', 'vcruntime')) - ] - else: - suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', - 'pythonw_d.exe'] - - for suffix in suffixes: - src = os.path.join(dirname, suffix) - if os.path.lexists(src): - copier(src, os.path.join(binpath, suffix)) - - if sysconfig.is_python_build(True): - # copy init.tcl - for root, dirs, files in os.walk(context.python_dir): - if 'init.tcl' in files: - tcldir = os.path.basename(root) - tcldir = os.path.join(context.env_dir, 'Lib', tcldir) - if not os.path.exists(tcldir): - os.makedirs(tcldir) - src = os.path.join(root, 'init.tcl') - dst = os.path.join(tcldir, 'init.tcl') - shutil.copyfile(src, dst) - break - - def _setup_pip(self, context): - """Installs or upgrades pip in a virtual environment""" - # We run ensurepip in isolated mode to avoid side effects from - # environment vars, the current directory and anything else - # intended for the global Python environment - cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade', - '--default-pip'] - subprocess.check_output(cmd, stderr=subprocess.STDOUT) - - def setup_scripts(self, context): - """ - Set up scripts into the created environment from a directory. - - This method installs the default scripts into the environment - being created. You can prevent the default installation by overriding - this method if you really need to, or if you need to specify - a different location for the scripts to install. By default, the - 'scripts' directory in the venv package is used as the source of - scripts to install. - """ - path = os.path.abspath(os.path.dirname(__file__)) - path = os.path.join(path, 'scripts') - self.install_scripts(context, path) - - def post_setup(self, context): - """ - Hook for post-setup modification of the venv. Subclasses may install - additional packages or scripts here, add activation shell scripts, etc. - - :param context: The information for the environment creation request - being processed. - """ - pass - - def replace_variables(self, text, context): - """ - Replace variable placeholders in script text with context-specific - variables. - - Return the text passed in , but with variables replaced. - - :param text: The text in which to replace placeholder variables. - :param context: The information for the environment creation request - being processed. - """ - text = text.replace('__VENV_DIR__', context.env_dir) - text = text.replace('__VENV_NAME__', context.env_name) - text = text.replace('__VENV_PROMPT__', context.prompt) - text = text.replace('__VENV_BIN_NAME__', context.bin_name) - text = text.replace('__VENV_PYTHON__', context.env_exe) - return text - - def install_scripts(self, context, path): - """ - Install scripts into the created environment from a directory. - - :param context: The information for the environment creation request - being processed. - :param path: Absolute pathname of a directory containing script. - Scripts in the 'common' subdirectory of this directory, - and those in the directory named for the platform - being run on, are installed in the created environment. - Placeholder variables are replaced with environment- - specific values. - """ - binpath = context.bin_path - plen = len(path) - for root, dirs, files in os.walk(path): - if root == path: # at top-level, remove irrelevant dirs - for d in dirs[:]: - if d not in ('common', os.name): - dirs.remove(d) - continue # ignore files in top level - for f in files: - if (os.name == 'nt' and f.startswith('python') - and f.endswith(('.exe', '.pdb'))): - continue - srcfile = os.path.join(root, f) - suffix = root[plen:].split(os.sep)[2:] - if not suffix: - dstdir = binpath - else: - dstdir = os.path.join(binpath, *suffix) - if not os.path.exists(dstdir): - os.makedirs(dstdir) - dstfile = os.path.join(dstdir, f) - with open(srcfile, 'rb') as f: - data = f.read() - if not srcfile.endswith(('.exe', '.pdb')): - try: - data = data.decode('utf-8') - data = self.replace_variables(data, context) - data = data.encode('utf-8') - except UnicodeError as e: - data = None - logger.warning('unable to copy script %r, ' - 'may be binary: %s', srcfile, e) - if data is not None: - with open(dstfile, 'wb') as f: - f.write(data) - shutil.copymode(srcfile, dstfile) - - def upgrade_dependencies(self, context): - logger.debug( - f'Upgrading {CORE_VENV_DEPS} packages in {context.bin_path}' - ) - if sys.platform == 'win32': - python_exe = os.path.join(context.bin_path, 'python.exe') - else: - python_exe = os.path.join(context.bin_path, 'python') - cmd = [python_exe, '-m', 'pip', 'install', '--upgrade'] - cmd.extend(CORE_VENV_DEPS) - subprocess.check_call(cmd) - - -def create(env_dir, system_site_packages=False, clear=False, - symlinks=False, with_pip=False, prompt=None, upgrade_deps=False): - """Create a virtual environment in a directory.""" - builder = EnvBuilder(system_site_packages=system_site_packages, - clear=clear, symlinks=symlinks, with_pip=with_pip, - prompt=prompt, upgrade_deps=upgrade_deps) - builder.create(env_dir) - -def main(args=None): - compatible = True - if sys.version_info < (3, 3): - compatible = False - elif not hasattr(sys, 'base_prefix'): - compatible = False - if not compatible: - raise ValueError('This script is only for use with Python >= 3.3') - else: - import argparse - - parser = argparse.ArgumentParser(prog=__name__, - description='Creates virtual Python ' - 'environments in one or ' - 'more target ' - 'directories.', - epilog='Once an environment has been ' - 'created, you may wish to ' - 'activate it, e.g. by ' - 'sourcing an activate script ' - 'in its bin directory.') - parser.add_argument('dirs', metavar='ENV_DIR', nargs='+', - help='A directory to create the environment in.') - parser.add_argument('--system-site-packages', default=False, - action='store_true', dest='system_site', - help='Give the virtual environment access to the ' - 'system site-packages dir.') - if os.name == 'nt': - use_symlinks = False - else: - use_symlinks = True - group = parser.add_mutually_exclusive_group() - group.add_argument('--symlinks', default=use_symlinks, - action='store_true', dest='symlinks', - help='Try to use symlinks rather than copies, ' - 'when symlinks are not the default for ' - 'the platform.') - group.add_argument('--copies', default=not use_symlinks, - action='store_false', dest='symlinks', - help='Try to use copies rather than symlinks, ' - 'even when symlinks are the default for ' - 'the platform.') - parser.add_argument('--clear', default=False, action='store_true', - dest='clear', help='Delete the contents of the ' - 'environment directory if it ' - 'already exists, before ' - 'environment creation.') - parser.add_argument('--upgrade', default=False, action='store_true', - dest='upgrade', help='Upgrade the environment ' - 'directory to use this version ' - 'of Python, assuming Python ' - 'has been upgraded in-place.') - parser.add_argument('--without-pip', dest='with_pip', - default=True, action='store_false', - help='Skips installing or upgrading pip in the ' - 'virtual environment (pip is bootstrapped ' - 'by default)') - parser.add_argument('--prompt', - help='Provides an alternative prompt prefix for ' - 'this environment.') - parser.add_argument('--upgrade-deps', default=False, action='store_true', - dest='upgrade_deps', - help='Upgrade core dependencies: {} to the latest ' - 'version in PyPI'.format( - ' '.join(CORE_VENV_DEPS))) - options = parser.parse_args(args) - if options.upgrade and options.clear: - raise ValueError('you cannot supply --upgrade and --clear together.') - builder = EnvBuilder(system_site_packages=options.system_site, - clear=options.clear, - symlinks=options.symlinks, - upgrade=options.upgrade, - with_pip=options.with_pip, - prompt=options.prompt, - upgrade_deps=options.upgrade_deps) - for d in options.dirs: - builder.create(d) - -if __name__ == '__main__': - rc = 1 - try: - main() - rc = 0 - except Exception as e: - print('Error: %s' % e, file=sys.stderr) - sys.exit(rc) diff --git a/LanguageResources/Library/lib/python3.9/venv/__main__.py b/LanguageResources/Library/lib/python3.9/venv/__main__.py deleted file mode 100644 index 912423e4a..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/__main__.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys -from . import main - -rc = 1 -try: - main() - rc = 0 -except Exception as e: - print('Error: %s' % e, file=sys.stderr) -sys.exit(rc) diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 b/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 deleted file mode 100644 index 2fb3852c3..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 +++ /dev/null @@ -1,241 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate b/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate deleted file mode 100644 index 45af3536a..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate +++ /dev/null @@ -1,66 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # This should detect bash and zsh, which have a hash command that must - # be called to get it to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null - fi - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -VIRTUAL_ENV="__VENV_DIR__" -export VIRTUAL_ENV - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1="__VENV_PROMPT__${PS1:-}" - export PS1 -fi - -# This should detect bash and zsh, which have a hash command that must -# be called to get it to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then - hash -r 2> /dev/null -fi diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh deleted file mode 100644 index 68a0dc74e..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh +++ /dev/null @@ -1,25 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "__VENV_DIR__" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = "__VENV_PROMPT__$prompt" -endif - -alias pydoc python -m pydoc - -rehash diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish deleted file mode 100644 index 54b9ea567..000000000 --- a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish +++ /dev/null @@ -1,64 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/); you cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - functions -e fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - - set -e VIRTUAL_ENV - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "__VENV_DIR__" - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end From 3d74afd4b47e34dcd3fc83e19da1aa1b15dc3a40 Mon Sep 17 00:00:00 2001 From: Thales Matheus <1417625@sga.pucminas.br> Date: Sun, 25 Jan 2026 21:08:34 -0600 Subject: [PATCH 11/33] Revert "Remove Python venv scripts and update lock files" This reverts commit 3c7f54f9d0785f8d448e10c59eab310ad047157d. --- .../node_modules/.package-lock.json | 431 ++++++++++ Dependencies/npm.bundle/package-lock.json | 764 ++++++++++++++++++ .../Library/lib/python3.9/venv/__init__.py | 499 ++++++++++++ .../Library/lib/python3.9/venv/__main__.py | 10 + .../venv/scripts/common/Activate.ps1 | 241 ++++++ .../python3.9/venv/scripts/common/activate | 66 ++ .../python3.9/venv/scripts/posix/activate.csh | 25 + .../venv/scripts/posix/activate.fish | 64 ++ 8 files changed, 2100 insertions(+) create mode 100644 LanguageResources/Library/lib/python3.9/venv/__init__.py create mode 100644 LanguageResources/Library/lib/python3.9/venv/__main__.py create mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 create mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/common/activate create mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh create mode 100644 LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish diff --git a/Dependencies/npm.bundle/node_modules/.package-lock.json b/Dependencies/npm.bundle/node_modules/.package-lock.json index 87f92d0ac..4ff98aa84 100644 --- a/Dependencies/npm.bundle/node_modules/.package-lock.json +++ b/Dependencies/npm.bundle/node_modules/.package-lock.json @@ -438,6 +438,27 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", "inBundle": true, @@ -489,11 +510,47 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/asn1": { + "version": "0.2.4", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/npm/node_modules/assert-plus": { + "version": "1.0.0", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/asynckit": { + "version": "0.4.0", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/npm/node_modules/aws-sign2": { + "version": "0.7.0", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/aws4": { + "version": "1.11.0", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/npm/node_modules/bin-links": { "version": "3.0.0", "inBundle": true, @@ -560,6 +617,10 @@ "node": ">= 10" } }, + "node_modules/npm/node_modules/caseless": { + "version": "0.12.0", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "node_modules/npm/node_modules/chalk": { "version": "4.1.2", "inBundle": true, @@ -647,9 +708,21 @@ "colors": "1.4.0" } }, + "node_modules/npm/node_modules/cli-table3/node_modules/ansi-regex": { + "extraneous": true, + "inBundle": true + }, + "node_modules/npm/node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/cli-table3/node_modules/string-width": { "inBundle": true }, + "node_modules/npm/node_modules/cli-table3/node_modules/strip-ansi": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/clone": { "version": "1.0.4", "inBundle": true, @@ -669,6 +742,13 @@ "node": ">=10" } }, + "node_modules/npm/node_modules/code-point-at": { + "version": "1.1.0", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", "inBundle": true, @@ -733,6 +813,16 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/combined-stream": { + "version": "1.0.8", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", "inBundle": true, @@ -748,6 +838,20 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/core-util-is": { + "version": "1.0.2", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/npm/node_modules/dashdash": { + "version": "1.14.1", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/npm/node_modules/debug": { "version": "4.3.3", "inBundle": true, @@ -785,6 +889,13 @@ "clone": "^1.0.2" } }, + "node_modules/npm/node_modules/delayed-stream": { + "version": "1.0.0", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/npm/node_modules/delegates": { "version": "1.0.0", "inBundle": true, @@ -815,6 +926,14 @@ "node": ">=0.3.1" } }, + "node_modules/npm/node_modules/ecc-jsbn": { + "version": "0.1.2", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", "inBundle": true, @@ -842,11 +961,49 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/extend": { + "version": "3.0.2", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/npm/node_modules/extsprintf": { + "version": "1.3.0", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/npm/node_modules/fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/npm/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.12", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/forever-agent": { + "version": "0.6.1", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/form-data": { + "version": "2.3.3", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/npm/node_modules/fs-minipass": { "version": "2.1.0", "inBundle": true, @@ -898,6 +1055,10 @@ "node_modules/npm/node_modules/gauge/node_modules/aproba": { "inBundle": true }, + "node_modules/npm/node_modules/gauge/node_modules/is-fullwidth-code-point": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/gauge/node_modules/string-width": { "inBundle": true }, @@ -912,6 +1073,13 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/getpass": { + "version": "0.1.7", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/npm/node_modules/glob": { "version": "7.2.0", "inBundle": true, @@ -936,6 +1104,25 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/har-schema": { + "version": "2.0.0", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/har-validator": { + "version": "5.1.5", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/npm/node_modules/has": { "version": "1.0.3", "inBundle": true, @@ -989,6 +1176,19 @@ "node": ">= 6" } }, + "node_modules/npm/node_modules/http-signature": { + "version": "1.2.0", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "5.0.0", "inBundle": true, @@ -1145,16 +1345,36 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/isarray": { + "version": "1.0.0", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/isstream": { + "version": "0.1.2", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/npm/node_modules/jsbn": { + "version": "0.1.1", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/json-schema": { + "version": "0.2.3", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/npm/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", "inBundle": true, @@ -1163,6 +1383,10 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/npm/node_modules/json-stringify-safe": { + "version": "5.0.1", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", "engines": [ @@ -1171,6 +1395,19 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/jsprim": { + "version": "1.4.1", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "node_modules/npm/node_modules/just-diff": { "version": "5.0.1", "inBundle": true, @@ -1382,6 +1619,23 @@ "node": ">=12" } }, + "node_modules/npm/node_modules/mime-db": { + "version": "1.47.0", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/mime-types": { + "version": "2.1.30", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/npm/node_modules/minimatch": { "version": "3.0.4", "inBundle": true, @@ -1752,6 +2006,27 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, + "node_modules/npm/node_modules/number-is-nan": { + "version": "1.0.1", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/oauth-sign": { + "version": "0.9.0", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/object-assign": { + "version": "4.1.1", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/once": { "version": "1.4.0", "inBundle": true, @@ -1837,6 +2112,14 @@ "node": ">=0.10.0" } }, + "node_modules/npm/node_modules/path-parse": { + "version": "1.0.6", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "node_modules/npm/node_modules/performance-now": { + "version": "2.1.0", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "node_modules/npm/node_modules/proc-log": { "version": "2.0.0", "inBundle": true, @@ -1845,6 +2128,10 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, + "node_modules/npm/node_modules/process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", "inBundle": true, @@ -1886,6 +2173,17 @@ "read": "1" } }, + "node_modules/npm/node_modules/psl": { + "version": "1.8.0", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/npm/node_modules/punycode": { + "version": "2.1.1", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", "inBundle": true, @@ -1893,6 +2191,13 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, + "node_modules/npm/node_modules/qs": { + "version": "6.5.2", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/npm/node_modules/read": { "version": "1.0.7", "inBundle": true, @@ -1959,6 +2264,58 @@ "once": "^1.3.0" } }, + "node_modules/npm/node_modules/request": { + "version": "2.88.2", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/resolve": { + "version": "1.20.0", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, @@ -2093,6 +2450,29 @@ "inBundle": true, "license": "CC0-1.0" }, + "node_modules/npm/node_modules/sshpk": { + "version": "1.16.1", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/ssri": { "version": "8.0.1", "inBundle": true, @@ -2149,6 +2529,16 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "3.0.1", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -2191,6 +2581,20 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/tunnel-agent": { + "version": "0.6.0", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/tweetnacl": { + "version": "0.14.5", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "node_modules/npm/node_modules/typedarray-to-buffer": { "version": "4.0.0", "funding": [ @@ -2226,11 +2630,26 @@ "imurmurhash": "^0.1.4" } }, + "node_modules/npm/node_modules/uri-js": { + "version": "4.4.1", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/uuid": { + "version": "3.4.0", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", "inBundle": true, @@ -2248,6 +2667,18 @@ "builtins": "^1.0.3" } }, + "node_modules/npm/node_modules/verror": { + "version": "1.10.0", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/npm/node_modules/walk-up-path": { "version": "1.0.0", "inBundle": true, diff --git a/Dependencies/npm.bundle/package-lock.json b/Dependencies/npm.bundle/package-lock.json index 7795449e6..c0966654e 100644 --- a/Dependencies/npm.bundle/package-lock.json +++ b/Dependencies/npm.bundle/package-lock.json @@ -443,6 +443,27 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/ajv": { + "version": "6.12.6", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "2.1.1", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/ansi-styles": { "version": "4.3.0", "inBundle": true, @@ -494,11 +515,47 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/asn1": { + "version": "0.2.4", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/npm/node_modules/assert-plus": { + "version": "1.0.0", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/asynckit": { + "version": "0.4.0", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/npm/node_modules/aws-sign2": { + "version": "0.7.0", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/aws4": { + "version": "1.11.0", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "node_modules/npm/node_modules/balanced-match": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/npm/node_modules/bin-links": { "version": "3.0.0", "inBundle": true, @@ -565,6 +622,10 @@ "node": ">= 10" } }, + "node_modules/npm/node_modules/caseless": { + "version": "0.12.0", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "node_modules/npm/node_modules/chalk": { "version": "4.1.2", "inBundle": true, @@ -652,9 +713,21 @@ "colors": "1.4.0" } }, + "node_modules/npm/node_modules/cli-table3/node_modules/ansi-regex": { + "extraneous": true, + "inBundle": true + }, + "node_modules/npm/node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/cli-table3/node_modules/string-width": { "inBundle": true }, + "node_modules/npm/node_modules/cli-table3/node_modules/strip-ansi": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/clone": { "version": "1.0.4", "inBundle": true, @@ -674,6 +747,13 @@ "node": ">=10" } }, + "node_modules/npm/node_modules/code-point-at": { + "version": "1.1.0", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/color-convert": { "version": "2.0.1", "inBundle": true, @@ -738,6 +818,16 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/combined-stream": { + "version": "1.0.8", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/npm/node_modules/common-ancestor-path": { "version": "1.0.1", "inBundle": true, @@ -753,6 +843,20 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/core-util-is": { + "version": "1.0.2", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/npm/node_modules/dashdash": { + "version": "1.14.1", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/npm/node_modules/debug": { "version": "4.3.3", "inBundle": true, @@ -790,6 +894,13 @@ "clone": "^1.0.2" } }, + "node_modules/npm/node_modules/delayed-stream": { + "version": "1.0.0", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/npm/node_modules/delegates": { "version": "1.0.0", "inBundle": true, @@ -820,6 +931,14 @@ "node": ">=0.3.1" } }, + "node_modules/npm/node_modules/ecc-jsbn": { + "version": "0.1.2", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/npm/node_modules/emoji-regex": { "version": "8.0.0", "inBundle": true, @@ -847,11 +966,49 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/extend": { + "version": "3.0.2", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/npm/node_modules/extsprintf": { + "version": "1.3.0", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/npm/node_modules/fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/npm/node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "node_modules/npm/node_modules/fastest-levenshtein": { "version": "1.0.12", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/forever-agent": { + "version": "0.6.1", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/form-data": { + "version": "2.3.3", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/npm/node_modules/fs-minipass": { "version": "2.1.0", "inBundle": true, @@ -903,6 +1060,10 @@ "node_modules/npm/node_modules/gauge/node_modules/aproba": { "inBundle": true }, + "node_modules/npm/node_modules/gauge/node_modules/is-fullwidth-code-point": { + "extraneous": true, + "inBundle": true + }, "node_modules/npm/node_modules/gauge/node_modules/string-width": { "inBundle": true }, @@ -917,6 +1078,13 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/getpass": { + "version": "0.1.7", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/npm/node_modules/glob": { "version": "7.2.0", "inBundle": true, @@ -941,6 +1109,25 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/har-schema": { + "version": "2.0.0", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/har-validator": { + "version": "5.1.5", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/npm/node_modules/has": { "version": "1.0.3", "inBundle": true, @@ -994,6 +1181,19 @@ "node": ">= 6" } }, + "node_modules/npm/node_modules/http-signature": { + "version": "1.2.0", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/npm/node_modules/https-proxy-agent": { "version": "5.0.0", "inBundle": true, @@ -1150,16 +1350,36 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/isarray": { + "version": "1.0.0", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "node_modules/npm/node_modules/isexe": { "version": "2.0.0", "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/isstream": { + "version": "0.1.2", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/npm/node_modules/jsbn": { + "version": "0.1.1", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "node_modules/npm/node_modules/json-parse-even-better-errors": { "version": "2.3.1", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/json-schema": { + "version": "0.2.3", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/npm/node_modules/json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "node_modules/npm/node_modules/json-stringify-nice": { "version": "1.1.4", "inBundle": true, @@ -1168,6 +1388,10 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/npm/node_modules/json-stringify-safe": { + "version": "5.0.1", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "node_modules/npm/node_modules/jsonparse": { "version": "1.3.1", "engines": [ @@ -1176,6 +1400,19 @@ "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/jsprim": { + "version": "1.4.1", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "node_modules/npm/node_modules/just-diff": { "version": "5.0.1", "inBundle": true, @@ -1387,6 +1624,23 @@ "node": ">=12" } }, + "node_modules/npm/node_modules/mime-db": { + "version": "1.47.0", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/mime-types": { + "version": "2.1.30", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "dependencies": { + "mime-db": "1.47.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/npm/node_modules/minimatch": { "version": "3.0.4", "inBundle": true, @@ -1757,6 +2011,27 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, + "node_modules/npm/node_modules/number-is-nan": { + "version": "1.0.1", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/oauth-sign": { + "version": "0.9.0", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/object-assign": { + "version": "4.1.1", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/once": { "version": "1.4.0", "inBundle": true, @@ -1842,6 +2117,14 @@ "node": ">=0.10.0" } }, + "node_modules/npm/node_modules/path-parse": { + "version": "1.0.6", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "node_modules/npm/node_modules/performance-now": { + "version": "2.1.0", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "node_modules/npm/node_modules/proc-log": { "version": "2.0.0", "inBundle": true, @@ -1850,6 +2133,10 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, + "node_modules/npm/node_modules/process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/npm/node_modules/promise-all-reject-late": { "version": "1.0.1", "inBundle": true, @@ -1891,6 +2178,17 @@ "read": "1" } }, + "node_modules/npm/node_modules/psl": { + "version": "1.8.0", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/npm/node_modules/punycode": { + "version": "2.1.1", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, "node_modules/npm/node_modules/qrcode-terminal": { "version": "0.12.0", "inBundle": true, @@ -1898,6 +2196,13 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, + "node_modules/npm/node_modules/qs": { + "version": "6.5.2", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, "node_modules/npm/node_modules/read": { "version": "1.0.7", "inBundle": true, @@ -1964,6 +2269,58 @@ "once": "^1.3.0" } }, + "node_modules/npm/node_modules/request": { + "version": "2.88.2", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/resolve": { + "version": "1.20.0", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/npm/node_modules/retry": { "version": "0.12.0", "inBundle": true, @@ -2098,6 +2455,29 @@ "inBundle": true, "license": "CC0-1.0" }, + "node_modules/npm/node_modules/sshpk": { + "version": "1.16.1", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/ssri": { "version": "8.0.1", "inBundle": true, @@ -2154,6 +2534,16 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "3.0.1", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm/node_modules/supports-color": { "version": "7.2.0", "inBundle": true, @@ -2196,6 +2586,20 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/tunnel-agent": { + "version": "0.6.0", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/tweetnacl": { + "version": "0.14.5", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "node_modules/npm/node_modules/typedarray-to-buffer": { "version": "4.0.0", "funding": [ @@ -2231,11 +2635,26 @@ "imurmurhash": "^0.1.4" } }, + "node_modules/npm/node_modules/uri-js": { + "version": "4.4.1", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/npm/node_modules/util-deprecate": { "version": "1.0.2", "inBundle": true, "license": "MIT" }, + "node_modules/npm/node_modules/uuid": { + "version": "3.4.0", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/npm/node_modules/validate-npm-package-license": { "version": "3.0.4", "inBundle": true, @@ -2253,6 +2672,18 @@ "builtins": "^1.0.3" } }, + "node_modules/npm/node_modules/verror": { + "version": "1.10.0", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/npm/node_modules/walk-up-path": { "version": "1.0.0", "inBundle": true, @@ -2594,6 +3025,20 @@ "indent-string": "^4.0.0" } }, + "ajv": { + "version": "6.12.6", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, "ansi-styles": { "version": "4.3.0", "bundled": true, @@ -2629,10 +3074,40 @@ "version": "2.0.6", "bundled": true }, + "asn1": { + "version": "0.2.4", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, "balanced-match": { "version": "1.0.2", "bundled": true }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "bin-links": { "version": "3.0.0", "bundled": true, @@ -2685,6 +3160,10 @@ "unique-filename": "^1.1.1" } }, + "caseless": { + "version": "0.12.0", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "chalk": { "version": "4.1.2", "bundled": true, @@ -2737,8 +3216,20 @@ "string-width": "^4.2.0" }, "dependencies": { + "ansi-regex": { + "bundled": true, + "extraneous": true + }, + "is-fullwidth-code-point": { + "bundled": true, + "extraneous": true + }, "string-width": { "bundled": true + }, + "strip-ansi": { + "bundled": true, + "extraneous": true } } }, @@ -2753,6 +3244,10 @@ "mkdirp-infer-owner": "^2.0.0" } }, + "code-point-at": { + "version": "1.1.0", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, "color-convert": { "version": "2.0.1", "bundled": true, @@ -2794,6 +3289,13 @@ } } }, + "combined-stream": { + "version": "1.0.8", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "common-ancestor-path": { "version": "1.0.1", "bundled": true @@ -2806,6 +3308,17 @@ "version": "1.1.0", "bundled": true }, + "core-util-is": { + "version": "1.0.2", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "4.3.3", "bundled": true, @@ -2830,6 +3343,10 @@ "clone": "^1.0.2" } }, + "delayed-stream": { + "version": "1.0.0", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "delegates": { "version": "1.0.0", "bundled": true @@ -2850,6 +3367,14 @@ "version": "5.0.0", "bundled": true }, + "ecc-jsbn": { + "version": "0.1.2", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "emoji-regex": { "version": "8.0.0", "bundled": true @@ -2870,10 +3395,39 @@ "version": "2.0.3", "bundled": true }, + "extend": { + "version": "3.0.2", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "fastest-levenshtein": { "version": "1.0.12", "bundled": true }, + "forever-agent": { + "version": "0.6.1", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fs-minipass": { "version": "2.1.0", "bundled": true, @@ -2911,6 +3465,10 @@ "aproba": { "bundled": true }, + "is-fullwidth-code-point": { + "bundled": true, + "extraneous": true + }, "string-width": { "bundled": true }, @@ -2923,6 +3481,13 @@ } } }, + "getpass": { + "version": "0.1.7", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "glob": { "version": "7.2.0", "bundled": true, @@ -2939,6 +3504,18 @@ "version": "4.2.9", "bundled": true }, + "har-schema": { + "version": "2.0.0", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, "has": { "version": "1.0.3", "bundled": true, @@ -2974,6 +3551,15 @@ "debug": "4" } }, + "http-signature": { + "version": "1.2.0", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "https-proxy-agent": { "version": "5.0.0", "bundled": true, @@ -3079,22 +3665,56 @@ "version": "1.0.0", "bundled": true }, + "isarray": { + "version": "1.0.0", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "isexe": { "version": "2.0.0", "bundled": true }, + "isstream": { + "version": "0.1.2", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, "json-parse-even-better-errors": { "version": "2.3.1", "bundled": true }, + "json-schema": { + "version": "0.2.3", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, "json-stringify-nice": { "version": "1.1.4", "bundled": true }, + "json-stringify-safe": { + "version": "5.0.1", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, "jsonparse": { "version": "1.3.1", "bundled": true }, + "jsprim": { + "version": "1.4.1", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "just-diff": { "version": "5.0.1", "bundled": true @@ -3250,6 +3870,17 @@ } } }, + "mime-db": { + "version": "1.47.0", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + }, + "mime-types": { + "version": "2.1.30", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "requires": { + "mime-db": "1.47.0" + } + }, "minimatch": { "version": "3.0.4", "bundled": true, @@ -3502,6 +4133,18 @@ "set-blocking": "^2.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "once": { "version": "1.4.0", "bundled": true, @@ -3560,10 +4203,22 @@ "version": "1.0.1", "bundled": true }, + "path-parse": { + "version": "1.0.6", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "performance-now": { + "version": "2.1.0", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "proc-log": { "version": "2.0.0", "bundled": true }, + "process-nextick-args": { + "version": "2.0.1", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "promise-all-reject-late": { "version": "1.0.1", "bundled": true @@ -3591,10 +4246,22 @@ "read": "1" } }, + "psl": { + "version": "1.8.0", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "punycode": { + "version": "2.1.1", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, "qrcode-terminal": { "version": "0.12.0", "bundled": true }, + "qs": { + "version": "6.5.2", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, "read": { "version": "1.0.7", "bundled": true, @@ -3643,6 +4310,50 @@ "once": "^1.3.0" } }, + "request": { + "version": "2.88.2", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "resolve": { + "version": "1.20.0", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, "retry": { "version": "0.12.0", "bundled": true @@ -3723,6 +4434,21 @@ "version": "3.0.11", "bundled": true }, + "sshpk": { + "version": "1.16.1", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "ssri": { "version": "8.0.1", "bundled": true, @@ -3763,6 +4489,13 @@ "version": "1.0.1", "bundled": true }, + "strip-ansi": { + "version": "3.0.1", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "7.2.0", "bundled": true, @@ -3794,6 +4527,17 @@ "version": "1.0.4", "bundled": true }, + "tunnel-agent": { + "version": "0.6.0", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "typedarray-to-buffer": { "version": "4.0.0", "bundled": true @@ -3812,10 +4556,21 @@ "imurmurhash": "^0.1.4" } }, + "uri-js": { + "version": "4.4.1", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, "util-deprecate": { "version": "1.0.2", "bundled": true }, + "uuid": { + "version": "3.4.0", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, "validate-npm-package-license": { "version": "3.0.4", "bundled": true, @@ -3831,6 +4586,15 @@ "builtins": "^1.0.3" } }, + "verror": { + "version": "1.10.0", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "walk-up-path": { "version": "1.0.0", "bundled": true diff --git a/LanguageResources/Library/lib/python3.9/venv/__init__.py b/LanguageResources/Library/lib/python3.9/venv/__init__.py new file mode 100644 index 000000000..8009deb3e --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/__init__.py @@ -0,0 +1,499 @@ +""" +Virtual environment (venv) package for Python. Based on PEP 405. + +Copyright (C) 2011-2014 Vinay Sajip. +Licensed to the PSF under a contributor agreement. +""" +import logging +import os +import shutil +import subprocess +import sys +import sysconfig +import types + + +CORE_VENV_DEPS = ('pip', 'setuptools') +logger = logging.getLogger(__name__) + + +class EnvBuilder: + """ + This class exists to allow virtual environment creation to be + customized. The constructor parameters determine the builder's + behaviour when called upon to create a virtual environment. + + By default, the builder makes the system (global) site-packages dir + *un*available to the created environment. + + If invoked using the Python -m option, the default is to use copying + on Windows platforms but symlinks elsewhere. If instantiated some + other way, the default is to *not* use symlinks. + + :param system_site_packages: If True, the system (global) site-packages + dir is available to created environments. + :param clear: If True, delete the contents of the environment directory if + it already exists, before environment creation. + :param symlinks: If True, attempt to symlink rather than copy files into + virtual environment. + :param upgrade: If True, upgrade an existing virtual environment. + :param with_pip: If True, ensure pip is installed in the virtual + environment + :param prompt: Alternative terminal prefix for the environment. + :param upgrade_deps: Update the base venv modules to the latest on PyPI + """ + + def __init__(self, system_site_packages=False, clear=False, + symlinks=False, upgrade=False, with_pip=False, prompt=None, + upgrade_deps=False): + self.system_site_packages = system_site_packages + self.clear = clear + self.symlinks = symlinks + self.upgrade = upgrade + self.with_pip = with_pip + if prompt == '.': # see bpo-38901 + prompt = os.path.basename(os.getcwd()) + self.prompt = prompt + self.upgrade_deps = upgrade_deps + + def create(self, env_dir): + """ + Create a virtual environment in a directory. + + :param env_dir: The target directory to create an environment in. + + """ + env_dir = os.path.abspath(env_dir) + context = self.ensure_directories(env_dir) + # See issue 24875. We need system_site_packages to be False + # until after pip is installed. + true_system_site_packages = self.system_site_packages + self.system_site_packages = False + self.create_configuration(context) + self.setup_python(context) + if self.with_pip: + self._setup_pip(context) + if not self.upgrade: + self.setup_scripts(context) + self.post_setup(context) + if true_system_site_packages: + # We had set it to False before, now + # restore it and rewrite the configuration + self.system_site_packages = True + self.create_configuration(context) + if self.upgrade_deps: + self.upgrade_dependencies(context) + + def clear_directory(self, path): + for fn in os.listdir(path): + fn = os.path.join(path, fn) + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + + def ensure_directories(self, env_dir): + """ + Create the directories for the environment. + + Returns a context object which holds paths in the environment, + for use by subsequent logic. + """ + + def create_if_needed(d): + if not os.path.exists(d): + os.makedirs(d) + elif os.path.islink(d) or os.path.isfile(d): + raise ValueError('Unable to create directory %r' % d) + + if os.path.exists(env_dir) and self.clear: + self.clear_directory(env_dir) + context = types.SimpleNamespace() + context.env_dir = env_dir + context.env_name = os.path.split(env_dir)[1] + prompt = self.prompt if self.prompt is not None else context.env_name + context.prompt = '(%s) ' % prompt + create_if_needed(env_dir) + executable = sys._base_executable + dirname, exename = os.path.split(os.path.abspath(executable)) + context.executable = executable + context.python_dir = dirname + context.python_exe = exename + if sys.platform == 'win32': + binname = 'Scripts' + incpath = 'Include' + libpath = os.path.join(env_dir, 'Lib', 'site-packages') + else: + binname = 'bin' + incpath = 'include' + libpath = os.path.join(env_dir, 'lib', + 'python%d.%d' % sys.version_info[:2], + 'site-packages') + context.inc_path = path = os.path.join(env_dir, incpath) + create_if_needed(path) + create_if_needed(libpath) + # Issue 21197: create lib64 as a symlink to lib on 64-bit non-OS X POSIX + if ((sys.maxsize > 2**32) and (os.name == 'posix') and + (sys.platform != 'darwin')): + link_path = os.path.join(env_dir, 'lib64') + if not os.path.exists(link_path): # Issue #21643 + os.symlink('lib', link_path) + context.bin_path = binpath = os.path.join(env_dir, binname) + context.bin_name = binname + context.env_exe = os.path.join(binpath, exename) + create_if_needed(binpath) + return context + + def create_configuration(self, context): + """ + Create a configuration file indicating where the environment's Python + was copied from, and whether the system site-packages should be made + available in the environment. + + :param context: The information for the environment creation request + being processed. + """ + context.cfg_path = path = os.path.join(context.env_dir, 'pyvenv.cfg') + with open(path, 'w', encoding='utf-8') as f: + f.write('home = %s\n' % context.python_dir) + if self.system_site_packages: + incl = 'true' + else: + incl = 'false' + f.write('include-system-site-packages = %s\n' % incl) + f.write('version = %d.%d.%d\n' % sys.version_info[:3]) + if self.prompt is not None: + f.write(f'prompt = {self.prompt!r}\n') + + if os.name != 'nt': + def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): + """ + Try symlinking a file, and if that fails, fall back to copying. + """ + force_copy = not self.symlinks + if not force_copy: + try: + if not os.path.islink(dst): # can't link to itself! + if relative_symlinks_ok: + assert os.path.dirname(src) == os.path.dirname(dst) + os.symlink(os.path.basename(src), dst) + else: + os.symlink(src, dst) + except Exception: # may need to use a more specific exception + logger.warning('Unable to symlink %r to %r', src, dst) + force_copy = True + if force_copy: + shutil.copyfile(src, dst) + else: + def symlink_or_copy(self, src, dst, relative_symlinks_ok=False): + """ + Try symlinking a file, and if that fails, fall back to copying. + """ + bad_src = os.path.lexists(src) and not os.path.exists(src) + if self.symlinks and not bad_src and not os.path.islink(dst): + try: + if relative_symlinks_ok: + assert os.path.dirname(src) == os.path.dirname(dst) + os.symlink(os.path.basename(src), dst) + else: + os.symlink(src, dst) + return + except Exception: # may need to use a more specific exception + logger.warning('Unable to symlink %r to %r', src, dst) + + # On Windows, we rewrite symlinks to our base python.exe into + # copies of venvlauncher.exe + basename, ext = os.path.splitext(os.path.basename(src)) + srcfn = os.path.join(os.path.dirname(__file__), + "scripts", + "nt", + basename + ext) + # Builds or venv's from builds need to remap source file + # locations, as we do not put them into Lib/venv/scripts + if sysconfig.is_python_build(True) or not os.path.isfile(srcfn): + if basename.endswith('_d'): + ext = '_d' + ext + basename = basename[:-2] + if basename == 'python': + basename = 'venvlauncher' + elif basename == 'pythonw': + basename = 'venvwlauncher' + src = os.path.join(os.path.dirname(src), basename + ext) + else: + src = srcfn + if not os.path.exists(src): + if not bad_src: + logger.warning('Unable to copy %r', src) + return + + shutil.copyfile(src, dst) + + def setup_python(self, context): + """ + Set up a Python executable in the environment. + + :param context: The information for the environment creation request + being processed. + """ + binpath = context.bin_path + path = context.env_exe + copier = self.symlink_or_copy + dirname = context.python_dir + if os.name != 'nt': + copier(context.executable, path) + if not os.path.islink(path): + os.chmod(path, 0o755) + for suffix in ('python', 'python3', f'python3.{sys.version_info[1]}'): + path = os.path.join(binpath, suffix) + if not os.path.exists(path): + # Issue 18807: make copies if + # symlinks are not wanted + copier(context.env_exe, path, relative_symlinks_ok=True) + if not os.path.islink(path): + os.chmod(path, 0o755) + else: + if self.symlinks: + # For symlinking, we need a complete copy of the root directory + # If symlinks fail, you'll get unnecessary copies of files, but + # we assume that if you've opted into symlinks on Windows then + # you know what you're doing. + suffixes = [ + f for f in os.listdir(dirname) if + os.path.normcase(os.path.splitext(f)[1]) in ('.exe', '.dll') + ] + if sysconfig.is_python_build(True): + suffixes = [ + f for f in suffixes if + os.path.normcase(f).startswith(('python', 'vcruntime')) + ] + else: + suffixes = ['python.exe', 'python_d.exe', 'pythonw.exe', + 'pythonw_d.exe'] + + for suffix in suffixes: + src = os.path.join(dirname, suffix) + if os.path.lexists(src): + copier(src, os.path.join(binpath, suffix)) + + if sysconfig.is_python_build(True): + # copy init.tcl + for root, dirs, files in os.walk(context.python_dir): + if 'init.tcl' in files: + tcldir = os.path.basename(root) + tcldir = os.path.join(context.env_dir, 'Lib', tcldir) + if not os.path.exists(tcldir): + os.makedirs(tcldir) + src = os.path.join(root, 'init.tcl') + dst = os.path.join(tcldir, 'init.tcl') + shutil.copyfile(src, dst) + break + + def _setup_pip(self, context): + """Installs or upgrades pip in a virtual environment""" + # We run ensurepip in isolated mode to avoid side effects from + # environment vars, the current directory and anything else + # intended for the global Python environment + cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade', + '--default-pip'] + subprocess.check_output(cmd, stderr=subprocess.STDOUT) + + def setup_scripts(self, context): + """ + Set up scripts into the created environment from a directory. + + This method installs the default scripts into the environment + being created. You can prevent the default installation by overriding + this method if you really need to, or if you need to specify + a different location for the scripts to install. By default, the + 'scripts' directory in the venv package is used as the source of + scripts to install. + """ + path = os.path.abspath(os.path.dirname(__file__)) + path = os.path.join(path, 'scripts') + self.install_scripts(context, path) + + def post_setup(self, context): + """ + Hook for post-setup modification of the venv. Subclasses may install + additional packages or scripts here, add activation shell scripts, etc. + + :param context: The information for the environment creation request + being processed. + """ + pass + + def replace_variables(self, text, context): + """ + Replace variable placeholders in script text with context-specific + variables. + + Return the text passed in , but with variables replaced. + + :param text: The text in which to replace placeholder variables. + :param context: The information for the environment creation request + being processed. + """ + text = text.replace('__VENV_DIR__', context.env_dir) + text = text.replace('__VENV_NAME__', context.env_name) + text = text.replace('__VENV_PROMPT__', context.prompt) + text = text.replace('__VENV_BIN_NAME__', context.bin_name) + text = text.replace('__VENV_PYTHON__', context.env_exe) + return text + + def install_scripts(self, context, path): + """ + Install scripts into the created environment from a directory. + + :param context: The information for the environment creation request + being processed. + :param path: Absolute pathname of a directory containing script. + Scripts in the 'common' subdirectory of this directory, + and those in the directory named for the platform + being run on, are installed in the created environment. + Placeholder variables are replaced with environment- + specific values. + """ + binpath = context.bin_path + plen = len(path) + for root, dirs, files in os.walk(path): + if root == path: # at top-level, remove irrelevant dirs + for d in dirs[:]: + if d not in ('common', os.name): + dirs.remove(d) + continue # ignore files in top level + for f in files: + if (os.name == 'nt' and f.startswith('python') + and f.endswith(('.exe', '.pdb'))): + continue + srcfile = os.path.join(root, f) + suffix = root[plen:].split(os.sep)[2:] + if not suffix: + dstdir = binpath + else: + dstdir = os.path.join(binpath, *suffix) + if not os.path.exists(dstdir): + os.makedirs(dstdir) + dstfile = os.path.join(dstdir, f) + with open(srcfile, 'rb') as f: + data = f.read() + if not srcfile.endswith(('.exe', '.pdb')): + try: + data = data.decode('utf-8') + data = self.replace_variables(data, context) + data = data.encode('utf-8') + except UnicodeError as e: + data = None + logger.warning('unable to copy script %r, ' + 'may be binary: %s', srcfile, e) + if data is not None: + with open(dstfile, 'wb') as f: + f.write(data) + shutil.copymode(srcfile, dstfile) + + def upgrade_dependencies(self, context): + logger.debug( + f'Upgrading {CORE_VENV_DEPS} packages in {context.bin_path}' + ) + if sys.platform == 'win32': + python_exe = os.path.join(context.bin_path, 'python.exe') + else: + python_exe = os.path.join(context.bin_path, 'python') + cmd = [python_exe, '-m', 'pip', 'install', '--upgrade'] + cmd.extend(CORE_VENV_DEPS) + subprocess.check_call(cmd) + + +def create(env_dir, system_site_packages=False, clear=False, + symlinks=False, with_pip=False, prompt=None, upgrade_deps=False): + """Create a virtual environment in a directory.""" + builder = EnvBuilder(system_site_packages=system_site_packages, + clear=clear, symlinks=symlinks, with_pip=with_pip, + prompt=prompt, upgrade_deps=upgrade_deps) + builder.create(env_dir) + +def main(args=None): + compatible = True + if sys.version_info < (3, 3): + compatible = False + elif not hasattr(sys, 'base_prefix'): + compatible = False + if not compatible: + raise ValueError('This script is only for use with Python >= 3.3') + else: + import argparse + + parser = argparse.ArgumentParser(prog=__name__, + description='Creates virtual Python ' + 'environments in one or ' + 'more target ' + 'directories.', + epilog='Once an environment has been ' + 'created, you may wish to ' + 'activate it, e.g. by ' + 'sourcing an activate script ' + 'in its bin directory.') + parser.add_argument('dirs', metavar='ENV_DIR', nargs='+', + help='A directory to create the environment in.') + parser.add_argument('--system-site-packages', default=False, + action='store_true', dest='system_site', + help='Give the virtual environment access to the ' + 'system site-packages dir.') + if os.name == 'nt': + use_symlinks = False + else: + use_symlinks = True + group = parser.add_mutually_exclusive_group() + group.add_argument('--symlinks', default=use_symlinks, + action='store_true', dest='symlinks', + help='Try to use symlinks rather than copies, ' + 'when symlinks are not the default for ' + 'the platform.') + group.add_argument('--copies', default=not use_symlinks, + action='store_false', dest='symlinks', + help='Try to use copies rather than symlinks, ' + 'even when symlinks are the default for ' + 'the platform.') + parser.add_argument('--clear', default=False, action='store_true', + dest='clear', help='Delete the contents of the ' + 'environment directory if it ' + 'already exists, before ' + 'environment creation.') + parser.add_argument('--upgrade', default=False, action='store_true', + dest='upgrade', help='Upgrade the environment ' + 'directory to use this version ' + 'of Python, assuming Python ' + 'has been upgraded in-place.') + parser.add_argument('--without-pip', dest='with_pip', + default=True, action='store_false', + help='Skips installing or upgrading pip in the ' + 'virtual environment (pip is bootstrapped ' + 'by default)') + parser.add_argument('--prompt', + help='Provides an alternative prompt prefix for ' + 'this environment.') + parser.add_argument('--upgrade-deps', default=False, action='store_true', + dest='upgrade_deps', + help='Upgrade core dependencies: {} to the latest ' + 'version in PyPI'.format( + ' '.join(CORE_VENV_DEPS))) + options = parser.parse_args(args) + if options.upgrade and options.clear: + raise ValueError('you cannot supply --upgrade and --clear together.') + builder = EnvBuilder(system_site_packages=options.system_site, + clear=options.clear, + symlinks=options.symlinks, + upgrade=options.upgrade, + with_pip=options.with_pip, + prompt=options.prompt, + upgrade_deps=options.upgrade_deps) + for d in options.dirs: + builder.create(d) + +if __name__ == '__main__': + rc = 1 + try: + main() + rc = 0 + except Exception as e: + print('Error: %s' % e, file=sys.stderr) + sys.exit(rc) diff --git a/LanguageResources/Library/lib/python3.9/venv/__main__.py b/LanguageResources/Library/lib/python3.9/venv/__main__.py new file mode 100644 index 000000000..912423e4a --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/__main__.py @@ -0,0 +1,10 @@ +import sys +from . import main + +rc = 1 +try: + main() + rc = 0 +except Exception as e: + print('Error: %s' % e, file=sys.stderr) +sys.exit(rc) diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 b/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 new file mode 100644 index 000000000..2fb3852c3 --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/scripts/common/Activate.ps1 @@ -0,0 +1,241 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate b/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate new file mode 100644 index 000000000..45af3536a --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/scripts/common/activate @@ -0,0 +1,66 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="__VENV_DIR__" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="__VENV_PROMPT__${PS1:-}" + export PS1 +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh new file mode 100644 index 000000000..68a0dc74e --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.csh @@ -0,0 +1,25 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "__VENV_DIR__" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "__VENV_PROMPT__$prompt" +endif + +alias pydoc python -m pydoc + +rehash diff --git a/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish new file mode 100644 index 000000000..54b9ea567 --- /dev/null +++ b/LanguageResources/Library/lib/python3.9/venv/scripts/posix/activate.fish @@ -0,0 +1,64 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/); you cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + functions -e fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + + set -e VIRTUAL_ENV + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "__VENV_DIR__" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end From 6c06d226adf70e440372c8939e582f121f8a597c Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 13:04:56 +0800 Subject: [PATCH 12/33] Remove interrupt button from terminal toolbar --- Extensions/TerminalService/TerminalExtension.swift | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index 4cafb6d5a..8a7f4b031 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -31,15 +31,6 @@ private struct ToolbarView: View { .disabled(!App.terminalManager.canCreateNewTerminal) .help("New Terminal") - Button( - action: { - App.terminalManager.activeTerminal?.sendInterrupt() - }, - label: { - Text("^C") - } - ).keyboardShortcut("c", modifiers: [.control]) - Button( action: { App.terminalManager.activeTerminal?.reset() From b0c6f7a43a803867f1a9adcaa27d56198436dfeb Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 13:05:41 +0800 Subject: [PATCH 13/33] Add accessibility labels and confirmation messages for terminal tab actions --- .../Localization/de.lproj/Localizable.strings | 11 +++++++++- .../Localization/en.lproj/Localizable.strings | 8 ++++++++ .../Localization/ja.lproj/Localizable.strings | 11 +++++++++- .../Localization/ko.lproj/Localizable.strings | 11 +++++++++- .../Localization/ru.lproj/Localizable.strings | 8 ++++++++ .../zh-Hans.lproj/Localizable.strings | 8 ++++++++ CodeApp/Views/TerminalTabBar.swift | 20 +++++++++---------- 7 files changed, 64 insertions(+), 13 deletions(-) diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 2bd496206..51367b0a0 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -665,4 +665,13 @@ "remote.port_forward.configure_description" = "Um eine Portweiterleitung zu konfigurieren, geben Sie die lokale und die Remote-Adresse ein. Wenn Sie eine Adresse eingeben, wird der Port 22 verwendet."; "remote.port_forward.address_example" = "z.B. 6000 oder 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH Remote"; -"remote.settings.resolve_home_path" = "Pfad auflösen"; \ No newline at end of file +"remote.settings.resolve_home_path" = "Pfad auflösen"; + +"terminal.tab.accessibility.active" = "Aktiv"; +"terminal.tab.accessibility.running" = "Läuft"; +"terminal.tab.accessibility.hint" = "Doppeltippen zum Wechseln zu diesem Terminal"; +"terminal.tab.kill" = "Terminal beenden"; +"terminal.tab.kill_confirmation.title" = "Terminal beenden?"; +"terminal.tab.kill_confirmation.cancel" = "Abbrechen"; +"terminal.tab.kill_confirmation.kill" = "Beenden"; +"terminal.tab.kill_confirmation.message" = "Dieses Terminal hat einen laufenden Prozess. Möchten Sie ihn wirklich beenden?"; diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index be3db0739..35d5c449e 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -561,3 +561,11 @@ are licensed under [BSD-3-Clause License](https://en.wikipedia.org/wiki/BSD_lice "remote.port_forward.address_example" = "e.g. 6000 or 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH Remote"; "remote.settings.resolve_home_path" = "Resolve Home Path"; +"terminal.tab.accessibility.active" = "Active"; +"terminal.tab.accessibility.running" = "Running"; +"terminal.tab.accessibility.hint" = "Double tap to switch to this terminal"; +"terminal.tab.kill" = "Kill Terminal"; +"terminal.tab.kill_confirmation.title" = "Kill Terminal?"; +"terminal.tab.kill_confirmation.cancel" = "Cancel"; +"terminal.tab.kill_confirmation.kill" = "Kill"; +"terminal.tab.kill_confirmation.message" = "This terminal has a running process. Are you sure you want to kill it?"; \ No newline at end of file diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index 6a3701ae6..800351921 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -665,4 +665,13 @@ "remote.port_forward.configure_description" = "ポートフォワーディングを使用すると、リモート ホストのポートをローカル ホストに転送できます。"; "remote.port_forward.address_example" = "例えば 6000 または 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH リモート"; -"remote.settings.resolve_home_path" = "ホーム パスを解決する"; \ No newline at end of file +"remote.settings.resolve_home_path" = "ホーム パスを解決する"; + +"terminal.tab.accessibility.active" = "アクティブ"; +"terminal.tab.accessibility.running" = "実行中"; +"terminal.tab.accessibility.hint" = "ダブルタップしてこのターミナルに切り替える"; +"terminal.tab.kill" = "ターミナルを閉じる"; +"terminal.tab.kill_confirmation.title" = "ターミナルを閉じますか?"; +"terminal.tab.kill_confirmation.cancel" = "キャンセル"; +"terminal.tab.kill_confirmation.kill" = "閉じる"; +"terminal.tab.kill_confirmation.message" = "このターミナルは実行中のプロセスを持っています。本当に閉じますか?"; diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index e35463815..7ae22c8c0 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -664,4 +664,13 @@ "remote.port_forward.configure_description" = "원격 시스템의 포트에 액세스하도록 포트 전달을 구성합니다."; "remote.port_forward.address_example" = "예를 들어 6000 또는 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH 원격 서버"; -"remote.settings.resolve_home_path" = "홈 경로 해결"; \ No newline at end of file +"remote.settings.resolve_home_path" = "홈 경로 해결"; + +"terminal.tab.accessibility.active" = "활성"; +"terminal.tab.accessibility.running" = "실행 중"; +"terminal.tab.accessibility.hint" = "이 터미널로 전환하려면 두 번 탭하세요"; +"terminal.tab.kill" = "터미널 닫기"; +"terminal.tab.kill_confirmation.title" = "터미널을 닫으시겠습니까?"; +"terminal.tab.kill_confirmation.cancel" = "취소"; +"terminal.tab.kill_confirmation.kill" = "닫기"; +"terminal.tab.kill_confirmation.message" = "이 터미널은 실행 중의 프로세스가 있습니다. 정말 닫으시겠습니까?"; diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index 4ff9c7d0a..504a2a45e 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -703,3 +703,11 @@ "remote.port_forward.address_example" = "пр. 6000 или 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH-подключение"; "remote.settings.resolve_home_path" = "Открывать домашний каталог"; +"terminal.tab.accessibility.active" = "Активна"; +"terminal.tab.accessibility.running" = "Выполняется"; +"terminal.tab.accessibility.hint" = "Дважды коснитесь, чтобы переключиться на этот терминал"; +"terminal.tab.kill" = "Закрыть терминал"; +"terminal.tab.kill_confirmation.title" = "Закрыть терминал?"; +"terminal.tab.kill_confirmation.cancel" = "Отмена"; +"terminal.tab.kill_confirmation.kill" = "Закрыть"; +"terminal.tab.kill_confirmation.message" = "Этот терминал имеет запущенный процесс. Вы уверены, что хотите его закрыть?"; \ No newline at end of file diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index c3f8cbba7..3091f5e4f 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -656,3 +656,11 @@ "remote.port_forward.address_example" = "例如 6000 或 127.0.0.1:6000"; "remote.settings.ssh_remote" = "SSH 远程"; "remote.settings.resolve_home_path" = "解析主目录路径"; +"terminal.tab.accessibility.active" = "活跃"; +"terminal.tab.accessibility.running" = "运行中"; +"terminal.tab.accessibility.hint" = "双击以切换到此终端"; +"terminal.tab.kill" = "关闭终端"; +"terminal.tab.kill_confirmation.title" = "关闭终端?"; +"terminal.tab.kill_confirmation.cancel" = "取消"; +"terminal.tab.kill_confirmation.kill" = "关闭"; +"terminal.tab.kill_confirmation.message" = "此终端有正在运行的进程。您确定要关闭它吗?"; \ No newline at end of file diff --git a/CodeApp/Views/TerminalTabBar.swift b/CodeApp/Views/TerminalTabBar.swift index 118e462cb..a8bc960c5 100644 --- a/CodeApp/Views/TerminalTabBar.swift +++ b/CodeApp/Views/TerminalTabBar.swift @@ -60,11 +60,11 @@ struct TerminalTabRow: View { private var accessibilityLabel: String { let activeLabel = NSLocalizedString( - "Active", + "terminal.tab.accessibility.active", comment: "Accessibility label for active terminal" ) let runningLabel = NSLocalizedString( - "Running", + "terminal.tab.accessibility.running", comment: "Accessibility label for running terminal" ) var parts = [terminal.name] @@ -110,33 +110,33 @@ struct TerminalTabRow: View { .accessibilityAddTraits(isActive ? [.isSelected, .isButton] : [.isButton]) .accessibilityHint( NSLocalizedString( - "Double tap to switch to this terminal", + "terminal.tab.accessibility.hint", comment: "Accessibility hint for terminal tab") ) .contextMenu { if canClose { - Button(NSLocalizedString("Kill Terminal", comment: ""), role: .destructive) { + Button(role: .destructive) { if isTerminalBusy { showingKillConfirmation = true } else { onClose() } + } label: { + Label("terminal.tab.kill", systemImage: "xmark") } } } .alert( - NSLocalizedString("Kill Terminal?", comment: ""), + "terminal.tab.kill_confirmation.title", isPresented: $showingKillConfirmation ) { - Button(NSLocalizedString("Cancel", comment: ""), role: .cancel) {} - Button(NSLocalizedString("Kill", comment: ""), role: .destructive) { + Button("terminal.tab.kill_confirmation.cancel", role: .cancel) {} + Button("terminal.tab.kill_confirmation.kill", role: .destructive) { onClose() } } message: { Text( - NSLocalizedString( - "This terminal has a running process. Are you sure you want to kill it?", - comment: "")) + "terminal.tab.kill_confirmation.message") } } } From 458d9cdab1ebc424632b82ccecf70bc9dae800f5 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 13:55:17 +0800 Subject: [PATCH 14/33] Reset terminals and editors on remote connection or disconnection --- CodeApp/Containers/RemoteContainer.swift | 7 +- .../FileSystem/WorkSpaceStorage.swift | 18 +++- CodeApp/Managers/MainApp.swift | 98 +++++++++++-------- CodeApp/Managers/TerminalManager.swift | 6 +- 4 files changed, 78 insertions(+), 51 deletions(-) diff --git a/CodeApp/Containers/RemoteContainer.swift b/CodeApp/Containers/RemoteContainer.swift index e521dde82..7dfa764a2 100644 --- a/CodeApp/Containers/RemoteContainer.swift +++ b/CodeApp/Containers/RemoteContainer.swift @@ -176,12 +176,7 @@ struct RemoteContainer: View { continuation.resume(throwing: error) } else { DispatchQueue.main.async { - App.loadRepository(url: hostUrl) - App.notificationManager.showInformationMessage( - "remote.connected") - // Set terminal service provider for the active terminal - App.terminalManager.setTerminalServiceProviderForAll( - App.workSpaceStorage.terminalServiceProvider) + App.loadFolder(url: hostUrl) } continuation.resume(returning: ()) } diff --git a/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift b/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift index 06c923dec..1dd84f8ac 100644 --- a/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift +++ b/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift @@ -24,6 +24,7 @@ class WorkSpaceStorage: ObservableObject { private var directoryMonitor = DirectoryMonitor() private var onDirectoryChangeAction: ((String) -> Void)? = nil private var onTerminalDataAction: ((Data) -> Void)? = nil + private var onRemoteDisconnectAction: (() -> Void)? = nil private var directoryStorage: [String: [(FileItemRepresentable)]] = [:] private var fss: [String: FileSystemProvider] = [:] private var isConnecting = false @@ -228,20 +229,29 @@ class WorkSpaceStorage: ObservableObject { fss[currentScheme!] = nil - let documentDir = getRootDirectory() - self.currentDirectory = FileItemRepresentable( - name: documentDir.lastPathComponent, url: documentDir.absoluteString, isDirectory: true) - self.requestDirectoryUpdateAt(id: documentDir.absoluteString) + onRemoteDisconnectAction?() + + // let documentDir = getRootDirectory() + // self.currentDirectory = FileItemRepresentable( + // name: documentDir.lastPathComponent, url: documentDir.absoluteString, isDirectory: true) + // self.requestDirectoryUpdateAt(id: documentDir.absoluteString) } + /// Assign the callback that fires when a remote server has terminal data incoming func onTerminalData(_ action: @escaping (Data) -> Void) { onTerminalDataAction = action } + /// Assign the callback that fires when files changes are detected in the directory func onDirectoryChange(_ action: @escaping ((String) -> Void)) { onDirectoryChangeAction = action } + /// Assign the callback that fires when a remote server is being disconnected + func onRemoteDisconnect(_ action: @escaping (() -> Void)) { + onRemoteDisconnectAction = action + } + /// Reload the whole directory and invalidate all existing cache func updateDirectory(name: String, url: String) { if url != currentDirectory.url { diff --git a/CodeApp/Managers/MainApp.swift b/CodeApp/Managers/MainApp.swift index 867cdb201..24d74301e 100644 --- a/CodeApp/Managers/MainApp.swift +++ b/CodeApp/Managers/MainApp.swift @@ -273,6 +273,13 @@ class MainApp: ObservableObject { ) } } + workSpaceStorage.onRemoteDisconnect { [weak self] in + guard let self = self else { return } + Task { @MainActor in + let documentDir = getRootDirectory() + self.loadFolder(url: documentDir) + } + } loadRepository(url: rootDir) NotificationCancellable = notificationManager.objectWillChange.sink { [weak self] (_) in @@ -504,7 +511,7 @@ class MainApp: ObservableObject { self.stateManager.showsNewFileSheet.toggle() }, onSelectFolderAsWorkspaceStorage: { url in - self.loadFolder(url: url, resetEditors: true) + self.loadFolder(url: url) }, onSelectFolder: { self.stateManager.showsDirectoryPicker.toggle() @@ -803,7 +810,7 @@ class MainApp: ObservableObject { guard let url = URL(string: workSpaceStorage.currentDirectory.url) else { return } - loadFolder(url: url, resetEditors: false) + loadFolder(url: url, resetEditorsAndTerminals: false) } private func groupStatusEntries(entries: [StatusEntry]) -> ( @@ -944,49 +951,62 @@ class MainApp: ObservableObject { updateGitRepositoryStatus() } - func loadFolder(url: URL, resetEditors: Bool = true) { - let url = url.standardizedFileURL - if workSpaceStorage.remoteConnected && url.isFileURL { - workSpaceStorage.disconnect() - } - - ios_setDirectoryURL(url) - - self.workSpaceStorage.updateDirectory( - name: url.lastPathComponent, url: url.absoluteString) - - loadRepository(url: url) - - if url.isFileURL, + private func saveLocalURLToRecentFolders(url: URL) { + guard url.isFileURL, let newBookmark = try? url.bookmarkData() - { - if var bookmarks = UserDefaults.standard.value(forKey: "recentFolder") as? [Data] { - bookmarks = bookmarks.filter { - var isStale = false - guard - let newURL = try? URL( - resolvingBookmarkData: $0, bookmarkDataIsStale: &isStale) - else { - return false - } - // We do not have a stable identity of a url due to sandboxing, compare lastPathComponent instead - return (newURL.lastPathComponent != url.lastPathComponent && !isStale) - } - bookmarks = [newBookmark] + bookmarks - if bookmarks.count > 5 { - bookmarks.removeLast() + else { + return + } + if var bookmarks = UserDefaults.standard.value(forKey: "recentFolder") as? [Data] { + bookmarks = bookmarks.filter { + var isStale = false + guard + let newURL = try? URL( + resolvingBookmarkData: $0, bookmarkDataIsStale: &isStale) + else { + return false } - UserDefaults.standard.setValue(bookmarks, forKey: "recentFolder") - } else { - UserDefaults.standard.setValue([newBookmark], forKey: "recentFolder") + // We do not have a stable identity of a url due to sandboxing, compare lastPathComponent instead + return (newURL.lastPathComponent != url.lastPathComponent && !isStale) } + bookmarks = [newBookmark] + bookmarks + if bookmarks.count > 5 { + bookmarks.removeLast() + } + UserDefaults.standard.setValue(bookmarks, forKey: "recentFolder") + } else { + UserDefaults.standard.setValue([newBookmark], forKey: "recentFolder") } - if resetEditors { - DispatchQueue.main.async { - self.closeAllEditors() - self.terminalManager.resetAndSetNewRootDirectory(url: url) + } + + /// Set the specified url as the root directory of the working space. The url can either be a local path or a remote path like sftp://xxxxx + @MainActor + func loadFolder(url: URL, resetEditorsAndTerminals: Bool = true) { + if resetEditorsAndTerminals { + self.closeAllEditors() + self.terminalManager.resetAndSetNewRootDirectory(url: url) + } + + let url = url.standardizedFileURL + if url.isFileURL { + // Local urls + ios_setDirectoryURL(url) + if workSpaceStorage.remoteConnected && url.isFileURL { + workSpaceStorage.disconnect() } + self.workSpaceStorage.updateDirectory( + name: url.lastPathComponent, url: url.absoluteString) + saveLocalURLToRecentFolders(url: url) + } else { + // Remote urls + notificationManager.showInformationMessage( + "remote.connected") + // Set terminal service provider for the active terminal + terminalManager.setTerminalServiceProviderForAll( + workSpaceStorage.terminalServiceProvider) } + + loadRepository(url: url) extensionManager.onWorkSpaceStorageChanged(newUrl: url) } diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index c2553dcbe..13a2a6752 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -248,12 +248,14 @@ class TerminalManager: ObservableObject { } } + /// Close all terminals exepct the first one, and reset that terminal's state func resetAndSetNewRootDirectory(url: URL) { assertMainThread() rootURL = url - for terminal in terminals { - terminal.resetAndSetNewRootDirectory(url: url) + for terminal in terminals.suffix(terminals.count - 1) { + closeTerminal(id: terminal.id) } + terminals.first?.resetAndSetNewRootDirectory(url: url) } /// Sets the terminal service provider on the active terminal only. From eb71d0f5206fede538fbde013192d8bc15f28198 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 13:55:52 +0800 Subject: [PATCH 15/33] Remove commented-out code in disconnect method for clarity --- CodeApp/Managers/FileSystem/WorkSpaceStorage.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift b/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift index 1dd84f8ac..6273f77ac 100644 --- a/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift +++ b/CodeApp/Managers/FileSystem/WorkSpaceStorage.swift @@ -230,11 +230,6 @@ class WorkSpaceStorage: ObservableObject { fss[currentScheme!] = nil onRemoteDisconnectAction?() - - // let documentDir = getRootDirectory() - // self.currentDirectory = FileItemRepresentable( - // name: documentDir.lastPathComponent, url: documentDir.absoluteString, isDirectory: true) - // self.requestDirectoryUpdateAt(id: documentDir.absoluteString) } /// Assign the callback that fires when a remote server has terminal data incoming From 47afe0e941406d4964bd95aeedf284210140c3e8 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 14:00:26 +0800 Subject: [PATCH 16/33] Restrict terminal creation when a remote terminal is active and update toolbar button visibility --- CodeApp/Managers/TerminalManager.swift | 2 +- Extensions/TerminalService/TerminalExtension.swift | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 13a2a6752..129c8f3a6 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -282,7 +282,7 @@ class TerminalManager: ObservableObject { } var canCreateNewTerminal: Bool { - terminals.count < TerminalManager.maxTerminals + terminals.count < TerminalManager.maxTerminals && remoteTerminalId == nil } private func setActiveTerminalId(_ id: UUID?) { diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index 8a7f4b031..f8dd19954 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -23,13 +23,14 @@ private struct ToolbarView: View { var body: some View { HStack(spacing: 12) { - Button(action: { - App.terminalManager.createTerminal() - }) { - Image(systemName: "plus") + if App.terminalManager.canCreateNewTerminal { + Button(action: { + App.terminalManager.createTerminal() + }) { + Image(systemName: "plus") + } + .help("New Terminal") } - .disabled(!App.terminalManager.canCreateNewTerminal) - .help("New Terminal") Button( action: { From 9638980bb3dc985a03bb7d2d1cc2a9d8e230c020 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 14:57:36 +0800 Subject: [PATCH 17/33] Add modifier states management to multi-terminal and sync with keyboard toolbar --- CodeApp/Managers/TerminalInstance.swift | 30 ++++++++++++++++++ CodeApp/Views/TerminalKeyboardToolbar.swift | 31 ++++++++++++++----- Dependencies/terminal.bundle/index.html | 11 +++++++ .../TerminalService/TerminalExtension.swift | 2 +- 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 62db1ae13..2e07e8472 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -564,6 +564,15 @@ extension TerminalInstance { } } +struct ModifierStates: Codable { + var controlActive: Bool + var controlLocked: Bool + var controlGeneration: Int + var altActive: Bool + var altLocked: Bool + var altGeneration: Int +} + // Keyboard toolbar methods extension TerminalInstance { @@ -591,6 +600,27 @@ extension TerminalInstance { func setAltLocked(_ locked: Bool) { executeScript("setAltLocked(\(locked))") } + + /// Asynchronously obtains all modifier states from JavaScript in a single call + func getModifierStates() async -> ModifierStates { + guard + let dict = try? await webView.evaluateJavaScript("getModifierStates()") + as? [String: Any], + let jsonData = try? JSONSerialization.data(withJSONObject: dict), + let states = try? JSONDecoder().decode(ModifierStates.self, from: jsonData) + else { + return ModifierStates( + controlActive: false, + controlLocked: false, + controlGeneration: 0, + altActive: false, + altLocked: false, + altGeneration: 0 + ) + } + + return states + } } extension Notification.Name { diff --git a/CodeApp/Views/TerminalKeyboardToolbar.swift b/CodeApp/Views/TerminalKeyboardToolbar.swift index 6237dc29e..ef4e21d40 100644 --- a/CodeApp/Views/TerminalKeyboardToolbar.swift +++ b/CodeApp/Views/TerminalKeyboardToolbar.swift @@ -21,13 +21,7 @@ struct TerminalKeyboardToolBar: View { @State var altLastTapTime: Date? @State var altGeneration = 0 - // Optional terminal ID - if nil, uses active terminal - var terminalId: UUID? - private var terminal: TerminalInstance? { - if let id = terminalId { - return App.terminalManager.terminals.first { $0.id == id } - } return App.terminalManager.activeTerminal } @@ -116,6 +110,22 @@ struct TerminalKeyboardToolBar: View { resetUnlockedModifiers() } + private func syncModifierStatesFromTerminal() { + guard let terminal = terminal else { return } + Task { + let states = await terminal.getModifierStates() + + await MainActor.run { + controlActive = states.controlActive + controlLocked = states.controlLocked + altActive = states.altActive + altLocked = states.altLocked + controlGeneration = states.controlGeneration + altGeneration = states.altGeneration + } + } + } + var body: some View { HStack(spacing: horizontalSizeClass == .compact ? 8 : 14) { Group { @@ -277,6 +287,13 @@ struct TerminalKeyboardToolBar: View { { altActive = false } - }) + } + ) + .onChange(of: App.terminalManager.activeTerminalId) { _ in + syncModifierStatesFromTerminal() + } + .onAppear { + syncModifierStatesFromTerminal() + } } } diff --git a/Dependencies/terminal.bundle/index.html b/Dependencies/terminal.bundle/index.html index 7dfd65bef..f9482692e 100644 --- a/Dependencies/terminal.bundle/index.html +++ b/Dependencies/terminal.bundle/index.html @@ -179,6 +179,17 @@ altLocked = locked; } + function getModifierStates() { + return { + controlActive: controlActive, + controlLocked: controlLocked, + controlGeneration: controlGeneration, + altActive: altActive, + altLocked: altLocked, + altGeneration: altGeneration + }; + } + function shouldApplyModifierToCsi(final, params) { if (final >= "A" && final <= "D") { return true; diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index f8dd19954..575fd724c 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -51,7 +51,7 @@ private struct _TerminalView: UIViewRepresentable { private func injectBarButtons(webView: WebViewBase) { let toolbar = UIHostingController( - rootView: TerminalKeyboardToolBar(terminalId: terminal.id).environmentObject(App)) + rootView: TerminalKeyboardToolBar().environmentObject(App)) toolbar.view.frame = CGRect( x: 0, y: 0, width: (webView.bounds.width), height: 40) From 3dd2cf5ca9411398254dd0c49ff1844b86cb81fa Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:00:33 +0800 Subject: [PATCH 18/33] Fix async handling for terminal executor retrieval in local execution --- Extensions/LocalExecution/LocalExecutionExtension.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Extensions/LocalExecution/LocalExecutionExtension.swift b/Extensions/LocalExecution/LocalExecutionExtension.swift index 9ee0f184c..d21ad2fa6 100644 --- a/Extensions/LocalExecution/LocalExecutionExtension.swift +++ b/Extensions/LocalExecution/LocalExecutionExtension.swift @@ -49,15 +49,15 @@ class LocalExecutionExtension: CodeAppExtension { return } - guard let executor = activeTerminal.executor else { + guard let executor = await activeTerminal.executor else { app.notificationManager.showErrorMessage( - "Cannot run: terminal '\(activeTerminal.name)' has no executor.") + "Cannot run: terminal '\(await activeTerminal.name)' has no executor.") return } guard executor.state == .idle else { app.notificationManager.showWarningMessage( - "Cannot run: terminal '\(activeTerminal.name)' executor is \(executor.state.displayName) (expected idle)." + "Cannot run: terminal '\(await activeTerminal.name)' executor is \(executor.state.displayName) (expected idle)." ) return } From 41a620fb692801e67eddc929fdbba1db8610891d Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:03:05 +0800 Subject: [PATCH 19/33] Remove deprecated terminalInstance property --- CodeApp/Managers/MainApp.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CodeApp/Managers/MainApp.swift b/CodeApp/Managers/MainApp.swift index 24d74301e..13f5e119c 100644 --- a/CodeApp/Managers/MainApp.swift +++ b/CodeApp/Managers/MainApp.swift @@ -197,10 +197,6 @@ class MainApp: ObservableObject { let terminalManager: TerminalManager var monacoInstance: EditorImplementation! = nil - // Backward compatibility: returns the active terminal - var terminalInstance: TerminalInstance! { - terminalManager.activeTerminal - } var editorTypesMonitor: FolderMonitor? = nil let deviceSupportsBiometricAuth: Bool = biometricAuthSupported() let sceneIdentifier = UUID() From 249d270c2c34e0b883e289941e1e1d8e482016cb Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:05:48 +0800 Subject: [PATCH 20/33] Clarify terminal instance creation by disabling remote terminal support --- CodeApp/Managers/TerminalManager.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 129c8f3a6..9f6bc0285 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -91,9 +91,7 @@ class TerminalManager: ObservableObject { private func createTerminalInstance(name: String) -> TerminalInstance { let terminal = TerminalInstance(root: rootURL, options: options, name: name) - if let provider = terminalServiceProvider, terminal.id == remoteTerminalId { - terminal.terminalServiceProvider = provider - } + // We do not support creating remote terminal instances for now return terminal } From 7eb27dd1f8c7f3ef61f77dde5d40383e1d275ca8 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:13:21 +0800 Subject: [PATCH 21/33] Refactor terminal service provider assignment to target only the active terminal --- CodeApp/Managers/MainApp.swift | 2 +- CodeApp/Managers/TerminalManager.swift | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/CodeApp/Managers/MainApp.swift b/CodeApp/Managers/MainApp.swift index 13f5e119c..242434c5d 100644 --- a/CodeApp/Managers/MainApp.swift +++ b/CodeApp/Managers/MainApp.swift @@ -998,7 +998,7 @@ class MainApp: ObservableObject { notificationManager.showInformationMessage( "remote.connected") // Set terminal service provider for the active terminal - terminalManager.setTerminalServiceProviderForAll( + terminalManager.setTerminalServiceProviderForActiveTerminal( workSpaceStorage.terminalServiceProvider) } diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 9f6bc0285..b0e0ea4b3 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -257,22 +257,19 @@ class TerminalManager: ObservableObject { } /// Sets the terminal service provider on the active terminal only. - func setTerminalServiceProviderForAll(_ provider: TerminalServiceProvider?) { + func setTerminalServiceProviderForActiveTerminal(_ provider: TerminalServiceProvider?) { assertMainThread() terminalServiceProvider = provider - let targetId = activeTerminalId ?? terminals.first?.id - for terminal in terminals { - terminal.terminalServiceProvider = - terminal.id == targetId ? provider : nil - } + activeTerminal?.terminalServiceProvider = provider + // Track the active terminal as the remote terminal when connecting if let provider = provider { provider.onDisconnect { [weak self] in DispatchQueue.main.async { - self?.setTerminalServiceProviderForAll(nil) + self?.setTerminalServiceProviderForActiveTerminal(nil) } } - remoteTerminalId = targetId + remoteTerminalId = activeTerminal?.id } else { remoteTerminalId = nil } From cd9abc0a7cf1cac611cd97794d82d50bc8bf8723 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:17:17 +0800 Subject: [PATCH 22/33] Update accessibility hints for terminal tab in multiple languages --- CodeApp/Localization/de.lproj/Localizable.strings | 2 +- CodeApp/Localization/en.lproj/Localizable.strings | 2 +- CodeApp/Localization/ja.lproj/Localizable.strings | 2 +- CodeApp/Localization/ko.lproj/Localizable.strings | 2 +- CodeApp/Localization/ru.lproj/Localizable.strings | 2 +- CodeApp/Localization/zh-Hans.lproj/Localizable.strings | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 51367b0a0..6c26e5692 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -669,7 +669,7 @@ "terminal.tab.accessibility.active" = "Aktiv"; "terminal.tab.accessibility.running" = "Läuft"; -"terminal.tab.accessibility.hint" = "Doppeltippen zum Wechseln zu diesem Terminal"; +"terminal.tab.accessibility.hint" = "Tippen, um zu diesem Terminal zu wechseln"; "terminal.tab.kill" = "Terminal beenden"; "terminal.tab.kill_confirmation.title" = "Terminal beenden?"; "terminal.tab.kill_confirmation.cancel" = "Abbrechen"; diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index 35d5c449e..2a0cd5f16 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -563,7 +563,7 @@ are licensed under [BSD-3-Clause License](https://en.wikipedia.org/wiki/BSD_lice "remote.settings.resolve_home_path" = "Resolve Home Path"; "terminal.tab.accessibility.active" = "Active"; "terminal.tab.accessibility.running" = "Running"; -"terminal.tab.accessibility.hint" = "Double tap to switch to this terminal"; +"terminal.tab.accessibility.hint" = "Tap to switch to this terminal"; "terminal.tab.kill" = "Kill Terminal"; "terminal.tab.kill_confirmation.title" = "Kill Terminal?"; "terminal.tab.kill_confirmation.cancel" = "Cancel"; diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index 800351921..ca657b5ea 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -669,7 +669,7 @@ "terminal.tab.accessibility.active" = "アクティブ"; "terminal.tab.accessibility.running" = "実行中"; -"terminal.tab.accessibility.hint" = "ダブルタップしてこのターミナルに切り替える"; +"terminal.tab.accessibility.hint" = "タップしてこのターミナルに切り替える"; "terminal.tab.kill" = "ターミナルを閉じる"; "terminal.tab.kill_confirmation.title" = "ターミナルを閉じますか?"; "terminal.tab.kill_confirmation.cancel" = "キャンセル"; diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index 7ae22c8c0..3457ef737 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -668,7 +668,7 @@ "terminal.tab.accessibility.active" = "활성"; "terminal.tab.accessibility.running" = "실행 중"; -"terminal.tab.accessibility.hint" = "이 터미널로 전환하려면 두 번 탭하세요"; +"terminal.tab.accessibility.hint" = "이 터미널로 전환하려면 탭하세요"; "terminal.tab.kill" = "터미널 닫기"; "terminal.tab.kill_confirmation.title" = "터미널을 닫으시겠습니까?"; "terminal.tab.kill_confirmation.cancel" = "취소"; diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index 504a2a45e..78653a20a 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -705,7 +705,7 @@ "remote.settings.resolve_home_path" = "Открывать домашний каталог"; "terminal.tab.accessibility.active" = "Активна"; "terminal.tab.accessibility.running" = "Выполняется"; -"terminal.tab.accessibility.hint" = "Дважды коснитесь, чтобы переключиться на этот терминал"; +"terminal.tab.accessibility.hint" = "Нажмите, чтобы переключиться на этот терминал"; "terminal.tab.kill" = "Закрыть терминал"; "terminal.tab.kill_confirmation.title" = "Закрыть терминал?"; "terminal.tab.kill_confirmation.cancel" = "Отмена"; diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index 3091f5e4f..e2247bf16 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -658,7 +658,7 @@ "remote.settings.resolve_home_path" = "解析主目录路径"; "terminal.tab.accessibility.active" = "活跃"; "terminal.tab.accessibility.running" = "运行中"; -"terminal.tab.accessibility.hint" = "双击以切换到此终端"; +"terminal.tab.accessibility.hint" = "点按以切换到此终端"; "terminal.tab.kill" = "关闭终端"; "terminal.tab.kill_confirmation.title" = "关闭终端?"; "terminal.tab.kill_confirmation.cancel" = "取消"; From 4f2bc8514bc834e55b5f409923115071724116f8 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:19:22 +0800 Subject: [PATCH 23/33] Fix remoteTerminal property to return nil when no remote terminal is set --- CodeApp/Managers/TerminalManager.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index b0e0ea4b3..36a71d945 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -70,8 +70,9 @@ class TerminalManager: ObservableObject { var remoteTerminal: TerminalInstance? { if let id = remoteTerminalId { return terminals.first { $0.id == id } + } else { + return nil } - return terminals.first { $0.terminalServiceProvider != nil } } init(rootURL: URL, options: TerminalOptions) { From e5e4e3b9628b54ef0ea34398601a9342cf5abdcb Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:21:50 +0800 Subject: [PATCH 24/33] Add canReset property to TerminalManager and conditionally enable reset button in ToolbarView --- CodeApp/Managers/TerminalManager.swift | 4 ++++ .../TerminalService/TerminalExtension.swift | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 36a71d945..3ba693edd 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -281,6 +281,10 @@ class TerminalManager: ObservableObject { terminals.count < TerminalManager.maxTerminals && remoteTerminalId == nil } + var canReset: Bool { + terminalServiceProvider == nil + } + private func setActiveTerminalId(_ id: UUID?) { activeTerminalId = id syncRemoteTerminalId() diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index 575fd724c..d0e48839e 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -32,14 +32,16 @@ private struct ToolbarView: View { .help("New Terminal") } - Button( - action: { - App.terminalManager.activeTerminal?.reset() - }, - label: { - Image(systemName: "trash") - } - ).keyboardShortcut("k", modifiers: [.command]) + if App.terminalManager.canReset { + Button( + action: { + App.terminalManager.activeTerminal?.reset() + }, + label: { + Image(systemName: "trash") + } + ).keyboardShortcut("k", modifiers: [.command]) + } } } } From 42ab50dcc094fc16552a4822b5e342747166c88c Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:31:07 +0800 Subject: [PATCH 25/33] Update localization files for version 1.12.0: correct release date and add changelog entries for multi-terminal support and key modifiers --- .../Localization/de.lproj/Localizable.strings | 17 ++++++++++++----- .../Localization/en.lproj/Localizable.strings | 7 ++++++- .../Localization/ja.lproj/Localizable.strings | 17 ++++++++++++----- .../Localization/ko.lproj/Localizable.strings | 9 +++++++-- .../Localization/ru.lproj/Localizable.strings | 9 +++++++-- .../zh-Hans.lproj/Localizable.strings | 17 ++++++++++++----- 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 6c26e5692..088285699 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (Januar 2026)** +##### **v1.12.0 (Februar 2026)** #### Start [Neue Datei](https://thebaselab.com/code/newfile) [Datei öffnen](https://thebaselab.com/code/openfile) @@ -22,7 +22,12 @@ "; "Changelog.message" = -"### 1.11.0 (Januar 2026) +"### 1.12.0 (Feburary 2026) +- Unterstützung für mehrere Terminals +- Unterstützung für Terminal‑Modifikatortasten +- Besonderer Dank an @ThalesMMS für den Beitrag + +### 1.11.0 (Januar 2026) - Liquid Glass-Benutzeroberfläche übernommen ### 1.10.4 (September 2025) @@ -226,13 +231,15 @@ --- -### v1.2.3 (April 2021) +### 1.12.0 (Februar 2026) +- Unterstützung für mehrere Terminals +- Unterstützung für Terminal‑Modifikatortasten +- Besonderer Dank an @ThalesMMS für den Beitrag + - Editor - 6 Additional Color Themes - Read-only mode - - Built-in types for Node.js - Support for @types definitions -- Explorer - Multi-file searching - Python Runtime - Built-in Matplotlib, Pandas diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index 2a0cd5f16..326011af2 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (January 2026)** +##### **v1.12.0 (February 2026)** #### Start [New file](https://thebaselab.com/code/newfile) [Open file](https://thebaselab.com/code/openfile) @@ -23,6 +23,11 @@ "Changelog.message" = " +### 1.12.0 (Feburary 2026) +- Support multi-terminal +- Support terminal key modifiers +- Special thanks to @ThalesMMS for contribution + ### 1.11.0 (January 2026) - Adopt Liquid Glass UI diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index ca657b5ea..2ced1ff36 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (2026 年 1 月)** +##### **v1.12.0 (2026 年 2 月)** #### 開始 [新しいファイル](https://thebaselab.com/code/newfile) [ファイルを開く](https://thebaselab.com/code/openfile) @@ -22,7 +22,12 @@ "; "Changelog.message" = -"### 1.11.0 (2026 年 1 月) +"### 1.12.0 (Feburary 2026) +- マルチターミナルに対応 +- ターミナルの修飾キーに対応 +- @ThalesMMS の貢献に特別感謝 + +### 1.11.0 (2026 年 1 月) - Liquid Glass UI の採用 ### 1.10.4 (2025 年 9 月) @@ -227,13 +232,15 @@ --- -### v1.2.3 (2021年 4月) +### 1.12.0 (2026年2月) +- マルチターミナルに対応 +- ターミナルの修飾キーに対応 +- @ThalesMMS の貢献に特別感謝 + - エディター - 6 つの追加カラー テーマ - 読み取り専用モード - - Node.js の組み込み型 - @types 定義のサポート -- エクスプローラー - 複数ファイル検索 - Python ランタイム - 組み込みの Matplotlib、Pandas diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index 3457ef737..12380b65b 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (2026년 1월)** +##### **v1.12.0 (2026년 2월)** #### 시작 [새 파일...](https://thebaselab.com/code/newfile) [파일 열기...](https://thebaselab.com/code/openfile) @@ -22,7 +22,12 @@ "; "Changelog.message" = -"### 1.11.0 (2026년 1월) +"### 1.12.0 (Feburary 2026) +- 멀티 터미널 지원 +- 터미널 키 모디파이어 지원 +- 기여해 주신 @ThalesMMS님께 특별한 감사 + +### 1.11.0 (2026년 1월) - Liquid Glass UI 채택 ### 1.10.4 (2025년 9월) diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index 78653a20a..8902753f5 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (Январь 2026)** +##### **v1.12.0 (Февраль 2026)** #### Начало [Новый файл](https://thebaselab.com/code/newfile) [Открыть файл](https://thebaselab.com/code/openfile) @@ -22,7 +22,12 @@ "; "Changelog.message" = -"### 1.11.0 (Январь 2026) +"### 1.12.0 (Feburary 2026) +- Поддержка нескольких терминалов +- Поддержка клавиш-модификаторов терминала +- Особая благодарность @ThalesMMS за вклад + +### 1.11.0 (Январь 2026) - Принята Liquid Glass UI ### 1.10.4 (Сентябрь 2025) diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index e2247bf16..150fac851 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Welcome Message" = "# Code App -##### **v1.12.0 (2026 年 1 月)** +##### **v1.12.0 (2026 年 2 月)** #### 开始 [新文件](https://thebaselab.com/code/newfile) [打开文件](https://thebaselab.com/code/openfile) @@ -22,7 +22,12 @@ "; "Changelog.message" = -"### 1.11.0 (2026 年 1 月) +"### 1.12.0 (Feburary 2026) +- 支持多终端 +- 支持终端修饰键 +- 特别感谢 @ThalesMMS 的贡献 + +### 1.11.0 (2026 年 1 月) - 采用 Liquid Glass 用户界面 ### 1.10.4 (2025 年 9 月) @@ -226,13 +231,15 @@ --- -### v1.2.3 (April 2021) +### 1.12.0 (2026年2月) +- 支持多终端 +- 支持终端修饰键 +- 特别感谢 @ThalesMMS 的贡献 + - 编辑器 - 6 个颜色主题 - 只读模式 - - Node.js 的内置类型 - 支持 @types 定义 -- 资源管理器 - 多文件搜索 - Python - 内置 Matplotlib,Pandas From 332d7ca325070d15c85ee95e65c9030cdbd91a96 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:42:53 +0800 Subject: [PATCH 26/33] Update macOS version for CI workflows to macOS-26 --- .github/workflows/build.yml | 2 +- .github/workflows/production.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a74395d3..cf0be474c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ concurrency: jobs: deploy: name: Deploying to TestFlight - runs-on: macOS-15 + runs-on: macOS-26 steps: - name: Checkout repository diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index 6d17294dc..2bb422742 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -8,7 +8,7 @@ concurrency: jobs: deploy: name: Deploying to App Store - runs-on: macOS-15 + runs-on: macOS-26 steps: - name: Checkout repository diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 30fe17da1..4783fc8df 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ on: jobs: Linting: - runs-on: macOS-15 + runs-on: macOS-26 steps: - uses: actions/checkout@v3 - name: Install swift-format From 8698695a16a789a845b6f940c0a43f060302526a Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sat, 7 Feb 2026 15:44:54 +0800 Subject: [PATCH 27/33] Update Xcode path to version 26.2 in CI workflows --- .github/workflows/build.yml | 2 +- .github/workflows/production.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cf0be474c..1b3a260be 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: JUDGE0_KEY: "" JUDGE0_ENDPOINT: "" DISTRIBUTE_EXTERNAL: "true" - XCODE_PATH: "/Applications/Xcode_26.0.app" + XCODE_PATH: "/Applications/Xcode_26.2.app" - name: Upload Artifact uses: actions/upload-artifact@v4 diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index 2bb422742..c309d0424 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -37,4 +37,4 @@ jobs: JUDGE0_KEY: "${{ secrets.JUDGE0_KEY }}" JUDGE0_ENDPOINT: "${{ secrets.JUDGE0_ENDPOINT }}" DISTRIBUTE_EXTERNAL: "false" - XCODE_PATH: "/Applications/Xcode_26.0.app" + XCODE_PATH: "/Applications/Xcode_26.2.app" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4783fc8df..adfaf25b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,4 +17,4 @@ jobs: - name: Unit Tests run: fastlane tests env: - XCODE_PATH: "/Applications/Xcode_26.0.app" + XCODE_PATH: "/Applications/Xcode_26.2.app" From 6273bcf97336a46ad34405d545958b0c62407645 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sun, 15 Feb 2026 12:07:34 +0800 Subject: [PATCH 28/33] feat: fix terminal focus when switching between multi terminal --- CodeApp/Managers/TerminalInstance.swift | 4 ++++ CodeApp/Managers/TerminalManager.swift | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/CodeApp/Managers/TerminalInstance.swift b/CodeApp/Managers/TerminalInstance.swift index 2e07e8472..102308cef 100644 --- a/CodeApp/Managers/TerminalInstance.swift +++ b/CodeApp/Managers/TerminalInstance.swift @@ -55,6 +55,10 @@ class TerminalInstance: NSObject, WKScriptMessageHandler, WKNavigationDelegate, executeScript("document.getElementById('overlay').focus()") } + func focus() { + executeScript("term.focus()") + } + func sendInterrupt() { executeScript("sendInterrupt()") } diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 3ba693edd..0897bb9c5 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -170,6 +170,10 @@ class TerminalManager: ObservableObject { logger.info( "created terminal name: \(terminal.name, privacy: .public) id: \(terminal.id, privacy: .public)" ) + // Introduce delay to allow web view finishes loading before calling focus + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + terminal.focus() + } return terminal } @@ -288,6 +292,7 @@ class TerminalManager: ObservableObject { private func setActiveTerminalId(_ id: UUID?) { activeTerminalId = id syncRemoteTerminalId() + activeTerminal?.focus() } private func syncRemoteTerminalId() { From 8c4b403c225d6af33e144d5f396bd5d9d1968a02 Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sun, 1 Mar 2026 13:02:53 +0800 Subject: [PATCH 29/33] fix: delay terminal fitting to fix terminal glitch --- Extensions/TerminalService/TerminalExtension.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Extensions/TerminalService/TerminalExtension.swift b/Extensions/TerminalService/TerminalExtension.swift index d0e48839e..761422d91 100644 --- a/Extensions/TerminalService/TerminalExtension.swift +++ b/Extensions/TerminalService/TerminalExtension.swift @@ -130,7 +130,10 @@ private struct MultiTerminalView: View { ) .onAppear(perform: { guard let terminal = App.terminalManager.activeTerminal else { return } - fitTerminalIfReady(terminal) + // Allow WKWebView to get the correct frame size before calling fit + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + fitTerminalIfReady(terminal) + } }) .onChange(of: App.terminalManager.activeTerminalId) { _ in guard let terminal = App.terminalManager.activeTerminal else { From 0f7147be9512b538074fd864e943c4f382e1c46a Mon Sep 17 00:00:00 2001 From: Chung Shing Hin Date: Sun, 1 Mar 2026 13:03:14 +0800 Subject: [PATCH 30/33] Update multi terminal icon color --- CodeApp/Views/TerminalTabBar.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CodeApp/Views/TerminalTabBar.swift b/CodeApp/Views/TerminalTabBar.swift index a8bc960c5..7480a0068 100644 --- a/CodeApp/Views/TerminalTabBar.swift +++ b/CodeApp/Views/TerminalTabBar.swift @@ -83,9 +83,7 @@ struct TerminalTabRow: View { // Icon Image(systemName: "terminal") .font(.system(size: TerminalTabBarConstants.iconSize)) - .foregroundColor( - isActive ? Color(id: "list.activeSelectionForeground") : Color(id: "foreground") - ) + .foregroundColor(Color(id: "foreground")) .frame(width: 20, height: 20) Spacer() } From 17f7a87a5e144b54f6115c71e433dbabdd5e9ff9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:32:25 +0000 Subject: [PATCH 31/33] Initial plan From 25243c790b28c1d1c3a4e0f05be993ab161f810c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:43:14 +0000 Subject: [PATCH 32/33] Fix typos: 'Feburary' -> 'February' in changelogs, 'exepct' -> 'except' in comment --- CodeApp/Localization/de.lproj/Localizable.strings | 2 +- CodeApp/Localization/en.lproj/Localizable.strings | 2 +- CodeApp/Localization/ja.lproj/Localizable.strings | 2 +- CodeApp/Localization/ko.lproj/Localizable.strings | 2 +- CodeApp/Localization/ru.lproj/Localizable.strings | 2 +- CodeApp/Localization/zh-Hans.lproj/Localizable.strings | 2 +- CodeApp/Managers/TerminalManager.swift | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CodeApp/Localization/de.lproj/Localizable.strings b/CodeApp/Localization/de.lproj/Localizable.strings index 4b8998d5a..67b45c275 100644 --- a/CodeApp/Localization/de.lproj/Localizable.strings +++ b/CodeApp/Localization/de.lproj/Localizable.strings @@ -22,7 +22,7 @@ "; "Changelog.message" = -"### 1.12.0 (Feburary 2026) +"### 1.12.0 (February 2026) - Unterstützung für mehrere Terminals - Unterstützung für Terminal‑Modifikatortasten - Besonderer Dank an @ThalesMMS für den Beitrag diff --git a/CodeApp/Localization/en.lproj/Localizable.strings b/CodeApp/Localization/en.lproj/Localizable.strings index c3fdde15d..c213d4609 100644 --- a/CodeApp/Localization/en.lproj/Localizable.strings +++ b/CodeApp/Localization/en.lproj/Localizable.strings @@ -23,7 +23,7 @@ "Changelog.message" = " -### 1.12.0 (Feburary 2026) +### 1.12.0 (February 2026) - Support multi-terminal - Support terminal key modifiers - Special thanks to @ThalesMMS for contribution diff --git a/CodeApp/Localization/ja.lproj/Localizable.strings b/CodeApp/Localization/ja.lproj/Localizable.strings index 2e506dafd..d9562c4f8 100644 --- a/CodeApp/Localization/ja.lproj/Localizable.strings +++ b/CodeApp/Localization/ja.lproj/Localizable.strings @@ -22,7 +22,7 @@ "; "Changelog.message" = -"### 1.12.0 (Feburary 2026) +"### 1.12.0 (February 2026) - マルチターミナルに対応 - ターミナルの修飾キーに対応 - @ThalesMMS の貢献に特別感謝 diff --git a/CodeApp/Localization/ko.lproj/Localizable.strings b/CodeApp/Localization/ko.lproj/Localizable.strings index 46a4050ce..549f7dfc0 100644 --- a/CodeApp/Localization/ko.lproj/Localizable.strings +++ b/CodeApp/Localization/ko.lproj/Localizable.strings @@ -22,7 +22,7 @@ "; "Changelog.message" = -"### 1.12.0 (Feburary 2026) +"### 1.12.0 (February 2026) - 멀티 터미널 지원 - 터미널 키 모디파이어 지원 - 기여해 주신 @ThalesMMS님께 특별한 감사 diff --git a/CodeApp/Localization/ru.lproj/Localizable.strings b/CodeApp/Localization/ru.lproj/Localizable.strings index 298a6d160..bd2298493 100644 --- a/CodeApp/Localization/ru.lproj/Localizable.strings +++ b/CodeApp/Localization/ru.lproj/Localizable.strings @@ -22,7 +22,7 @@ "; "Changelog.message" = -"### 1.12.0 (Feburary 2026) +"### 1.12.0 (February 2026) - Поддержка нескольких терминалов - Поддержка клавиш-модификаторов терминала - Особая благодарность @ThalesMMS за вклад diff --git a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings index 93441aacb..efca9c8ae 100644 --- a/CodeApp/Localization/zh-Hans.lproj/Localizable.strings +++ b/CodeApp/Localization/zh-Hans.lproj/Localizable.strings @@ -22,7 +22,7 @@ "; "Changelog.message" = -"### 1.12.0 (Feburary 2026) +"### 1.12.0 (February 2026) - 支持多终端 - 支持终端修饰键 - 特别感谢 @ThalesMMS 的贡献 diff --git a/CodeApp/Managers/TerminalManager.swift b/CodeApp/Managers/TerminalManager.swift index 0897bb9c5..f9c6dbffc 100644 --- a/CodeApp/Managers/TerminalManager.swift +++ b/CodeApp/Managers/TerminalManager.swift @@ -251,7 +251,7 @@ class TerminalManager: ObservableObject { } } - /// Close all terminals exepct the first one, and reset that terminal's state + /// Close all terminals except the first one, and reset that terminal's state func resetAndSetNewRootDirectory(url: URL) { assertMainThread() rootURL = url From 94dfdc17c08d280f74a8be732c56ad2bc2881a7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:44:01 +0000 Subject: [PATCH 33/33] Security: add explicit permissions block to test.yml workflow --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index adfaf25b7..67043a68a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,9 @@ on: - "*" - "!gitbook" +permissions: + contents: read + jobs: Linting: runs-on: macOS-26