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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/release-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ jobs:
/usr/libexec/PlistBuddy \
-c "Print :CFBundleVersion" \
"$app_path/Contents/Info.plist"
for build_key in \
LitheBuildGitRevision \
LitheBuildGitBranch \
LitheBuildGitDirty \
LitheBuildTimestamp; do
/usr/libexec/PlistBuddy \
-c "Print :${build_key}" \
"$app_path/Contents/Info.plist"
done
lipo "$app_path/Contents/MacOS/Lithe" -verify_arch "$LITHE_ARCH"
hdiutil imageinfo "$dmg_path" > /dev/null
test -s "$dmg_path"
Expand Down
12 changes: 12 additions & 0 deletions Resources/zh-Hans.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
"Save the active document" = "保存当前文档";
"Move to the next match in the active editor" = "跳转到当前编辑器中的下一个匹配项";
"Move to the previous match in the active editor" = "跳转到当前编辑器中的上一个匹配项";
"Back" = "后退";
"Navigate to the previous editor location" = "跳转到上一个编辑器位置";
"Forward" = "前进";
"Navigate to the next editor location" = "跳转到下一个编辑器位置";
"Go to Definition" = "跳转到定义";
"Navigate to the declaration of the selected symbol" = "跳转到所选符号的声明";
"Spring Endpoints" = "Spring 接口";
"Show indexed Spring MVC routes" = "显示已索引的 Spring MVC 路由";
"Navigate to a call site of the selected symbol" = "跳转到所选符号的调用位置";
"Navigate to an implementation of the selected symbol" = "跳转到所选符号的实现";
"Find references to the selected symbol" = "查找所选符号的引用";
Expand Down Expand Up @@ -1149,6 +1157,10 @@
"Uninstall" = "卸载";
"Overview" = "概览";
"No Plugins" = "暂无插件";
"More Language Support" = "扩展更多语言";
"%lld languages · %lld enabled" = "%lld 种语言 · 已启用 %lld 个";
"Expanded" = "已展开";
"Collapsed" = "已收起";
"Database" = "数据库连接";
"Enabled" = "已启用";
"Disabled" = "已禁用";
Expand Down
104 changes: 104 additions & 0 deletions Sources/Lithe/Application/Features/NavigationHistoryFeatureModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import Combine
import Foundation

struct EditorNavigationLocation: Hashable, Sendable {
let url: URL
let line: Int
let utf16Column: Int
let isReadOnly: Bool
let displayPath: String?
let virtualProviderID: String?

init(
url: URL,
line: Int,
utf16Column: Int,
isReadOnly: Bool = false,
displayPath: String? = nil,
virtualProviderID: String? = nil
) {
self.url = url.isFileURL ? url.standardizedFileURL : url
self.line = max(0, line)
self.utf16Column = max(0, utf16Column)
self.isReadOnly = isReadOnly
self.displayPath = displayPath
self.virtualProviderID = virtualProviderID
}
}

struct NavigationHistorySnapshot: Equatable, Sendable {
let backLocations: [EditorNavigationLocation]
let forwardLocations: [EditorNavigationLocation]
}

/// Owns bounded editor-location history independently from document tabs.
/// A jump records the live departure location so caret movement since the last
/// navigation is preserved when the user returns.
@MainActor
final class NavigationHistoryFeatureModel: ObservableObject {
@Published private(set) var backLocations: [EditorNavigationLocation] = []
@Published private(set) var forwardLocations: [EditorNavigationLocation] = []

private let maximumEntryCount: Int

init(maximumEntryCount: Int = 100) {
self.maximumEntryCount = max(1, maximumEntryCount)
}

var canNavigateBack: Bool { !backLocations.isEmpty }
var canNavigateForward: Bool { !forwardLocations.isEmpty }

func recordJump(
from departure: EditorNavigationLocation?,
to destination: EditorNavigationLocation
) {
guard let departure, departure != destination else { return }
append(departure, to: &backLocations)
forwardLocations.removeAll()
}

func navigateBack(from current: EditorNavigationLocation?) -> EditorNavigationLocation? {
guard let destination = backLocations.popLast() else { return nil }
if let current, current != destination {
append(current, to: &forwardLocations)
}
return destination
}

func navigateForward(from current: EditorNavigationLocation?) -> EditorNavigationLocation? {
guard let destination = forwardLocations.popLast() else { return nil }
if let current, current != destination {
append(current, to: &backLocations)
}
return destination
}

func reset() {
backLocations.removeAll()
forwardLocations.removeAll()
}

func snapshot() -> NavigationHistorySnapshot {
NavigationHistorySnapshot(
backLocations: backLocations,
forwardLocations: forwardLocations
)
}

func restore(_ snapshot: NavigationHistorySnapshot) {
backLocations = snapshot.backLocations
forwardLocations = snapshot.forwardLocations
}

private func append(
_ location: EditorNavigationLocation,
to locations: inout [EditorNavigationLocation]
) {
if locations.last != location {
locations.append(location)
}
if locations.count > maximumEntryCount {
locations.removeFirst(locations.count - maximumEntryCount)
}
}
}
Loading
Loading