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
44 changes: 44 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,50 @@ jobs:
- name: Install xcbeautify
run: brew install xcbeautify

- name: Clone local tree-sitter packages
run: |
mkdir -p apps/purepoint-macos/LocalPackages
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-css.git apps/purepoint-macos/LocalPackages/tree-sitter-css
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-javascript.git apps/purepoint-macos/LocalPackages/tree-sitter-javascript
git clone --depth 1 https://github.com/tree-sitter-grammars/tree-sitter-lua.git apps/purepoint-macos/LocalPackages/tree-sitter-lua
git clone --depth 1 https://github.com/tree-sitter/tree-sitter-python.git apps/purepoint-macos/LocalPackages/tree-sitter-python
git clone --depth 1 https://github.com/tree-sitter-grammars/tree-sitter-yaml.git apps/purepoint-macos/LocalPackages/tree-sitter-yaml

- name: Prepare local packages for Xcode
run: |
# Xcode 26 ignores the explicit `sources` parameter in local SPM packages,
# so restructure each package to use path-based auto-discovery instead.
for pkg in apps/purepoint-macos/LocalPackages/tree-sitter-*; do
lib=$(sed -n 's/.*name: "\(TreeSitter[^"]*\)".*/\1/p' "$pkg/Package.swift" | head -1)
# Copy public header into src/include/
mkdir -p "$pkg/src/include"
find "$pkg/bindings/swift" -name '*.h' -exec cp {} "$pkg/src/include/" \;
# Copy queries into src/ so resources path works with path: "src"
cp -r "$pkg/queries" "$pkg/src/queries" 2>/dev/null || true
# Remove non-C/H files from src/ (JSON metadata confuses SPM)
find "$pkg/src" -type f -not -name '*.c' -not -name '*.h' -not -name '*.scm' -delete
find "$pkg/src" -type d -empty -delete 2>/dev/null || true
# Rewrite Package.swift: use path "src" so SPM auto-discovers all .c files
cat > "$pkg/Package.swift" << PKGEOF
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "$lib",
products: [.library(name: "$lib", targets: ["$lib"])],
targets: [
.target(
name: "$lib",
path: "src",
resources: [.copy("queries")],
publicHeadersPath: "include",
cSettings: [.headerSearchPath(".")]
),
],
cLanguageStandard: .c11
)
PKGEOF
done

- name: Build
run: |
xcodebuild build \
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,8 @@ build/
.ppg/swarms/
.ppg/conductor-context.md

# Tree-sitter local overrides (cloned per-developer, not project source)
apps/purepoint-macos/LocalPackages/

# PurePoint runtime
.pu/
352 changes: 352 additions & 0 deletions apps/purepoint-macos/purepoint-macos.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 84 additions & 5 deletions apps/purepoint-macos/purepoint-macos/Models/EditorTab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum EditorLanguage: String, CaseIterable {
case rust
case javascript
case typescript
case tsx
case python
case markdown
case json
Expand All @@ -23,38 +24,116 @@ enum EditorLanguage: String, CaseIterable {
case html
case css
case shell
case c
case cpp
case go
case ruby
case php
case java
case csharp
case scala
case haskell
case lua
case xml
case plaintext

static func detect(from filename: String) -> EditorLanguage {
let name = (filename as NSString).lastPathComponent.lowercased()

if let match = knownFilenames[name] { return match }

let ext = (filename as NSString).pathExtension.lowercased()
switch ext {
case "swift": return .swift
case "rs": return .rust
case "js", "jsx", "mjs", "cjs": return .javascript
case "ts", "tsx", "mts", "cts": return .typescript
case "ts", "mts", "cts": return .typescript
case "tsx": return .tsx
case "py", "pyi": return .python
case "md", "markdown": return .markdown
case "json": return .json
case "md", "markdown", "mdx": return .markdown
case "json", "jsonc", "json5": return .json
case "yml", "yaml": return .yaml
case "toml": return .toml
case "html", "htm": return .html
case "css", "scss", "sass", "less": return .css
case "sh", "bash", "zsh", "fish": return .shell
case "c", "h": return .c
case "cpp", "cc", "cxx", "hpp", "hxx", "hh": return .cpp
case "go": return .go
case "rb", "rake", "gemspec": return .ruby
case "php": return .php
case "java": return .java
case "cs": return .csharp
case "scala", "sc": return .scala
case "hs", "lhs": return .haskell
case "lua": return .lua
case "xml", "xsl", "xslt", "svg", "plist": return .xml
case "graphql", "gql": return .plaintext
case "dockerfile": return .shell
default: return .plaintext
}
}

private static let knownFilenames: [String: EditorLanguage] = [
// Lock files
"cargo.lock": .toml,
"package.resolved": .json,
"composer.lock": .json,
// Ruby conventions
"gemfile": .ruby,
"rakefile": .ruby,
"podfile": .ruby,
"vagrantfile": .ruby,
"fastfile": .ruby,
"brewfile": .ruby,
"dangerfile": .ruby,
"guardfile": .ruby,
// Build/task files
"makefile": .shell,
"gnumakefile": .shell,
"dockerfile": .shell,
"justfile": .shell,
"procfile": .shell,
// Ignore files
".gitignore": .shell,
".dockerignore": .shell,
".npmignore": .shell,
".hgignore": .shell,
// Config dotfiles
".editorconfig": .plaintext,
".gitconfig": .plaintext,
".gitmodules": .plaintext,
// Shell dotfiles
".zshrc": .shell,
".bashrc": .shell,
".bash_profile": .shell,
".profile": .shell,
".zprofile": .shell,
".zshenv": .shell,
".bash_aliases": .shell,
".bash_logout": .shell,
]

var icon: String {
switch self {
case .swift: return "swift"
case .rust: return "gearshape.2"
case .javascript, .typescript: return "curlybraces"
case .javascript, .typescript, .tsx: return "curlybraces"
case .python: return "chevron.left.forwardslash.chevron.right"
case .markdown: return "doc.text"
case .json, .yaml, .toml: return "doc.badge.gearshape"
case .html: return "globe"
case .html, .xml: return "globe"
case .css: return "paintbrush"
case .shell: return "terminal"
case .c, .cpp: return "c.square"
case .go: return "arrow.right.arrow.left"
case .ruby: return "diamond"
case .php: return "server.rack"
case .java: return "cup.and.saucer"
case .csharp: return "number"
case .scala: return "s.square"
case .haskell: return "function"
case .lua: return "moon"
case .plaintext: return "doc"
}
}
Expand Down
Loading
Loading