Skip to content
Open
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
3 changes: 3 additions & 0 deletions CodeEdit/Features/Editor/Views/CodeFileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
var lineHeightMultiple
@AppSettings(\.textEditing.wrapLinesToEditorWidth)
var wrapLinesToEditorWidth
@AppSettings(\.textEditing.wrappedLineIndent)
var wrappedLineIndent
@AppSettings(\.textEditing.overscroll)
var overscroll
@AppSettings(\.textEditing.font)
Expand Down Expand Up @@ -125,6 +127,7 @@
lineHeightMultiple: lineHeightMultiple,
letterSpacing: letterSpacing,
wrapLines: wrapLinesToEditorWidth,
wrappedLineIndent: wrappedLineIndent,

Check failure on line 130 in CodeEdit/Features/Editor/Views/CodeFileView.swift

View workflow job for this annotation

GitHub Actions / Testing CodeEdit / Testing CodeEdit

extra argument 'wrappedLineIndent' in call
useSystemCursor: useSystemCursor,
tabWidth: defaultTabWidth,
bracketPairEmphasis: getBracketPairEmphasis()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ extension SettingsData {
"Prefer Indent Using",
"Tab Width",
"Wrap lines to editor width",
"Indent wrapped lines",
"Editor Overscroll",
"Font",
"Font Size",
Expand Down Expand Up @@ -60,6 +61,11 @@ extension SettingsData {
/// A flag indicating whether to wrap lines to editor width
var wrapLinesToEditorWidth: Bool = true

/// Spaces to indent continuation lines when line wrapping
/// is on (e.g. 4 or 12). See:
/// https://github.com/CodeEditApp/CodeEditTextView/issues/18
var wrappedLineIndent: Int = 4

/// The percentage of overscroll to apply to the text view
var overscroll: OverscrollOption = .medium

Comment on lines +64 to 71
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation comment spans multiple lines but doesn't follow the standard Swift documentation format. In the codebase, similar properties use single-line comments (see lines 45-46, 52-53, 55-56, 58-59, 61-62, 69-70). Consider condensing to a single-line comment for consistency, or if the reference is important, format it as a proper multi-line doc comment with proper indentation on continuation lines.

Suggested change
/// Spaces to indent continuation lines when line wrapping
/// is on (e.g. 4 or 12). See:
/// https://github.com/CodeEditApp/CodeEditTextView/issues/18
var wrappedLineIndent: Int = 4
/// The percentage of overscroll to apply to the text view
var overscroll: OverscrollOption = .medium
/// Spaces to indent continuation lines when line wrapping is on (e.g. 4 or 12); see https://github.com/CodeEditApp/CodeEditTextView/issues/18
var wrappedLineIndent: Int = 4
/// The percentage of overscroll to apply to the text view
var overscroll: OverscrollOption = .medium
var overscroll: OverscrollOption = .medium

Copilot uses AI. Check for mistakes.
Expand Down Expand Up @@ -122,6 +128,10 @@ extension SettingsData {
Bool.self,
forKey: .wrapLinesToEditorWidth
) ?? true
self.wrappedLineIndent = try container.decodeIfPresent(
Int.self,
forKey: .wrappedLineIndent
) ?? 4
Comment on lines +131 to +134
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no validation to clamp values outside the expected range (0-24) when decoding from JSON or when the property is set programmatically. While the UI Stepper enforces this range, values set directly (e.g., via JSON manipulation or programmatic access) could be invalid. Consider adding validation in the decoder or using a property wrapper with a didSet observer to clamp values to the valid range, similar to how other settings with constraints are handled elsewhere in the codebase.

Suggested change
self.wrappedLineIndent = try container.decodeIfPresent(
Int.self,
forKey: .wrappedLineIndent
) ?? 4
let decodedWrappedLineIndent = try container.decodeIfPresent(
Int.self,
forKey: .wrappedLineIndent
) ?? 4
self.wrappedLineIndent = min(max(decodedWrappedLineIndent, 0), 24)

Copilot uses AI. Check for mistakes.
self.overscroll = try container.decodeIfPresent(
OverscrollOption.self,
forKey: .overscroll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct TextEditingSettingsView: View {
indentOption
defaultTabWidth
wrapLinesToEditorWidth
wrappedLineIndent
useSystemCursor
overscroll
}
Expand Down Expand Up @@ -86,6 +87,25 @@ private extension TextEditingSettingsView {
Toggle("Wrap lines to editor width", isOn: $textEditing.wrapLinesToEditorWidth)
}

@ViewBuilder private var wrappedLineIndent: some View {
HStack(alignment: .top) {
Stepper(
"Indent wrapped lines",
value: Binding<Double>(
get: { Double(textEditing.wrappedLineIndent) },
set: { textEditing.wrappedLineIndent = Int($0) }
),
in: 0...24,
step: 1,
format: .number
)
Text("spaces")
.foregroundColor(.secondary)
}
.disabled(!textEditing.wrapLinesToEditorWidth)
.help("Number of spaces to indent continuation lines when line wrapping is on (e.g. like Xcode).")
}

@ViewBuilder private var useSystemCursor: some View {
if #available(macOS 14, *) {
Toggle("Use System Cursor", isOn: $textEditing.useSystemCursor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ extension GitClient {
case "!", "#": // Ignored files or Header
try substringToNextNull(from: &index, output: output) // move the index to the next line.
default:
throw GitClientError.statusInvalidChangeType(output[typeIndex])
// Skip unknown entry types (e.g. future porcelain v2 types or unexpected output)
try substringToNextNull(from: &index, output: output)
Comment on lines 77 to +79
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the change from throwing to silently skipping unknown entry types is reasonable for forward compatibility, there's no test coverage for this behavior. Consider adding a test case that includes an unknown entry type character in the status output to verify that it's properly skipped without affecting the parsing of other entries. This would help prevent regressions and document the expected behavior.

Copilot uses AI. Check for mistakes.
}
}

Expand Down
1 change: 0 additions & 1 deletion CodeEdit/WorkspaceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ struct WorkspaceView: View {
.task {
// Only refresh git data if source control is enabled
guard sourceControlIsEnabled else { return }

do {
try await sourceControlManager.refreshRemotes()
try await sourceControlManager.refreshStashEntries()
Expand Down
61 changes: 61 additions & 0 deletions CodeEditTests/Features/Settings/TextEditingSettingsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// TextEditingSettingsTests.swift
// CodeEditTests
//
// Tests for Text Editing settings, including wrapped line indent (CodeEditTextView #18).
//

import Foundation
import Testing
@testable import CodeEdit

@Suite("Text Editing Settings")
struct TextEditingSettingsTests {

// MARK: - Wrapped line indent (indent wrapped lines - CodeEditTextView #18)

@Test("Default wrapped line indent is 4 spaces")
func defaultWrappedLineIndentIsFour() {
let settings = SettingsData.TextEditingSettings()
#expect(settings.wrappedLineIndent == 4)
}

@Test("Wrapped line indent round-trips through Codable")
func wrappedLineIndentRoundTrips() throws {
var settings = SettingsData.TextEditingSettings()
settings.wrappedLineIndent = 12

let encoded = try JSONEncoder().encode(settings)
let decoded = try JSONDecoder().decode(SettingsData.TextEditingSettings.self, from: encoded)
#expect(decoded.wrappedLineIndent == 12)
}

@Test("Decode with missing wrappedLineIndent uses default 4")
func decodeMissingWrappedLineIndentUsesDefault() throws {
// JSON without wrappedLineIndent key (e.g. existing user preferences)
let json = """
{"wrapLinesToEditorWidth": true}
"""
let data = json.data(using: .utf8)!
// Decode a minimal object; TextEditingSettings init(from:) decodes each key with default
let decoded = try JSONDecoder().decode(SettingsData.TextEditingSettings.self, from: data)
#expect(decoded.wrappedLineIndent == 4)
}

@Test("Wrapped line indent accepts valid range 0–24")
func wrappedLineIndentValidRange() throws {
for value in [0, 4, 8, 12, 24] {
var settings = SettingsData.TextEditingSettings()
settings.wrappedLineIndent = value
let encoded = try JSONEncoder().encode(settings)
let decoded = try JSONDecoder().decode(SettingsData.TextEditingSettings.self, from: encoded)
#expect(decoded.wrappedLineIndent == value)
}
}
Comment on lines +45 to +54
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests validate the range 0-24, but they don't test boundary violations or what happens when invalid values (e.g., -1, 25, 100) are set directly on the property or decoded from JSON. Consider adding tests for these edge cases to ensure the setting handles invalid values gracefully, especially since there's no validation logic in the model to prevent out-of-range values.

Copilot uses AI. Check for mistakes.

@Test("Wrap lines to editor width default is true")
func wrapLinesToEditorWidthDefault() {
let settings = SettingsData.TextEditingSettings()
#expect(settings.wrapLinesToEditorWidth == true)
}
}
Loading