diff --git a/.swiftlint.yml b/.swiftlint.yml
index bce3d69bc..dbb608ab8 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -1,2 +1,3 @@
 disabled_rules:
-  - todo
\ No newline at end of file
+  - todo
+  - trailing_comma
diff --git a/CodeEdit.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 7d8fafa3f..ee206aceb 100644
--- a/CodeEdit.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/CodeEdit.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,15 +1,6 @@
 {
   "object": {
     "pins": [
-      {
-        "package": "CodeEditor",
-        "repositoryURL": "https://github.com/ZeeZide/CodeEditor.git",
-        "state": {
-          "branch": null,
-          "revision": "5856fac22b0a2174dbdea212784567c8c9cd1129",
-          "version": "1.2.0"
-        }
-      },
       {
         "package": "Highlightr",
         "repositoryURL": "https://github.com/raspu/Highlightr",
diff --git a/CodeEdit/ContentView.swift b/CodeEdit/ContentView.swift
deleted file mode 100644
index a6cfe131d..000000000
--- a/CodeEdit/ContentView.swift
+++ /dev/null
@@ -1,216 +0,0 @@
-//
-//  ContentView.swift
-//  CodeEdit
-//
-//  Created by Austin Condiff on 3/10/22.
-//
-
-import SwiftUI
-import WorkspaceClient
-import CodeEditorView
-
-struct WorkspaceView: View {
-    @State private var directoryURL: URL?
-    @State private var workspaceClient: WorkspaceClient?
-    // TODO: Create a ViewModel to hold selectedId, openFileItems,
-    // ... to pass it to subviews as an EnvironmentObject (less boilerplate parameters)
-    @State private var selectedId: WorkspaceClient.FileId?
-    @State private var openFileItems: [WorkspaceClient.FileItem] = []
-    @State private var urlInit = false
-    @State private var showingAlert = false
-    @State private var alertTitle = ""
-    @State private var alertMsg = ""
-
-    var tabBarHeight = 28.0
-    private var path: String = ""
-
-    func closeFileTab(item: WorkspaceClient.FileItem) {
-        guard let idx = openFileItems.firstIndex(of: item) else { return }
-        let closedFileItem = openFileItems.remove(at: idx)
-        guard closedFileItem.id == selectedId else { return }
-
-        if openFileItems.isEmpty {
-            selectedId = nil
-        } else if idx == 0 {
-            selectedId = openFileItems.first?.id
-        } else {
-            selectedId = openFileItems[idx - 1].id
-        }
-    }
-
-    var body: some View {
-        NavigationView {
-            if let workspaceClient = workspaceClient, let directoryURL = directoryURL {
-                sidebar(workspaceClient: workspaceClient, directoryURL: directoryURL)
-                    .frame(minWidth: 250)
-                    .toolbar {
-                        ToolbarItem(placement: .primaryAction) {
-                            Button(action: toggleSidebar) {
-                                Image(systemName: "sidebar.leading").imageScale(.large)
-                            }
-                            .help("Show/Hide Sidebar")
-                        }
-                    }
-                if openFileItems.isEmpty {
-                    Text("Open file from sidebar")
-                } else {
-                    ZStack {
-                        if let selectedId = selectedId {
-                            if let selectedItem = try? workspaceClient.getFileItem(selectedId) {
-                                CodeEditorView(fileURL: selectedItem.url)
-                                    .padding(.top, 31.0)
-                            }
-                        }
-
-                        VStack {
-                            tabBar
-                                .frame(maxHeight: tabBarHeight)
-                                .background(Material.regular)
-
-                            Spacer()
-                        }
-                    }
-                }
-            } else {
-                EmptyView()
-            }
-        }
-        .toolbar {
-            ToolbarItem(placement: .navigation) {
-                Button(
-                    action: {},
-                    label: { Image(systemName: "chevron.left").imageScale(.large) }
-                )
-                .help("Back")
-            }
-            ToolbarItem(placement: .navigation) {
-                Button(
-                    action: {},
-                    label: { Image(systemName: "chevron.right").imageScale(.large) }
-                )
-                .disabled(true)
-                .help("Forward")
-            }
-        }
-        .frame(minWidth: 800, minHeight: 600)
-        .onOpenURL { url in
-            urlInit = true
-            do {
-                self.workspaceClient = try .default(
-                    fileManager: .default,
-                    folderURL: url,
-                    ignoredFilesAndFolders: ignoredFilesAndDirectory
-                )
-                self.directoryURL = url
-            } catch {
-                self.alertTitle = "Unable to Open Workspace"
-                self.alertMsg = error.localizedDescription
-                self.showingAlert = true
-                print(error.localizedDescription)
-            }
-        }
-        .alert(alertTitle, isPresented: $showingAlert, actions: {
-            Button(
-                action: { showingAlert = false },
-                label: { Text("OK") }
-            )
-        }, message: { Text(alertMsg) })
-    }
-
-    var tabBar: some View {
-        VStack(spacing: 0.0) {
-            ScrollView(.horizontal, showsIndicators: false) {
-                ScrollViewReader { value in
-                    HStack(alignment: .center, spacing: 0.0) {
-                        ForEach(openFileItems, id: \.id) { item in
-                            let isActive = selectedId == item.id
-
-                            Button(
-                                action: { selectedId = item.id },
-                                label: {
-                                    HStack(spacing: 0.0) {
-                                        FileTabRow(fileItem: item, isSelected: isActive) {
-                                            withAnimation {
-                                                closeFileTab(item: item)
-                                            }
-                                        }
-
-                                        Divider()
-                                    }
-                                    )
-                                    .frame(height: tabBarHeight)
-                                    .foregroundColor(isActive ? .primary : .gray)
-                                    .background(isActive ? Material.bar : Material.regular)
-                                    .animation(.easeOut(duration: 0.2), value: openFileItems)
-                                }
-                                    .buttonStyle(.plain)
-                                    .id(item.id)
-                                }
-                                }
-                                    .onChange(of: selectedId) { newValue in
-                                        withAnimation {
-                                            value.scrollTo(newValue)
-                                        }
-                                    }
-                                }
-                                }
-
-                                Divider()
-                                    .foregroundColor(.gray)
-                                    .frame(height: 1.0)
-                                }
-                                }
-
-                                func sidebar(
-                                    workspaceClient: WorkspaceClient,
-                                    directoryURL: URL
-                                ) -> some View {
-                                    List {
-                                        Section(header: Text(directoryURL.lastPathComponent)) {
-                                            OutlineGroup(workspaceClient.getFiles(), children: \.children) { item in
-                                                if item.children == nil {
-                                                    Button(
-                                                        action: {
-                                                            withAnimation {
-                                                                if !openFileItems.contains(item) {
-                                                                    openFileItems.append(item)
-                                                                }
-                                                            }
-                                                            selectedId = item.id
-                                                        },
-                                                        label: {
-                                                            Label(
-                                                                item.url.lastPathComponent,
-                                                                systemImage: item.systemImage
-                                                            )
-                                                            .accentColor(.secondary)
-                                                            .font(.callout)
-                                                        }
-                                                    )
-                                                    .buttonStyle(.plain)
-                                                } else {
-                                                    Label(item.url.lastPathComponent, systemImage: item.systemImage)
-                                                        .accentColor(.secondary)
-                                                        .font(.callout)
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
-
-                                private func toggleSidebar() {
-#if os(iOS)
-#else
-                                    NSApp.keyWindow?.firstResponder?.tryToPerform(
-                                        #selector(NSSplitViewController.toggleSidebar(_:)),
-                                        with: nil
-                                    )
-#endif
-                                }
-                                }
-
-                                struct ContentView_Previews: PreviewProvider {
-                                    static var previews: some View {
-                                        WorkspaceView()
-                                    }
-                                }
diff --git a/CodeEdit/Documents/WorkspaceCodeFileView.swift b/CodeEdit/Documents/WorkspaceCodeFileView.swift
index 162fb47e7..254b8af85 100644
--- a/CodeEdit/Documents/WorkspaceCodeFileView.swift
+++ b/CodeEdit/Documents/WorkspaceCodeFileView.swift
@@ -16,6 +16,9 @@ struct WorkspaceCodeFileView: View {
 
     @ViewBuilder var body: some View {
         if let item = workspace.openFileItems.first(where: { file in
+            if file.id == workspace.selectedId {
+                print("Item loaded is: ", file.url)
+            }
             return file.id == workspace.selectedId
         }) {
             if let codeFile = workspace.openedCodeFiles[item] {
diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift
index 309c97ef1..d91f8d38c 100644
--- a/CodeEdit/Documents/WorkspaceDocument.swift
+++ b/CodeEdit/Documents/WorkspaceDocument.swift
@@ -87,7 +87,7 @@ class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate {
                 openedCodeFiles[item] = codeFile
             }
             selectedId = item.id
-
+            Swift.print("Opening file for item: ", item.url)
             self.windowControllers.first?.window?.subtitle = item.url.lastPathComponent
         } catch let err {
             Swift.print(err)
diff --git a/CodeEdit/Quick Open/QuickOpenPreviewView.swift b/CodeEdit/Quick Open/QuickOpenPreviewView.swift
index 79cba2f5a..aff4de883 100644
--- a/CodeEdit/Quick Open/QuickOpenPreviewView.swift	
+++ b/CodeEdit/Quick Open/QuickOpenPreviewView.swift	
@@ -8,7 +8,6 @@
 import SwiftUI
 import WorkspaceClient
 import CodeFile
-import CodeEditor
 
 struct QuickOpenPreviewView: View {
     var item: WorkspaceClient.FileItem
@@ -18,8 +17,12 @@ struct QuickOpenPreviewView: View {
 
     var body: some View {
         VStack {
-            if loaded {
-                ThemedCodeView($content, language: .init(url: item.url), editable: false)
+            if let codeFile = try? CodeFileDocument(
+                for: item.url,
+                withContentsOf: item.url,
+                ofType: "public.source-code"
+            ), loaded {
+                CodeFileView(codeFile: codeFile, editable: false)
             } else if let error = error {
                 Text(error)
             } else {
diff --git a/CodeEdit/Settings/GeneralSettingsView.swift b/CodeEdit/Settings/GeneralSettingsView.swift
index 91d07a9f1..8c2c193d4 100644
--- a/CodeEdit/Settings/GeneralSettingsView.swift
+++ b/CodeEdit/Settings/GeneralSettingsView.swift
@@ -7,15 +7,15 @@
 
 import SwiftUI
 import CodeFile
-import CodeEditor
 
 // MARK: - View
 
 struct GeneralSettingsView: View {
     @AppStorage(Appearances.storageKey) var appearance: Appearances = .default
     @AppStorage(ReopenBehavior.storageKey) var reopenBehavior: ReopenBehavior = .default
-	  @AppStorage(FileIconStyle.storageKey) var fileIconStyle: FileIconStyle = .default
-	  @AppStorage(CodeEditorTheme.storageKey) var editorTheme: CodeEditor.ThemeName = .atelierSavannaAuto
+    @AppStorage(FileIconStyle.storageKey) var fileIconStyle: FileIconStyle = .default
+    @AppStorage(CodeFileView.Theme.storageKey) var editorTheme: CodeFileView.Theme = .atelierSavannaAuto
+
     var body: some View {
         Form {
 			Picker("Appearance".localized(), selection: $appearance) {
@@ -50,18 +50,18 @@ struct GeneralSettingsView: View {
 
 			Picker("Editor Theme".localized(), selection: $editorTheme) {
 				Text("Atelier Savanna (Auto)")
-					.tag(CodeEditor.ThemeName.atelierSavannaAuto)
+                    .tag(CodeFileView.Theme.atelierSavannaAuto)
 				Text("Atelier Savanna Dark")
-					.tag(CodeEditor.ThemeName.atelierSavannaDark)
+                    .tag(CodeFileView.Theme.atelierSavannaDark)
 				Text("Atelier Savanna Light")
-					.tag(CodeEditor.ThemeName.atelierSavannaLight)
+                    .tag(CodeFileView.Theme.atelierSavannaLight)
 				// TODO: Pojoaque does not seem to work (does not change from previous selection)
 //				Text("Pojoaque")
 //					.tag(CodeEditor.ThemeName.pojoaque)
 				Text("Agate")
-					.tag(CodeEditor.ThemeName.agate)
+					.tag(CodeFileView.Theme.agate)
 				Text("Ocean")
-					.tag(CodeEditor.ThemeName.ocean)
+					.tag(CodeFileView.Theme.ocean)
 			}
         }
         .padding()
diff --git a/CodeEdit/WorkspaceView.swift b/CodeEdit/WorkspaceView.swift
index c6b51d21d..caa751d35 100644
--- a/CodeEdit/WorkspaceView.swift
+++ b/CodeEdit/WorkspaceView.swift
@@ -31,11 +31,17 @@ struct WorkspaceView: View {
                 NavigatorSidebar(workspace: workspace, windowController: windowController)
                     .frame(minWidth: 250)
                 HSplitView {
-                    WorkspaceCodeFileView(windowController: windowController,
-                                    workspace: workspace)
-              .frame(maxWidth: .infinity, maxHeight: .infinity)
-                  InspectorSidebar(workspace: workspace, windowController: windowController)
-                  .frame(minWidth: 250, maxWidth: .infinity, maxHeight: .infinity)
+                    WorkspaceCodeFileView(
+                        windowController: windowController,
+                        workspace: workspace
+                    )
+                    .frame(maxWidth: .infinity, maxHeight: .infinity)
+
+                    InspectorSidebar(
+                        workspace: workspace,
+                        windowController: windowController
+                    )
+                    .frame(minWidth: 250, maxWidth: .infinity, maxHeight: .infinity)
                 }
             } else {
                 EmptyView()
@@ -56,7 +62,7 @@ struct WorkspaceView: View {
     }
 }
 
-struct ContentView_Previews: PreviewProvider {
+struct WorkspaceView_Previews: PreviewProvider {
     static var previews: some View {
         WorkspaceView(windowController: NSWindowController(), workspace: .init())
     }
diff --git a/CodeEditModules/.swiftpm/xcode/xcshareddata/xcschemes/CodeFile.xcscheme b/CodeEditModules/.swiftpm/xcode/xcshareddata/xcschemes/CodeFile.xcscheme
new file mode 100644
index 000000000..e89a7d765
--- /dev/null
+++ b/CodeEditModules/.swiftpm/xcode/xcshareddata/xcschemes/CodeFile.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1330"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "CodeFile"
+               BuildableName = "CodeFile"
+               BlueprintName = "CodeFile"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "CodeFile"
+            BuildableName = "CodeFile"
+            BlueprintName = "CodeFile"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/CodeEditModules/Modules/CodeFile/src/CodeEditor+AppStorage.swift b/CodeEditModules/Modules/CodeFile/src/CodeEditor+AppStorage.swift
deleted file mode 100644
index 66a049654..000000000
--- a/CodeEditModules/Modules/CodeFile/src/CodeEditor+AppStorage.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-//  File.swift
-//  
-//
-//  Created by Lukas Pistrol on 18.03.22.
-//
-
-import Foundation
-import CodeEditor
-
-public extension CodeEditor.ThemeName {
-	static var atelierSavannaAuto = CodeEditor.ThemeName(rawValue: "atelier-savanna-auto")
-}
-
-public enum CodeEditorTheme {
-	public static let storageKey = "codeEditorTheme"
-}
diff --git a/CodeEditModules/Modules/CodeFile/src/CodeEditor.swift b/CodeEditModules/Modules/CodeFile/src/CodeEditor.swift
new file mode 100644
index 000000000..2b3a998f2
--- /dev/null
+++ b/CodeEditModules/Modules/CodeFile/src/CodeEditor.swift
@@ -0,0 +1,148 @@
+//
+//  CodeEditor.swift
+//  CodeEdit
+//
+//  Created by Marco Carnevali on 19/03/22.
+//
+
+import Foundation
+import AppKit
+import SwiftUI
+import Highlightr
+import Combine
+
+struct CodeEditor: NSViewRepresentable {
+    @State private var isCurrentlyUpdatingView: ReferenceTypeBool = .init(value: false)
+    private var content: Binding<String>
+    private let language: Language?
+    private let theme: Binding<CodeFileView.Theme>
+    private let highlightr = Highlightr()
+
+    init(
+        content: Binding<String>,
+        language: Language?,
+        theme: Binding<CodeFileView.Theme>
+    ) {
+        self.content = content
+        self.language = language
+        self.theme = theme
+        highlightr?.setTheme(to: theme.wrappedValue.rawValue)
+    }
+
+    func makeNSView(context: Context) -> NSScrollView {
+        let scrollView = NSScrollView()
+        let textView = CodeEditorTextView(
+            textContainer: buildTextStorage(
+                language: language,
+                scrollView: scrollView
+            )
+        )
+        textView.autoresizingMask = .width
+        textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
+        textView.minSize = NSSize(width: 0, height: scrollView.contentSize.height)
+        textView.delegate = context.coordinator
+
+        scrollView.drawsBackground = true
+        scrollView.borderType = .noBorder
+        scrollView.hasVerticalScroller = true
+        scrollView.hasHorizontalRuler = false
+        scrollView.autoresizingMask = [.width, .height]
+
+        scrollView.documentView = textView
+        scrollView.verticalRulerView = LineGutter(
+            scrollView: scrollView,
+            width: 45,
+            font: .monospacedDigitSystemFont(ofSize: 11, weight: .regular),
+            textColor: .secondaryLabelColor,
+            backgroundColor: .clear
+        )
+        scrollView.rulersVisible = true
+
+        updateTextView(textView)
+        return scrollView
+    }
+
+    func updateNSView(_ scrollView: NSScrollView, context: Context) {
+        if let textView = scrollView.documentView as? CodeEditorTextView {
+            updateTextView(textView)
+        }
+    }
+
+    final class Coordinator: NSObject, NSTextViewDelegate {
+        private var content: Binding<String>
+        init(content: Binding<String>) {
+            self.content = content
+        }
+
+        func textDidChange(_ notification: Notification) {
+            guard let textView = notification.object as? NSTextView else {
+                return
+            }
+            content.wrappedValue = textView.string
+        }
+
+    }
+
+    func makeCoordinator() -> Coordinator {
+        Coordinator(content: content)
+    }
+
+    private func updateTextView(_ textView: NSTextView) {
+        guard !isCurrentlyUpdatingView.value else {
+            return
+        }
+
+        isCurrentlyUpdatingView.value = true
+
+        defer {
+            isCurrentlyUpdatingView.value = false
+        }
+
+        highlightr?.setTheme(to: theme.wrappedValue.rawValue)
+
+        if content.wrappedValue != textView.string {
+            if let textStorage = textView.textStorage as? CodeAttributedString {
+                textStorage.language = language?.rawValue
+                textStorage.replaceCharacters(
+                    in: NSRange(location: 0, length: textStorage.length),
+                    with: content.wrappedValue
+                )
+            } else {
+                textView.string = content.wrappedValue
+            }
+        }
+    }
+
+    private func buildTextStorage(language: Language?, scrollView: NSScrollView) -> NSTextContainer {
+        // highlightr wrapper that enables real-time highlighting
+        let textStorage: CodeAttributedString
+        if let highlightr = highlightr {
+            textStorage = CodeAttributedString(highlightr: highlightr)
+        } else {
+            textStorage = CodeAttributedString()
+        }
+        textStorage.language = language?.rawValue
+        let layoutManager = NSLayoutManager()
+        textStorage.addLayoutManager(layoutManager)
+        let textContainer = NSTextContainer(containerSize: scrollView.frame.size)
+        textContainer.widthTracksTextView = true
+        textContainer.containerSize = NSSize(
+            width: scrollView.contentSize.width,
+            height: .greatestFiniteMagnitude
+        )
+        layoutManager.addTextContainer(textContainer)
+        return textContainer
+    }
+}
+
+extension CodeEditor {
+    // A wrapper around a `Bool` that enables updating
+    // the wrapped value during `View` renders.
+    private class ReferenceTypeBool {
+        var value: Bool
+
+        init(value: Bool) {
+            self.value = value
+        }
+    }
+}
diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift
index 9fb606b3c..6b4a98c8b 100644
--- a/CodeEditModules/Modules/CodeFile/src/CodeFile.swift
+++ b/CodeEditModules/Modules/CodeFile/src/CodeFile.swift
@@ -6,7 +6,6 @@
 //
 
 import AppKit
-import CodeEditor
 import Foundation
 import SwiftUI
 
@@ -25,14 +24,6 @@ public final class CodeFileDocument: NSDocument, ObservableObject {
         return true
     }
 
-    public func fileLanguage() -> CodeEditor.Language {
-        if let fileURL = fileURL {
-            return .init(url: fileURL)
-        } else {
-            return .markdown
-        }
-    }
-
     override public func makeWindowControllers() {
         // Returns the Storyboard that contains your Document window.
         let contentView = CodeFileView(codeFile: self)
@@ -57,15 +48,3 @@ public final class CodeFileDocument: NSDocument, ObservableObject {
         self.content = content
     }
 }
-
-public extension CodeEditor.Language {
-    init(url: URL) {
-        var value = url.pathExtension
-        switch value {
-        case "js": value = "javascript"
-        case "sh": value = "shell"
-        default: break
-        }
-        self.init(rawValue: value)
-    }
-}
diff --git a/CodeEditModules/Modules/CodeFile/src/CodeFileView.swift b/CodeEditModules/Modules/CodeFile/src/CodeFileView.swift
index 0f03bc4c9..2827491cd 100644
--- a/CodeEditModules/Modules/CodeFile/src/CodeFileView.swift
+++ b/CodeEditModules/Modules/CodeFile/src/CodeFileView.swift
@@ -5,21 +5,43 @@
 //  Created by Marco Carnevali on 17/03/22.
 //
 
-import CodeEditor
+import Highlightr
 import Foundation
 import SwiftUI
 
 /// CodeFileView is just a wrapper of the `CodeEditor` dependency
 public struct CodeFileView: View {
-    @ObservedObject public var codeFile: CodeFileDocument
+    @ObservedObject private var codeFile: CodeFileDocument
+    @AppStorage(Theme.storageKey) var theme: Theme = .atelierSavannaAuto
     @Environment(\.colorScheme) private var colorScheme
-    @AppStorage(CodeEditorTheme.storageKey) var theme: CodeEditor.ThemeName = .atelierSavannaAuto
+    private let editable: Bool
 
-    public init(codeFile: CodeFileDocument) {
+    public init(codeFile: CodeFileDocument, editable: Bool = true) {
         self.codeFile = codeFile
+        self.editable = editable
     }
 
     public var body: some View {
-        ThemedCodeView($codeFile.content, language: codeFile.fileLanguage())
+        CodeEditor(
+            content: $codeFile.content,
+            language: getLanguage(),
+            theme: $theme
+        )
+        .disabled(!editable)
+    }
+
+    private func getLanguage() -> CodeEditor.Language? {
+        if let url = codeFile.fileURL {
+            return .init(url: url)
+        } else {
+            return .plaintext
+        }
+    }
+
+    private func getTheme() -> Theme {
+        if theme == .atelierSavannaAuto {
+            return colorScheme == .light ? .atelierSavannaLight : .atelierSavannaDark
+        }
+        return theme
     }
 }
diff --git a/CodeEditModules/Modules/CodeFile/src/LineGutter/LineGutter.swift b/CodeEditModules/Modules/CodeFile/src/LineGutter/LineGutter.swift
new file mode 100644
index 000000000..0dbd7a46c
--- /dev/null
+++ b/CodeEditModules/Modules/CodeFile/src/LineGutter/LineGutter.swift
@@ -0,0 +1,242 @@
+//
+//  LineGutter.swift
+//  CodeEdit
+//
+//  Created by Marco Carnevali on 19/03/22.
+//
+
+import Cocoa
+
+class LineGutter: NSRulerView {
+    private var _lineIndices: [Int]? {
+        didSet {
+            DispatchQueue.main.async {
+                let newThickness = self.calculateRuleThickness()
+                if fabs(self.ruleThickness - newThickness) > 1 {
+                    self.ruleThickness = CGFloat(ceil(newThickness))
+                    self.needsDisplay = true
+                }
+            }
+        }
+    }
+    private var lineIndices: [Int]? {
+        // swiftlint:disable:next implicit_getter
+        get {
+            if _lineIndices == nil {
+                calculateLines()
+            }
+            return _lineIndices
+        }
+    }
+
+    private var textView: NSTextView? { clientView as? NSTextView }
+    override var isOpaque: Bool { false }
+    override var clientView: NSView? {
+        willSet {
+            let center = NotificationCenter.default
+            if let oldView = clientView as? NSTextView, oldView != newValue {
+                center.removeObserver(self, name: NSText.didEndEditingNotification, object: oldView.textStorage)
+                center.removeObserver(self, name: NSView.boundsDidChangeNotification, object: scrollView?.contentView)
+            }
+            center.addObserver(
+                self,
+                selector: #selector(textDidChange(_:)),
+                name: NSText.didChangeNotification,
+                object: newValue
+            )
+            scrollView?.contentView.postsBoundsChangedNotifications = true
+            center.addObserver(
+                self,
+                selector: #selector(boundsDidChange(_:)),
+                name: NSView.boundsDidChangeNotification,
+                object: scrollView?.contentView
+            )
+            invalidateLineIndices()
+        }
+    }
+
+    private let rulerMargin: CGFloat = 5
+    private let rulerWidth: CGFloat
+    private let font: NSFont
+    public var textColor: NSColor
+    public var backgroundColor: NSColor
+
+    init(
+        scrollView: NSScrollView,
+        width: CGFloat,
+        font: NSFont,
+        textColor: NSColor,
+        backgroundColor: NSColor
+    ) {
+        rulerWidth = width
+        self.font = font
+        self.textColor = textColor
+        self.backgroundColor = backgroundColor
+        super.init(scrollView: scrollView, orientation: .verticalRuler)
+        clientView = scrollView.documentView
+        ruleThickness = width
+        needsDisplay = true
+    }
+
+    required init(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+
+    @objc
+    func boundsDidChange(_ notification: Notification) {
+        needsDisplay = true
+    }
+
+    @objc
+    func textDidChange(_ notification: Notification) {
+        invalidateLineIndices()
+        needsDisplay = true
+    }
+
+    override func draw(_ dirtyRect: NSRect) {
+        drawHashMarksAndLabels(in: dirtyRect)
+    }
+
+    func invalidateLineIndices() {
+        _lineIndices = nil
+    }
+
+    func lineNumberForCharacterIndex(index: Int) -> Int {
+        guard let lineIndices = lineIndices else {
+            return 0
+        }
+
+        var left = 0, right = lineIndices.count
+        while right - left > 1 {
+            let mid = (left + right) / 2
+            let lineIndex = lineIndices[mid]
+            if index < lineIndex {
+                right = mid
+            } else if index > lineIndex {
+                left = mid
+            } else {
+                return mid + 1
+            }
+        }
+        return left + 1
+    }
+
+    func calculateRuleThickness() -> CGFloat {
+        let string = String(lineIndices?.last ?? 0) as NSString
+        let rect = calculateStringSize(string)
+        return max(rect.width, rulerWidth)
+    }
+
+    func calculateLines() {
+        var lineIndices = [Int]()
+        guard let textView = textView else {
+            return
+        }
+        let text = textView.string as NSString
+        let textLength = text.length
+        var totalLines = 0
+        var charIndex = 0
+        repeat {
+            lineIndices.append(charIndex)
+            charIndex = text.lineRange(for: NSRange(location: charIndex, length: 0)).upperBound
+            totalLines += 1
+        } while charIndex < textLength
+
+        // Check for trailing return
+        var lineEndIndex = 0, contentEndIndex = 0
+        let lastObject = lineIndices[lineIndices.count - 1]
+        text.getLineStart(
+            nil,
+            end: &lineEndIndex,
+            contentsEnd: &contentEndIndex,
+            for: NSRange(location: lastObject, length: 0)
+        )
+        if contentEndIndex < lineEndIndex {
+            lineIndices.append(lineEndIndex)
+        }
+        _lineIndices = lineIndices
+    }
+
+    // swiftlint:disable function_body_length
+    override func drawHashMarksAndLabels(in rect: NSRect) {
+        guard let textView = textView,
+              let clientView = clientView,
+              let layoutManager = textView.layoutManager,
+              let container = textView.textContainer,
+              let scrollView = scrollView,
+              let lineIndices = lineIndices
+        else { return }
+
+        // Make background
+        let docRect = convert(clientView.bounds, from: clientView)
+        let yOrigin = docRect.origin.y
+        let height = docRect.size.height
+        let width = bounds.size.width
+        backgroundColor.set()
+
+        NSRect(x: 0, y: yOrigin, width: width, height: height).fill()
+
+        // Code folding area
+        NSRect(x: width - 8, y: yOrigin, width: 8, height: height).fill()
+
+        let nullRange = NSRange(location: NSNotFound, length: 0)
+        var lineRectCount = 0
+
+        let textVisibleRect = scrollView.contentView.bounds
+        let rulerBounds = bounds
+        let textInset = textView.textContainerInset.height
+
+        let glyphRange = layoutManager.glyphRange(forBoundingRect: textVisibleRect, in: container)
+        let charRange = layoutManager.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
+
+        let startChange = lineNumberForCharacterIndex(index: charRange.location)
+        let endChange = lineNumberForCharacterIndex(index: charRange.upperBound)
+        for lineNumber in startChange...endChange {
+            let charIndex = lineIndices[lineNumber - 1]
+            if let lineRectsForRange = layoutManager.rectArray(
+                forCharacterRange: NSRange(location: charIndex, length: 0),
+                withinSelectedCharacterRange: nullRange,
+                in: container,
+                rectCount: &lineRectCount
+            ), lineRectCount > 0 {
+                let ypos = textInset + lineRectsForRange[0].minY - textVisibleRect.minY
+                let labelText = NSString(format: "%ld", lineNumber)
+                let labelSize = calculateStringSize(labelText)
+
+                let lineNumberRect = NSRect(
+                    x: rulerBounds.width - labelSize.width - rulerMargin,
+                    y: ypos + (lineRectsForRange[0].height - labelSize.height) / 2,
+                    width: rulerBounds.width - rulerMargin * 2,
+                    height: lineRectsForRange[0].height
+                )
+
+                labelText.draw(in: lineNumberRect, withAttributes: textAttributes())
+            }
+
+            // we are past the visible range so exit for
+            if charIndex > charRange.upperBound {
+                break
+            }
+        }
+    }
+
+    func calculateStringSize(_ string: NSString) -> CGRect {
+        string.boundingRect(
+            with: NSSize(width: self.frame.width, height: .greatestFiniteMagnitude),
+            options: .usesLineFragmentOrigin,
+            attributes: textAttributes(),
+            context: nil
+        )
+    }
+
+    func textAttributes() -> [NSAttributedString.Key: AnyObject] {
+        [
+            NSAttributedString.Key.font: self.font,
+            NSAttributedString.Key.foregroundColor: self.textColor
+        ]
+    }
+}
diff --git a/CodeEditModules/Modules/CodeFile/src/Model/Language.swift b/CodeEditModules/Modules/CodeFile/src/Model/Language.swift
new file mode 100644
index 000000000..e40839d84
--- /dev/null
+++ b/CodeEditModules/Modules/CodeFile/src/Model/Language.swift
@@ -0,0 +1,213 @@
+//
+//  File.swift
+//  
+//
+//  Created by Marco Carnevali on 22/03/22.
+//
+import Foundation.NSURL
+// swiftlint:disable identifier_name
+extension CodeEditor {
+    enum Language: String {
+        case abnf
+        case accesslog
+        case actionscript
+        case ada
+        case angelscript
+        case apache
+        case applescript
+        case arcade
+        case cpp
+        case arduino
+        case armasm
+        case xml
+        case asciidoc
+        case aspectj
+        case autohotkey
+        case autoit
+        case avrasm
+        case awk
+        case axapta
+        case bash
+        case basic
+        case bnf
+        case brainfuck
+        case cal
+        case capnproto
+        case ceylon
+        case clean
+        case clojure
+        case cmake
+        case coffeescript
+        case coq
+        case cos
+        case crmsh
+        case crystal
+        case cs
+        case csp
+        case css
+        case d
+        case markdown
+        case dart
+        case delphi
+        case diff
+        case django
+        case dns
+        case dockerfile
+        case dos
+        case dsconfig
+        case dts
+        case dust
+        case ebnf
+        case elixir
+        case elm
+        case ruby
+        case erb
+        case erlang
+        case excel
+        case fix
+        case flix
+        case fortran
+        case fsharp
+        case gams
+        case gauss
+        case gcode
+        case gherkin
+        case glsl
+        case gml
+        case go
+        case golo
+        case gradle
+        case groovy
+        case haml
+        case handlebars
+        case haskell
+        case haxe
+        case hsp
+        case htmlbars
+        case http
+        case hy
+        case inform7
+        case ini
+        case irpf90
+        case isbl
+        case java
+        case javascript
+        case json
+        case julia
+        case kotlin
+        case lasso
+        case ldif
+        case leaf
+        case less
+        case lisp
+        case livecodeserver
+        case livescript
+        case llvm
+        case lsl
+        case lua
+        case makefile
+        case mathematica
+        case matlab
+        case maxima
+        case mel
+        case mercury
+        case mipsasm
+        case mizar
+        case perl
+        case mojolicious
+        case monkey
+        case moonscript
+        case n1ql
+        case nginx
+        case nimrod
+        case nix
+        case nsis
+        case objectivec
+        case ocaml
+        case openscad
+        case oxygene
+        case parser3
+        case pf
+        case pgsql
+        case php
+        case plaintext
+        case pony
+        case powershell
+        case processing
+        case profile
+        case prolog
+        case properties
+        case protobuf
+        case puppet
+        case purebasic
+        case python
+        case q
+        case qml
+        case r
+        case reasonml
+        case rib
+        case roboconf
+        case routeros
+        case rsl
+        case ruleslanguage
+        case rust
+        case sas
+        case scala
+        case scheme
+        case scilab
+        case scss
+        case shell
+        case smali
+        case smalltalk
+        case sml
+        case sqf
+        case sql
+        case stan
+        case stata
+        case step21
+        case stylus
+        case subunit
+        case swift
+        case taggerscript
+        case yaml
+        case tap
+        case tcl
+        case tex
+        case thrift
+        case tp
+        case twig
+        case typescript
+        case vala
+        case vbnet
+        case vbscript
+        case verilog
+        case vhdl
+        case vim
+        case x86asm
+        case xl
+        case xquery
+        case zephir
+        case clojureRepl = "clojure-repl"
+        case vbscriptHtml = "vbscript-html"
+        case juliaRepl = "julia-repl"
+        case jbossCli = "jboss-cli"
+        case erlangRepl = "erlang-repl"
+        case oneC = "1c"
+
+        init?(url: URL) {
+            let fileExtension = url.pathExtension.lowercased()
+            switch fileExtension {
+            case "js": self = .javascript
+            case "tf": self = .typescript
+            case "md": self = .markdown
+            case "py": self = .python
+            case "bat": self = .dos
+            case "cxx", "h", "hpp", "hxx": self = .cpp
+            case "scpt", "scptd", "applescript": self = .applescript
+            case "pl": self = .perl
+            case "txt": self = .plaintext
+            default: self.init(rawValue: fileExtension)
+            }
+        }
+    }
+}
diff --git a/CodeEditModules/Modules/CodeFile/src/Model/Theme.swift b/CodeEditModules/Modules/CodeFile/src/Model/Theme.swift
new file mode 100644
index 000000000..a54c94620
--- /dev/null
+++ b/CodeEditModules/Modules/CodeFile/src/Model/Theme.swift
@@ -0,0 +1,18 @@
+//
+//  Theme.swift
+//  CodeEdit
+//
+//  Created by Marco Carnevali on 19/03/22.
+//
+
+extension CodeFileView {
+    public enum Theme: String {
+        public static let storageKey = "codeEditorTheme"
+
+        case agate
+        case ocean
+        case atelierSavannaDark = "atelier-savanna-dark"
+        case atelierSavannaLight = "atelier-savanna-light"
+        case atelierSavannaAuto = "atelier-savanna-auto"
+    }
+}
diff --git a/CodeEditModules/Modules/CodeFile/src/TextView/CodeEditorTextView.swift b/CodeEditModules/Modules/CodeFile/src/TextView/CodeEditorTextView.swift
new file mode 100644
index 000000000..565691b4b
--- /dev/null
+++ b/CodeEditModules/Modules/CodeFile/src/TextView/CodeEditorTextView.swift
@@ -0,0 +1,87 @@
+//
+//  CodeEditorTextView.swift
+//  CodeEdit
+//
+//  Created by Marco Carnevali on 19/03/22.
+//
+
+import Cocoa
+
+class CodeEditorTextView: NSTextView {
+    private let tabNumber = 4
+
+    init(
+        textContainer container: NSTextContainer?
+    ) {
+        super.init(frame: .zero, textContainer: container)
+        drawsBackground = true
+        isEditable = true
+        isHorizontallyResizable = false
+        isVerticallyResizable = true
+        allowsUndo = true
+        isRichText = false
+        isGrammarCheckingEnabled = false
+        isContinuousSpellCheckingEnabled = false
+        isAutomaticQuoteSubstitutionEnabled = false
+        isAutomaticDashSubstitutionEnabled = false
+    }
+
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+    }
+
+    private var swiftSelectedRange: Range<String.Index> {
+        let string = self.string
+        guard !string.isEmpty else { return string.startIndex..<string.startIndex }
+        guard let selectedRange = Range(self.selectedRange(), in: string) else {
+            assertionFailure("Could not convert the selectedRange")
+            return string.startIndex..<string.startIndex
+        }
+        return selectedRange
+    }
+    private var currentLine: String {
+        let string = self.string
+        return String(string[string.lineRange(for: swiftSelectedRange)])
+    }
+
+    override func insertNewline(_ sender: Any?) {
+        // get line before newline
+        let currentLine = self.currentLine
+        let prefix = currentLine.prefix {
+            guard let scalar = $0.unicodeScalars.first else { return false }
+            return CharacterSet.whitespaces.contains(scalar)
+        }
+
+        super.insertNewline(sender)
+
+        if !prefix.isEmpty {
+            insertText(String(prefix), replacementRange: selectedRange())
+        }
+    }
+
+    let autoPairs = [
+        "(": ")",
+        "{": "}",
+        "[": "]",
+        "\"": "\"",
+    ]
+
+    override func insertText(_ string: Any, replacementRange: NSRange) {
+        super.insertText(string, replacementRange: replacementRange)
+        guard let string = string as? String,
+              let end = autoPairs[string]
+        else { return }
+        super.insertText(end, replacementRange: selectedRange())
+        super.moveBackward(self)
+    }
+
+    override func insertTab(_ sender: Any?) {
+        super.insertText(
+            String(
+                repeating: " ",
+                count: tabNumber
+            ),
+            replacementRange: selectedRange()
+        )
+    }
+}
diff --git a/CodeEditModules/Modules/CodeFile/src/ThemedCodeView.swift b/CodeEditModules/Modules/CodeFile/src/ThemedCodeView.swift
deleted file mode 100644
index 956ad330d..000000000
--- a/CodeEditModules/Modules/CodeFile/src/ThemedCodeView.swift
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-//  ThemedCodeView.swift
-//  
-//
-//  Created by Pavel Kasila on 20.03.22.
-//
-
-import SwiftUI
-import CodeEditor
-
-public struct ThemedCodeView: View {
-    @Binding public var content: String
-    public var language: CodeEditor.Language
-    public var editable: Bool
-    @Environment(\.colorScheme) private var colorScheme
-    @AppStorage(CodeEditorTheme.storageKey) var theme: CodeEditor.ThemeName = .atelierSavannaAuto
-
-    public init(_ content: Binding<String>, language: CodeEditor.Language, editable: Bool = true) {
-        self._content = content
-        self.language = language
-        self.editable = editable
-    }
-
-    public var body: some View {
-        CodeEditor(
-            source: $content,
-            language: language,
-            theme: getTheme(),
-            flags: editable ? .defaultEditorFlags : .defaultViewerFlags,
-            indentStyle: .system
-        )
-    }
-
-    private func getTheme() -> CodeEditor.ThemeName {
-        if theme == .atelierSavannaAuto {
-            return colorScheme == .light ? .atelierSavannaLight : .atelierSavannaDark
-        }
-        return theme
-    }
-}
-
-struct SwiftUIView_Previews: PreviewProvider {
-    static var previews: some View {
-        ThemedCodeView(.constant("## Example"), language: .markdown)
-    }
-}
diff --git a/CodeEditModules/Package.swift b/CodeEditModules/Package.swift
index 91d100d51..b488d1d79 100644
--- a/CodeEditModules/Package.swift
+++ b/CodeEditModules/Package.swift
@@ -36,9 +36,9 @@ let package = Package(
     ],
     dependencies: [
         .package(
-            name: "CodeEditor",
-            url: "https://github.com/ZeeZide/CodeEditor.git",
-            from: "1.2.0"
+            name: "Highlightr",
+            url: "https://github.com/raspu/Highlightr.git",
+            from: "2.1.2"
         ),
         .package(
             name: "SnapshotTesting",
@@ -61,7 +61,7 @@ let package = Package(
         .target(
             name: "CodeFile",
             dependencies: [
-                "CodeEditor"
+                "Highlightr"
             ],
             path: "Modules/CodeFile/src"
         ),