├── themes ├── true.png ├── emacs.png ├── catppuccin.png └── nordic-theme.el ├── etc ├── sound │ └── bell.mp3 └── yasnippet │ └── snippets │ └── swift-mode │ ├── weakself.yasnippet │ ├── Comments │ ├── Mark │ ├── Doc comment (one line) │ ├── Doc comment block │ ├── Doc comment remark │ ├── Doc comment returns │ ├── Doc comment warning │ ├── Doc comment parameter │ └── Doc comment important │ ├── import.yasnippet │ ├── Typealias │ ├── enum │ ├── let.yasnippet │ ├── async.yasnippet │ ├── var │ ├── self.yasnippet │ ├── await │ ├── defer.yasnippet │ ├── for.yasnippet │ ├── test.yasnippet │ ├── todo.yasnippet │ ├── while.yasnippet │ ├── @available │ ├── deinit.yasnippet │ ├── fori │ ├── if │ ├── protocol.yasnippet │ ├── guardself.yasnippet │ ├── typealias.yasnippet │ ├── after.yasnippet │ ├── lazyvar.yasnippet │ ├── iflet.yasnippet │ ├── closure.yasnippet │ ├── for-try-await │ ├── guardlet │ ├── localized.yasnippet │ ├── repeatWhile │ ├── varget.yasnippet │ ├── ifelse.yasnippet │ ├── requiredinit.yasnippet │ ├── dispatch-async │ ├── initall.yasnippet │ ├── var-didset │ ├── convenienceinit.yasnippet │ ├── docatch.yasnippet │ ├── init.yasnippet │ ├── lazy-init │ ├── letget.yasnippet │ ├── switch.yasnippet │ ├── struct │ ├── dispatch-after-delay │ ├── if-available │ ├── lazyvarget.yasnippet │ ├── letclosure.yasnippet │ ├── try-catch │ ├── lazyvarclosure.yasnippet │ ├── available.yasnippet │ ├── dispatch-group │ ├── function-with-param-return-type │ ├── vargetset.yasnippet │ ├── unwind.yasnippet │ ├── class │ ├── swui-contentview.yasnippet │ ├── shelltempdir.yasnippet │ ├── iabutton.yasnippet │ ├── optionset.yasnippet │ ├── shellarguments.swift │ ├── shell.yasnippet │ ├── script.yasnippet │ └── .yas-setup.el ├── README.md ├── localpackages ├── periphery │ ├── tests │ │ ├── debug-swift.el │ │ ├── test-fixed-regex.el │ │ ├── test-faces.el │ │ ├── test-highlight-patterns.el │ │ ├── test-exact-error.el │ │ ├── test-highlighting.el │ │ ├── test-no-space.el │ │ ├── test-pattern-management.el │ │ ├── test-regex-match.el │ │ ├── reload-periphery.el │ │ ├── test-periphery.el │ │ ├── debug-regex-parts.el │ │ ├── periphery-test.el │ │ ├── simple-regex-test.el │ │ └── debug-full-chain.el │ ├── periphery-loco.el │ ├── periphery-swiftlint.el │ ├── periphery-ktlint.el │ ├── periphery-multiline.el │ ├── periphery-swiftformat.el │ ├── periphery-search.el │ ├── periphery-quick.el │ ├── periphery-core.el │ └── periphery-helper.el ├── music-control │ └── README.md ├── domain-blocker.el └── filer.el ├── modules ├── mk-misc.el ├── mk-term.el ├── mk-theme.el ├── mk-web.el ├── mk-kotlin-development.el ├── mk-lisp.el ├── mk-vc.el ├── mk-treemacs.el ├── mk-core.el ├── mk-elfeed.el ├── mk-ai.el ├── mk-editing.el ├── mk-completion.el ├── mk-ios-development.el ├── mk-emacs.el ├── mk-ui.el ├── mk-org.el ├── mk-code-completion.el └── mk-evil.el ├── .gitignore ├── suppress-warnings.el ├── init.el └── early-init.el /themes/true.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/konrad1977/emacs/HEAD/themes/true.png -------------------------------------------------------------------------------- /etc/sound/bell.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/konrad1977/emacs/HEAD/etc/sound/bell.mp3 -------------------------------------------------------------------------------- /themes/emacs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/konrad1977/emacs/HEAD/themes/emacs.png -------------------------------------------------------------------------------- /themes/catppuccin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/konrad1977/emacs/HEAD/themes/catppuccin.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ❤️ [Please sponsor me if you like this package](https://github.com/sponsors/konrad1977) 3 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/weakself.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Weak self 2 | #key : ws 3 | # -- 4 | [weak self] $0 5 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Mark: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Mark 3 | # key: mark 4 | # -- 5 | //MARK:- $1 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/import.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Import Statement 2 | #key : import 3 | # -- 4 | import ${1:module} -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Typealias: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Typealias 3 | # key: alias 4 | # -- 5 | typealias $1 = $2 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/enum: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: enum 3 | # key: enum 4 | # -- 5 | enum ${1:name} { 6 | 7 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/let.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Let Declaration 2 | #key : let 3 | # -- 4 | let ${1:name} = ${2:value} 5 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/async.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Async 2 | #key : async 3 | # -- 4 | DispatchQueue.main.async { 5 | $0 6 | } 7 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/var: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: var 3 | # key: var 4 | # -- 5 | var ${1:name}: ${2:type} = ${3:value} -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/self.yasnippet: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: self initialized 3 | # key: self 4 | # -- 5 | self.$1 = ${1:}$0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/await: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: await 3 | # key: await 4 | # -- 5 | let ${1:value} = await ${2:defferedValue} 6 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/defer.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Defer Statement 2 | #key : defer 3 | # -- 4 | defer { 5 | ${1:deferred statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/for.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift For Statement 2 | #key : for 3 | # -- 4 | for ${1:item} in ${2:items} { 5 | ${3:code} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/test.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Test Method 2 | #key : test 3 | # -- 4 | func test${1:Name}() { 5 | ${2:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/todo.yasnippet: -------------------------------------------------------------------------------- 1 | #name : todo 2 | #key : todo 3 | # -- 4 | // TODO(`(user-login-name)`): ${1:Am I just being lazy?!?}.$0 5 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/while.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift While Statement 2 | #key : while 3 | # -- 4 | while ${1:condition} { 5 | ${2:code} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/@available: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: @available 3 | # key: @available 4 | # -- 5 | @available(${1:iOS} ${2:version}, *) -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment (one line): -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment (one line) 3 | # key: ** 4 | # -- 5 | /** $0 */ -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment block: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment block 3 | # key: *** 4 | # -- 5 | /** 6 | $1 7 | */ -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment remark: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment remark 3 | # key: remark 4 | # -- 5 | - remark: $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment returns: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment returns 3 | # key: returns 4 | # -- 5 | - returns: $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment warning: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment warning 3 | # key: warning 4 | # -- 5 | - warning: $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/deinit.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Deinitializer Declaration 2 | #key : deinit 3 | # -- 4 | deinit { 5 | ${1:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/fori: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: for 3 | # key: fori 4 | # -- 5 | for ${1:i} in ${2:0}..<${1:count} { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/if: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: if 3 | # key: if 4 | # -- 5 | if ${1:condition} { 6 | ${2:statement} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/protocol.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Protocol 2 | #key : protocol 3 | # -- 4 | protocol ${1:name} { 5 | ${2:requirements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment parameter: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment parameter 3 | # key: param 4 | # -- 5 | - parameter $1: $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/guardself.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Guard-Let Self Statement 2 | #key : gs 3 | # -- 4 | guard let self = self else { 5 | return 6 | }$0 7 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/typealias.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Typealias Declaration 2 | #key : typealias 3 | # -- 4 | typealias ${1:type name} = ${2:type expression} -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/Comments/Doc comment important: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Doc comment important 3 | # key: important 4 | # -- 5 | - important $1: $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/after.yasnippet: -------------------------------------------------------------------------------- 1 | #name : After 2 | #key : after 3 | # -- 4 | DispatchQueue.main.asyncAfter(deadline: .now() + ${1:seconds}) { 5 | $0 6 | } 7 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/lazyvar.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Lazy Stored Property Declaration 2 | #key : lazyvar 3 | # -- 4 | lazy var ${1:property name} = ${2:expression} -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/iflet.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift If-Let Statement 2 | #key : iflet 3 | # -- 4 | if let ${1:constant name} = ${2:optional} { 5 | ${3:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/closure.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Closure Expression 2 | #key : closure 3 | # -- 4 | { (${1:parameters}) -> ${2:return type} in 5 | ${3:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/for-try-await: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: for try await 3 | # key: for try await 4 | # -- 5 | for try await ${1:value} in ${2:list} { 6 | 7 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/guardlet: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: guard let 3 | # key: guard 4 | # -- 5 | 6 | guard let ${1:name} = ${2:type} 7 | else { return ${3:retValue} } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/localized.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift localized string 2 | #key : loc 3 | # -- 4 | NSLocalizedString("${1:string}", 5 | comment: "${2:comment}") 6 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/repeatWhile: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: repeat while 3 | # key: repeat 4 | # -- 5 | repeat { 6 | ${1:statement} 7 | } while ${2:condition} 8 | 9 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/varget.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Computed Variable Get Declaration 2 | #key : varget 3 | # -- 4 | var ${1:variable name}: ${2:type} { 5 | ${3:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/ifelse.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift If-Else Statement 2 | #key : ifelse 3 | # -- 4 | if ${1:condition} { 5 | ${2:statements} 6 | } else { 7 | ${3:statements} 8 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/requiredinit.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Required Initializer Declaration 2 | #key : requiredinit 3 | # -- 4 | required init(${1:parameters}) { 5 | ${2:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/dispatch-async: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: DispatchQueue async 3 | # key: dispatchqueue async 4 | # -- 5 | DispatchQueue.main.async { 6 | ${1:statement} 7 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/initall.yasnippet: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: init all 3 | # key: init 4 | # -- 5 | `(swift-class-or-struct-initializer-text (swift-class-or-struct-vars-at-point))` 6 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/var-didset: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: var didset 3 | # key: vardid 4 | # -- 5 | var ${1:name}: ${2:type} = ${3:initialValue} { 6 | didset { 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/convenienceinit.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Convenience Initializer Declaration 2 | #key : convenienceinit 3 | # -- 4 | convenience init(${1:parameters}) { 5 | ${2:statements} 6 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/docatch.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Do-Catch Statement 2 | #key : docatch 3 | # -- 4 | do { 5 | try ${1:throwing expression} 6 | } catch ${2:pattern} { 7 | ${3:statements} 8 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/init.yasnippet: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: init with assignments 3 | # key: init 4 | # -- 5 | init(${1:, args}) { 6 | ${1:$(swift-snippet-init-assignments yas-text)} 7 | } 8 | $0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/lazy-init: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: lazy init 3 | # key: private lazy init 4 | # -- 5 | private lazy var ${1:name}: ${2:type} = { 6 | let $1 = $2() 7 | 8 | return $1 9 | }() -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/letget.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Computed Constant Declaration 2 | #key : letget 3 | # -- 4 | let ${1:property name}: ${2:type name} = { 5 | ${3:statements} 6 | return ${4:value} 7 | }() -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/switch.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Switch Statement 2 | #key : switch 3 | # -- 4 | switch ${1:value} { 5 | case ${2:pattern}: 6 | ${3:code} 7 | default: 8 | ${4:code} 9 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/struct: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Create Struct 3 | # key: struct 4 | # -- 5 | struct ${1:Name} { 6 | let ${2:VariableName}: ${3:Type} 7 | } 8 | 9 | extension $1 { 10 | 11 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/dispatch-after-delay: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: dispatch after delay 3 | # key: dispatch after delay 4 | # -- 5 | DispatchQueue.main.asyncAfter(deadline: .now() + ${1:delay}) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/if-available: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: if available 3 | # key: if #available 4 | # -- 5 | if #available(${1:iOS} ${2:version}, *) { 6 | // Available 7 | } else { 8 | // Fallback code 9 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/lazyvarget.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Lazy Computed Property Declaration 2 | #key : lazyvarget 3 | # -- 4 | lazy var ${1:property name}: ${2:type name} = { 5 | ${3:statements} 6 | return ${4:value} 7 | }() -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/letclosure.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Closure Stored Constant Declaration 2 | #key : letclosure 3 | # -- 4 | let ${1:constant name}: ${2:type name} = { 5 | ${3:statements} 6 | return ${4:value} 7 | }() -------------------------------------------------------------------------------- /localpackages/periphery/tests/debug-swift.el: -------------------------------------------------------------------------------- 1 | ;;; Enable debugging 2 | 3 | (setq periphery-debug t) 4 | (setq swift-additions:debug t) 5 | 6 | ;; Test compilation with debug 7 | (message "Swift and periphery debug enabled. Try building now.") -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/try-catch: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: try catch 3 | # key: try catch 4 | # -- 5 | do { 6 | let ${1:value} = try ${2:somethingThrowing} 7 | } catch let error { 8 | print(error) 9 | } 10 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/lazyvarclosure.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Lazy Closure Stored Property Declaration 2 | #key : lazyvarclosure 3 | # -- 4 | lazy var ${1:property name}: ${2:type name} = { 5 | ${3:statements} 6 | return ${4:value} 7 | }() -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/available.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift API Availability Check 2 | #key : available 3 | # -- 4 | if #available(${1:{i, mac, tv, watch}}OS ${2:x.y.z}, *) { 5 | ${3:API available statements} 6 | } else { 7 | ${4:fallback statements} 8 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/dispatch-group: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: dispatch group 3 | # key: dispatch group 4 | # -- 5 | let ${1:group} = DispatchGroup() 6 | let ${2:queue} = DispatchQueue(label: "${3:queuename}") 7 | 8 | $1.notify(queue: $2) { 9 | 10 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/function-with-param-return-type: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Function with args and return types 3 | # key: fure 4 | # -- 5 | 6 | private func ${1:functionName}(${2:paramName}: ${3:type}) -> ${4:returnType} { 7 | 8 | return 9 | } 10 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/vargetset.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Computed Variable Get and Set Declaration 2 | #key : vargetset 3 | # -- 4 | var ${1:variable name}: ${2:type} { 5 | get { 6 | ${3:statements} 7 | } 8 | set { 9 | ${4:variable name} = newValue 10 | } 11 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/unwind.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift Unwind Segue Method 2 | #key : unwind 3 | # -- 4 | @IBAction func unwindTo${1:name}(_ unwindSegue: UIStoryboardSegue) { 5 | let sourceViewController = unwindSegue.source 6 | // Use data from the view controller which initiated the unwind segue 7 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/class: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Create class 3 | # key: class 4 | # -- 5 | import Foundation 6 | 7 | final class ${1:classname} { 8 | init() { 9 | } 10 | } 11 | 12 | // MARK: - public 13 | extension $1 { 14 | 15 | } 16 | 17 | // MARK: - private 18 | extension $1 { 19 | 20 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/swui-contentview.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swiftui content view 2 | #key : cv 3 | # -- 4 | struct ${1:My}ContentView: View { 5 | 6 | var body: some View { 7 | NavigationView { 8 | Text("Hello $1ContentView") 9 | .navigationBarTitle("Mind Blowing") 10 | } 11 | } 12 | }$0 -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/shelltempdir.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Shell temporary directory 2 | #key : tempDir 3 | # -- 4 | func tempDir() -> String? { 5 | let (output, exitCode) = shell("mktemp", "-d") 6 | if exitCode != 0 { 7 | return nil 8 | } 9 | return output.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) 10 | } 11 | 12 | $0 13 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/iabutton.yasnippet: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet -*- 2 | # name: Create IA Button 3 | # key: iabutton 4 | # -- 5 | Button { 6 | ${1:callback} 7 | } label: { 8 | HStack { 9 | ${2:view} 10 | } 11 | } 12 | .iaButtonStyle(${3:$$(yas-choose-value '(".plain" ".plainLarge" ".plainWithState" ".plainWithLoadingState" ".plainLargeWithLoadingState" ".start" ".bezel"))}) -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/optionset.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift OptionSet 2 | #key : optionset 3 | # -- 4 | struct ${1:name}: OptionSet { 5 | let rawValue: ${2:integer type} 6 | 7 | static let ${3:optionA} = ${4:name}(rawValue: 1 << 0) 8 | static let ${5:optionB} = ${6:name}(rawValue: 1 << 1) 9 | static let ${7:optionC} = ${8:name}(rawValue: 1 << 2) 10 | 11 | static let all: ${9:name} = [.${10:optionA}, .${11:optionB}, .${12:optionC}] 12 | } -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/shellarguments.swift: -------------------------------------------------------------------------------- 1 | #name : Shell script arguments 2 | #key : shellArgs 3 | # -- 4 | struct Script { 5 | let fileName: String 6 | let arguments: Arguments 7 | 8 | struct Arguments { 9 | let $1: $2 10 | } 11 | 12 | init() { 13 | fileName = CommandLine.arguments[0] 14 | 15 | if CommandLine.arguments.count < 2 { 16 | fputs("Usage: \\(fileName) $3", stderr) 17 | exit(1) 18 | } 19 | 20 | arguments = Arguments($1: CommandLine.arguments[1]) 21 | } 22 | } 23 | 24 | $0 25 | -------------------------------------------------------------------------------- /modules/mk-misc.el: -------------------------------------------------------------------------------- 1 | ;;; mk-misc.el --- Miscellaneous configurations -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file contains miscellaneous configurations and package setups for Emacs. 4 | ;;; Code: 5 | 6 | (use-package weather-scout 7 | :defer t 8 | :commands (weather-scout-show-forecast) 9 | :init 10 | ;; Use Vim motions in the weather forecast buffer (optional) 11 | (with-eval-after-load 'evil 12 | (evil-set-initial-state 'weather-scout-mode 'motion))) 13 | 14 | 15 | (provide 'mk-misc) 16 | ;;; mk-misc.el ends here 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /elpa/ 2 | /eln-cache/ 3 | /.cache/ 4 | /.DS_Store 5 | *DS_Store* 6 | /localpackages/cocaine/ 7 | /localpackages/darken-buffer/ 8 | /localpackages/flycheck-eglot/ 9 | /localpackages/flycheck-overlay/ 10 | /localpackages/mito-laser-emacs/ 11 | /localpackages/periphery/ 12 | /localpackages/swift-development/ 13 | /localpackages/welcome-dashboard/ 14 | 15 | # Temporary and runtime files 16 | flycheck_*.el 17 | /persist/ 18 | /recentf 19 | /history 20 | /undo-fu-session/ 21 | /transient/ 22 | /request/ 23 | /tramp 24 | /tree-sitter/ 25 | /projects 26 | /var/ 27 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/shell.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Shell 2 | #key : shell 3 | # -- 4 | @discardableResult 5 | func shell(_ args: String...) -> (String, Int32) { 6 | let pipe = Pipe() 7 | pipe.fileHandleForReading.waitForDataInBackgroundAndNotify() 8 | 9 | let process = Process() 10 | process.standardOutput = pipe 11 | process.arguments = args 12 | process.launchPath = "/usr/bin/env" 13 | process.waitUntilExit() 14 | process.launch() 15 | 16 | let data = pipe.fileHandleForReading.availableData 17 | let output = String(data: data, encoding: String.Encoding.utf8) ?? "" 18 | return (output, process.terminationStatus) 19 | } 20 | 21 | $0 22 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/script.yasnippet: -------------------------------------------------------------------------------- 1 | #name : Swift shell script skeleton 2 | #key : script 3 | # -- 4 | #!/usr/bin/swift 5 | 6 | import Foundation 7 | 8 | struct Script { 9 | let fileName: String 10 | let arguments: Arguments 11 | 12 | struct Arguments { 13 | let $1: $2 14 | } 15 | 16 | init() { 17 | fileName = CommandLine.arguments[0] 18 | 19 | if CommandLine.arguments.count < 2 { 20 | fputs("Usage: \\(fileName) $3", stderr) 21 | exit(1) 22 | } 23 | 24 | arguments = Arguments($1: CommandLine.arguments[1]) 25 | } 26 | } 27 | 28 | func main() { 29 | let script = Script() 30 | 31 | $0 32 | 33 | print("Hello world with argument: \\(script.arguments.$1)") 34 | } 35 | 36 | 37 | main() 38 | -------------------------------------------------------------------------------- /modules/mk-term.el: -------------------------------------------------------------------------------- 1 | ;;; mk-term.el --- Create and manage terminal buffers -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file provides functionality to create and manage terminal buffers in Emacs. 4 | ;;; Code: 5 | 6 | (add-hook 'comint-mode-hook 7 | (lambda () 8 | (setq-local comint-prompt-read-only t) 9 | (setq-local visual-line-mode t))) 10 | 11 | (use-package vterm 12 | :defer t 13 | :commands vterm 14 | :config 15 | (add-hook 'vterm-mode-hook (lambda () (setq-local global-hl-line-mode nil))) 16 | (setq vterm-timer-delay nil 17 | vterm-kill-buffer-on-exit t)) 18 | 19 | (defun toggle-vterm () 20 | "Toggle vterm buffer." 21 | (interactive) 22 | (if (get-buffer "*vterm*") 23 | (if (eq (current-buffer) (get-buffer "*vterm*")) 24 | (delete-window) 25 | (switch-to-buffer-other-window "*vterm*")) 26 | (progn 27 | (vterm-other-window)))) 28 | 29 | (provide 'mk-term) 30 | ;;; mk-term.el ends here 31 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-fixed-regex.el: -------------------------------------------------------------------------------- 1 | ;;; Test the fixed regex 2 | 3 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'") 4 | (fixed-regex "\\(/[^:]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\)?\\s+\\(\\w+\\):\\s*\\(.*\\)")) 5 | 6 | (message "\n=== FIXED REGEX TEST ===") 7 | (message "Test line: %s" test-line) 8 | (message "Fixed regex: %s" fixed-regex) 9 | 10 | (if (string-match fixed-regex test-line) 11 | (progn 12 | (message "SUCCESS - Fixed regex matches!") 13 | (message "Groups:") 14 | (message " 1 (file): %s" (match-string 1 test-line)) 15 | (message " 2 (line): %s" (match-string 2 test-line)) 16 | (message " 3 (col): %s" (match-string 3 test-line)) 17 | (message " 4 (type): %s" (match-string 4 test-line)) 18 | (message " 5 (msg): %s" (match-string 5 test-line))) 19 | (message "FAILED - Fixed regex still doesn't match!"))) -------------------------------------------------------------------------------- /modules/mk-theme.el: -------------------------------------------------------------------------------- 1 | ;;; mk-theme.el --- My custom Emacs theme configuration -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file contains configurations related to Emacs themes. 4 | ;;; Code: 5 | 6 | (add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory)) 7 | 8 | (use-package autothemer 9 | :ensure t 10 | :init 11 | ;; (load-theme 'catppuccin-mocha t) 12 | ;; (load-theme 'catppuccin-macchiato t) 13 | ;; (load-theme 'catppuccin-frappe t) 14 | ;; (load-theme 'catppuccin-latte t) 15 | ;; (load-theme 'ef-deuteranopia-dark t) 16 | ;; (load-theme 'rose-pine t) 17 | ;; (load-theme 'oxographite t) 18 | ;; (load-theme 'kman t) 19 | ;; (load-theme 'kalmar-night t) 20 | (load-theme 'kanagawa t) 21 | ;; (load-theme 'neofusion t) 22 | ;; (load-theme 'doom-gruvbox t) 23 | ;; (load-theme 'oxocarbon t) 24 | ;; (load-theme 'nordic t) 25 | ;; (load-theme 'poimandres t) 26 | ;; (load-theme 'mito-laser t) 27 | ;; (load-theme 'doom-outrun-electric t) 28 | ;; (load-theme 'doom-laserwave t) 29 | ) 30 | 31 | 32 | (provide 'mk-theme) 33 | ;;; mk-theme.el ends here 34 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-faces.el: -------------------------------------------------------------------------------- 1 | ;;; Test face definitions after reorganization 2 | 3 | ;; Load just the config to test faces 4 | (add-to-list 'load-path "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/") 5 | (require 'periphery-config) 6 | 7 | ;; Test that face definitions are available 8 | (let ((test-faces '(periphery-error-face-full 9 | periphery-warning-face-full 10 | periphery-identifier-face 11 | periphery-message-face 12 | periphery-todo-face-full 13 | periphery-fix-face-full))) 14 | 15 | (message "\n=== FACE TEST ===") 16 | (dolist (face test-faces) 17 | (if (facep face) 18 | (message "✓ Face %s is defined" face) 19 | (message "✗ Face %s NOT defined" face)))) 20 | 21 | ;; Test syntax faces configuration 22 | (if (boundp 'periphery-syntax-faces) 23 | (progn 24 | (message "✓ periphery-syntax-faces is defined") 25 | (message "Syntax faces: %S" periphery-syntax-faces)) 26 | (message "✗ periphery-syntax-faces NOT defined")) 27 | 28 | (message "Face test completed.") -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-highlight-patterns.el: -------------------------------------------------------------------------------- 1 | ;;; Test highlight patterns after moving to config 2 | 3 | ;; Load config 4 | (add-to-list 'load-path "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/") 5 | (require 'periphery-config) 6 | 7 | ;; Test that patterns are available 8 | (message "\n=== HIGHLIGHT PATTERNS TEST ===") 9 | 10 | (if (boundp 'periphery-highlight-patterns) 11 | (progn 12 | (message "✓ periphery-highlight-patterns is defined") 13 | (message "Available patterns: %S" (mapcar #'car periphery-highlight-patterns))) 14 | (message "✗ periphery-highlight-patterns NOT defined")) 15 | 16 | ;; Test adding a new pattern 17 | (periphery-add-highlight-pattern 'brackets "\\(\\[[^]]+\\]\\)" 'periphery-warning-face) 18 | 19 | (message "After adding brackets pattern:") 20 | (message "Patterns: %S" (mapcar #'car periphery-highlight-patterns)) 21 | (message "Faces: %S" (mapcar #'car periphery-syntax-faces)) 22 | 23 | ;; Test that the pattern was added 24 | (let ((bracket-pattern (alist-get 'brackets periphery-highlight-patterns)) 25 | (bracket-face (alist-get 'brackets periphery-syntax-faces))) 26 | (if (and bracket-pattern bracket-face) 27 | (message "✓ Successfully added brackets pattern: %s -> %s" bracket-pattern bracket-face) 28 | (message "✗ Failed to add brackets pattern"))) 29 | 30 | (message "Highlight patterns test completed.") -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-exact-error.el: -------------------------------------------------------------------------------- 1 | ;;; Test exact error from user 2 | 3 | (load-file "periphery-config.el") 4 | (load-file "periphery-core.el") 5 | (load-file "periphery-parsers.el") 6 | 7 | (setq periphery-debug t) 8 | 9 | (let ((error-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'")) 10 | 11 | (message "\nTesting exact error string:") 12 | (message "Input: %s" error-line) 13 | 14 | ;; Test regex 15 | (let ((regex (alist-get 'compiler periphery-builtin-patterns))) 16 | (message "\nRegex: %s" regex) 17 | (if (string-match regex error-line) 18 | (progn 19 | (message "MATCH SUCCESS!") 20 | (message " File (1): %s" (match-string 1 error-line)) 21 | (message " Line (2): %s" (match-string 2 error-line)) 22 | (message " Col (3): %s" (match-string 3 error-line)) 23 | (message " Type (4): %s" (match-string 4 error-line)) 24 | (message " Msg (5): %s" (match-string 5 error-line))) 25 | (message "NO MATCH - REGEX FAILED"))) 26 | 27 | ;; Test parser 28 | (message "\nTesting parser:") 29 | (let ((result (periphery-parser-compiler error-line))) 30 | (if result 31 | (message "Parser worked! Result: %S" result) 32 | (message "Parser returned nil")))) -------------------------------------------------------------------------------- /suppress-warnings.el: -------------------------------------------------------------------------------- 1 | ;;; suppress-warnings.el --- Suppress obsolete warnings -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file completely suppresses obsolete warnings and other annoying messages 4 | 5 | ;;; Code: 6 | 7 | (defun suppress-obsolete-warnings (orig-fun &rest args) 8 | "Filter out obsolete warnings from display-warning." 9 | (let ((_ (car args)) 10 | (message (cadr args))) 11 | (unless (and (stringp message) 12 | (or (string-match-p "obsolete" message) 13 | (string-match-p "defadvice" message) 14 | (string-match-p "when-let" message) 15 | (string-match-p "if-let" message) 16 | (string-match-p "deprecated" message))) 17 | (apply orig-fun args)))) 18 | 19 | (advice-add 'display-warning :around #'suppress-obsolete-warnings) 20 | 21 | ;; Also suppress messages about warnings 22 | (defun suppress-warning-messages (orig-fun &rest args) 23 | "Filter out warning messages from message function." 24 | (let ((msg (car args))) 25 | (unless (and (stringp msg) 26 | (or (string-match-p "Warning:" msg) 27 | (string-match-p "\\.el: Warning:" msg))) 28 | (apply orig-fun args)))) 29 | 30 | (advice-add 'message :around #'suppress-warning-messages) 31 | 32 | (provide 'suppress-warnings) 33 | ;;; suppress-warnings.el ends here 34 | -------------------------------------------------------------------------------- /modules/mk-web.el: -------------------------------------------------------------------------------- 1 | ;;; mk-web.el --- Web development and markup languages -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Configuration for web development including HTML, XML, CSS, JavaScript, and TypeScript. 4 | ;;; Code: 5 | 6 | (use-package nxml-mode 7 | :ensure nil 8 | :mode "\\.xml\\'" 9 | :hook ((nxml-mode . setup-programming-mode) 10 | (nxml-mode . colorful-mode) 11 | (nxml-mode . display-line-numbers-mode))) 12 | 13 | (use-package typescript-ts-mode 14 | :defer t 15 | :hook (typescript-ts-base-mode . (lambda () 16 | (setq-local typescript-ts-indent-level 4 17 | typescript-ts-mode-indent-offset 4 18 | js-indent-level 4))) 19 | :mode (("\\.tsx\\'" . tsx-ts-mode) 20 | ("\\.js\\'" . typescript-ts-mode) 21 | ("\\.mjs\\'" . typescript-ts-mode) 22 | ("\\.mts\\'" . typescript-ts-mode) 23 | ("\\.cjs\\'" . typescript-ts-mode) 24 | ("\\.ts\\'" . typescript-ts-mode) 25 | ("\\.jsx\\'" . tsx-ts-mode))) 26 | 27 | (use-package markdown-mode 28 | :defer t 29 | :ensure t 30 | :commands (markdown-mode gfm-mode) 31 | :mode (("README\\.md\\'" . gfm-mode) 32 | ("\\.md\\'" . markdown-mode) 33 | ("\\.markdown\\'" . markdown-mode)) 34 | :config 35 | (setq markdown-fontify-code-blocks-natively t)) 36 | 37 | (provide 'mk-web) 38 | ;;; mk-web.el ends here -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-highlighting.el: -------------------------------------------------------------------------------- 1 | ;;; Test highlighting function 2 | 3 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery.el") 4 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-parsers.el") 5 | 6 | (setq periphery-debug t) 7 | 8 | ;; Test the highlighting function directly 9 | (let ((test-message "type 'Style.Color' has no member 'primaryElemen'")) 10 | (message "\n=== HIGHLIGHTING TEST ===") 11 | (message "Input: %s" test-message) 12 | 13 | ;; Test periphery--mark-all-symbols directly 14 | (let ((quotes-regex "\\('[^']+'\\)") 15 | (result test-message)) 16 | (message "Quotes regex: %s" quotes-regex) 17 | (if (string-match quotes-regex test-message) 18 | (progn 19 | (message "Regex matches: '%s'" (match-string 1 test-message)) 20 | (setq result (periphery--mark-all-symbols 21 | :input test-message 22 | :regex quotes-regex 23 | :property '(face highlight))) 24 | (message "After highlighting: %s" result) 25 | (message "Text properties: %S" (text-properties-at 5 result))) 26 | (message "Regex doesn't match"))) 27 | 28 | ;; Test the full highlighting function 29 | (let ((highlighted (periphery-parser--apply-highlighting test-message))) 30 | (message "Full highlighting result: %s" highlighted) 31 | (message "Properties at pos 5: %S" (text-properties-at 5 highlighted)) 32 | (message "Properties at pos 15: %S" (text-properties-at 15 highlighted)))) -------------------------------------------------------------------------------- /localpackages/periphery/periphery-loco.el: -------------------------------------------------------------------------------- 1 | ;;; Periphery-loco --- Validate .strings and .swift file and show the result as flycheck list. -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: Package for showing linting as result in a tabulated list 4 | 5 | ;;; Code: 6 | (require 'periphery-helper) 7 | (require 'periphery) 8 | (require 'cl-lib) 9 | 10 | (defvar loco-command "loco") 11 | 12 | (defun send-loco-result-to-periphery (text) 13 | "Let periphery parse the (as TEXT)." 14 | (periphery-run-parser text (lambda () 15 | (message-with-color 16 | :tag "[Success]" 17 | :text "No warning or errors." 18 | :attributes 'success)))) 19 | 20 | (defun periphery-run-loco() 21 | "Run LOCO linter." 22 | (interactive) 23 | (if (executable-find loco-command) 24 | (progn 25 | (let ((default-directory (vc-root-dir))) 26 | (async-shell-command-to-string 27 | :process-name "loco" 28 | :command (concat loco-command " --no-color") 29 | :callback #'send-loco-result-to-periphery)) 30 | (message-with-color 31 | :tag "[Linting|Loco]" 32 | :text (file-name-nondirectory (directory-file-name 33 | (file-name-directory (vc-root-dir)))) 34 | :attributes 'success)) 35 | (message-with-color 36 | :tag "[Failed]" 37 | :text (format "Install %s to use this command." loco-command) 38 | :attributes 'warning))) 39 | 40 | (provide 'periphery-loco) 41 | ;;; periphery-loco.el ends here. 42 | -------------------------------------------------------------------------------- /modules/mk-kotlin-development.el: -------------------------------------------------------------------------------- 1 | ;;; mk-kotlin-development.el --- Kotlin development environment setup -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Configuration for Kotlin development in Emacs, including syntax checking and development tools. 4 | ;;; Code: 5 | 6 | (use-package flycheck-kotlin 7 | :hook ((kotlin-mode kotlin-ts-mode) . flycheck-kotlin-setup)) 8 | 9 | (use-package kotlin-mode 10 | :ensure t 11 | :defer 3 12 | :mode ("\\.kt\\'" "\\.kts\\'")) 13 | 14 | (use-package kotlin-ts-mode 15 | :ensure t 16 | :after kotlin-mode 17 | :mode ("\\.kt\\'" "\\.kts\\'")) 18 | 19 | (use-package kotlin-development 20 | :after kotlin-ts-mode 21 | :hook ((kotlin-mode kotlin-ts-mode) . kotlin-development-mode-setup) 22 | :ensure nil ; if it's a local package 23 | :bind ((:map kotlin-mode-map 24 | ("C-c C-c" . kotlin-development-build-and-run) 25 | ("M-K" . kotlin-development-clean-build) 26 | ("C-c C-e l" . kotlin-development-list-emulators) 27 | ("C-c C-e k" . kotlin-development-kill-emulator)) 28 | (:map kotlin-ts-mode-map 29 | ("C-c r s" . code-refactor:split-function-list) 30 | ("C-c C-c" . kotlin-development-build-and-run) 31 | ("C-c C-e l" . kotlin-development-list-emulators) 32 | ("C-c C-e k" . kotlin-development-kill-emulator))) 33 | :init 34 | (require 'swift-refactor) 35 | :config 36 | (setenv "JAVA_OPTS" "-Xmx8g") 37 | (setq kotlin-development-emulator-name "Medium_Phone_API_35")) 38 | 39 | ;;; Provide 40 | (provide 'mk-kotlin-development) 41 | ;;; mk-kotlin-development.el ends here 42 | -------------------------------------------------------------------------------- /modules/mk-lisp.el: -------------------------------------------------------------------------------- 1 | ;;; mk-lispediting.el --- Emacs Lisp editing enhancements -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file contains configurations and enhancements for editing Emacs Lisp code. 4 | 5 | ;;; Code: 6 | 7 | (use-package page-break-lines 8 | :defer t 9 | :commands (page-break-lines-mode 10 | global-page-break-lines-mode) 11 | :hook 12 | (emacs-lisp-mode . page-break-lines-mode)) 13 | 14 | (use-package aggressive-indent 15 | :defer t 16 | :commands aggressive-indent-mode 17 | :hook 18 | (emacs-lisp-mode . aggressive-indent-mode)) 19 | 20 | (use-package highlight-defined 21 | :ensure t 22 | :defer t 23 | :commands highlight-defined-mode 24 | :hook 25 | (emacs-lisp-mode . highlight-defined-mode)) 26 | 27 | ;; (use-package paredit 28 | ;; :defer t 29 | ;; :commands paredit-mode 30 | ;; :hook 31 | ;; (emacs-lisp-mode . paredit-mode) 32 | ;; :config 33 | ;; (define-key paredit-mode-map (kbd "RET") nil)) 34 | 35 | ;; (use-package semel 36 | ;; :vc (semel 37 | ;; :url "https://github.com/eshelyaron/semel" :rev :newest) 38 | ;; :hook (emacs-lisp-mode . semel-mode)) 39 | 40 | (use-package colorful-mode 41 | :defer t 42 | :ensure t 43 | :hook (emacs-lisp-mode . colorful-mode) 44 | :custom 45 | (colorful-use-prefix t) 46 | (colorful-prefix-alignment 'left) 47 | (colorful-prefix-string "●")) 48 | 49 | (use-package highlight-quoted 50 | :hook 51 | (emacs-lisp-mode-hook . highlight-quoted-mode)) 52 | 53 | ;; (use-package eros 54 | ;; :custom-face 55 | ;; (eros-result-overlay-face ((t (:inherit shadow :box t)))) 56 | ;; :hook 57 | ;; (emacs-lisp-mode-hook . eros-mode)) 58 | 59 | ;;; Provide 60 | (provide 'mk-lisp) 61 | ;;; mk-lisp.el ends here. 62 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-no-space.el: -------------------------------------------------------------------------------- 1 | ;;; Test with no space before error 2 | 3 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'")) 4 | 5 | (message "\n=== NO SPACE TEST ===") 6 | 7 | ;; Test the actual pattern in the line 8 | (let ((after-44 ": error: type 'Style.Color' has no member 'primaryElemen'")) 9 | (message "Testing against: '%s'" after-44) 10 | 11 | ;; No space between : and error 12 | (if (string-match ":\\s*\\(\\w+\\):" after-44) 13 | (message "✓ No space pattern matches: '%s'" (match-string 1 after-44)) 14 | (message "✗ No space pattern FAILS")) 15 | 16 | ;; Literal space 17 | (if (string-match ": \\(\\w+\\):" after-44) 18 | (message "✓ Literal space pattern matches: '%s'" (match-string 1 after-44)) 19 | (message "✗ Literal space pattern FAILS"))) 20 | 21 | ;; Test complete regex with literal space 22 | (let ((regex-literal-space "\\(/[^:]+\\):\\([0-9]+\\):\\([0-9]+\\): \\(\\w+\\): \\(.*\\)")) 23 | (message "\nTesting with literal space: %s" regex-literal-space) 24 | (if (string-match regex-literal-space test-line) 25 | (progn 26 | (message "✓ Literal space regex MATCHES!") 27 | (message "Groups:") 28 | (message " 1 (file): %s" (match-string 1 test-line)) 29 | (message " 2 (line): %s" (match-string 2 test-line)) 30 | (message " 3 (col): %s" (match-string 3 test-line)) 31 | (message " 4 (type): %s" (match-string 4 test-line)) 32 | (message " 5 (msg): %s" (match-string 5 test-line))) 33 | (message "✗ Literal space regex FAILS")))) -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-pattern-management.el: -------------------------------------------------------------------------------- 1 | ;;; Test complete highlight pattern management system 2 | 3 | (add-to-list 'load-path "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/") 4 | (require 'periphery-config) 5 | 6 | (message "\n=== PATTERN MANAGEMENT TEST ===") 7 | 8 | ;; Test initial patterns 9 | (message "Initial patterns: %d" (length periphery-highlight-patterns)) 10 | (periphery-list-highlight-patterns) 11 | 12 | ;; Test adding a pattern 13 | (message "\nAdding 'numbers' pattern...") 14 | (periphery-add-highlight-pattern 'numbers "\\([0-9]+\\)" 'periphery-warning-face) 15 | 16 | ;; Test adding another pattern 17 | (message "\nAdding 'emails' pattern...") 18 | (periphery-add-highlight-pattern 'emails "\\([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\)" 'periphery-info-face) 19 | 20 | (message "\nAfter adding patterns:") 21 | (periphery-list-highlight-patterns) 22 | 23 | ;; Test removing a pattern 24 | (message "\nRemoving 'numbers' pattern...") 25 | (periphery-remove-highlight-pattern 'numbers) 26 | 27 | (message "\nAfter removing numbers pattern:") 28 | (periphery-list-highlight-patterns) 29 | 30 | ;; Test that patterns and faces are properly synced 31 | (let ((pattern-elements (mapcar #'car periphery-highlight-patterns)) 32 | (face-elements (mapcar #'car periphery-syntax-faces))) 33 | (message "\nPattern elements: %S" pattern-elements) 34 | (message "Face elements: %S" face-elements) 35 | 36 | ;; Check if they contain the same elements (order may differ) 37 | (if (and (cl-subsetp pattern-elements face-elements) 38 | (cl-subsetp face-elements pattern-elements)) 39 | (message "✓ Patterns and faces are properly synchronized") 40 | (message "✗ Patterns and faces are NOT synchronized"))) 41 | 42 | (message "\nPattern management test completed.") -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-regex-match.el: -------------------------------------------------------------------------------- 1 | ;;; Test regex against the actual line 2 | 3 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-config.el") 4 | 5 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'") 6 | (regex (alist-get 'compiler periphery-builtin-patterns))) 7 | 8 | (message "\n=== REGEX TEST ===") 9 | (message "Test line: %s" test-line) 10 | (message "Regex: %s" regex) 11 | 12 | (if (string-match regex test-line) 13 | (progn 14 | (message "SUCCESS - Regex matches!") 15 | (message "Groups:") 16 | (message " 1 (file): %s" (match-string 1 test-line)) 17 | (message " 2 (line): %s" (match-string 2 test-line)) 18 | (message " 3 (col): %s" (match-string 3 test-line)) 19 | (message " 4 (type): %s" (match-string 4 test-line)) 20 | (message " 5 (msg): %s" (match-string 5 test-line))) 21 | (message "FAILED - Regex does NOT match!"))) 22 | 23 | ;; Test a simpler pattern too 24 | (let ((simple-regex "\\(/[^:]+\\):\\([0-9]+\\):\\([0-9]+\\):\\s*\\(\\w+\\):\\s*\\(.*\\)")) 25 | (message "\n=== SIMPLE REGEX TEST ===") 26 | (message "Simple regex: %s" simple-regex) 27 | (if (string-match simple-regex test-line) 28 | (progn 29 | (message "Simple regex MATCHES!") 30 | (message "Groups:") 31 | (message " 1: %s" (match-string 1 test-line)) 32 | (message " 2: %s" (match-string 2 test-line)) 33 | (message " 3: %s" (match-string 3 test-line)) 34 | (message " 4: %s" (match-string 4 test-line)) 35 | (message " 5: %s" (match-string 5 test-line))) 36 | (message "Simple regex does NOT match!"))) -------------------------------------------------------------------------------- /localpackages/periphery/periphery-swiftlint.el: -------------------------------------------------------------------------------- 1 | ;;; Periphery-swiftlint -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: Package for showing all swiftlint results abulated list 4 | 5 | ;;; Code: 6 | (require 'periphery-helper) 7 | (require 'periphery) 8 | (require 'cl-lib) 9 | 10 | (defun get-swiftlint-file-root () 11 | "Get the path of the swiftlint file." 12 | (if-let* ((default-directory (periphery-helper:project-root-dir)) 13 | (root (locate-dominating-file default-directory ".swiftlint.yml"))) 14 | root) 15 | default-directory) 16 | 17 | (defun periphery--swiftlint:analyze-result (result) 18 | "Analyze RESULT." 19 | (periphery-run-parser result (lambda () 20 | (message-with-color 21 | :tag "[Success]" 22 | :text "No lint warning or errors." 23 | :attributes 'success)))) 24 | 25 | (defun periphery-run-swiftlint () 26 | "Lint the whole project not just current file." 27 | (interactive) 28 | (if (executable-find "swiftlint") 29 | (progn 30 | (let ((default-directory (get-swiftlint-file-root))) 31 | (async-start-command-to-string 32 | :command "swiftlint" 33 | :callback '(lambda (result) (periphery--swiftlint:analyze-result result)))) 34 | (message-with-color 35 | :tag "[Linting|Swiftlint]" 36 | :text (file-name-nondirectory (directory-file-name (file-name-directory default-directory))) 37 | :attributes 'success)) 38 | (message-with-color 39 | :tag "[Failed]" 40 | :text (format "Install %s to use this command. 'swiftlint'") 41 | :attributes 'warning))) 42 | 43 | (provide 'periphery-swiftlint) 44 | ;;; periphery-swiftlint.el ends here. 45 | 46 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-ktlint.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-ktlint.el --- Validate ktlint-format and show the result as flycheck list. -*- lexical-binding: t; -*- 2 | ;;; Commentary: Package for showing linting as result in a tabulated list 3 | ;;; Code: 4 | (require 'periphery) 5 | (require 'periphery-helper) 6 | (require 'cl-lib) 7 | (require 'mode-line-hud) 8 | 9 | (defvar ktlint-command "ktlint") 10 | (defvar android-kotlin-version "1.9") 11 | 12 | (defun periphery-ktlint-parse (text) 13 | "Parse the output of ktlint and return a list of errors." 14 | (periphery-parse-ktlint-result text)) 15 | 16 | ;;;###autoload 17 | (defun periphery-ktlint-lint-buffer() 18 | "Lint current buffer using ktlint." 19 | (interactive) 20 | (if-let* ((file (buffer-file-name))) 21 | (periphery-run-ktlint-buffer 22 | :command (concat ktlint-command " " file)))) 23 | 24 | ;;;###autoload 25 | (defun periphery-ktlint-autocorrect-buffer() 26 | "Autocorrect current buffer using ktlint." 27 | (interactive) 28 | (mode-line-hud:notification :message (propertize "running ktlint" 'face 'font-lock-keyword-face) :seconds 1) 29 | (save-some-buffers t) 30 | (if-let* ((file (buffer-file-name))) 31 | (periphery-run-ktlint-buffer 32 | :command (concat ktlint-command " -F " file)))) 33 | 34 | (cl-defun periphery-run-ktlint-buffer (&key command) 35 | "Run ktlint for current buffer (as COMMAND FILE)." 36 | (if (executable-find ktlint-command) 37 | (progn 38 | (let ((output (shell-command-to-string command))) 39 | (if (string= output "") 40 | (message "ktlint: No issues found.") 41 | (periphery-ktlint-parse output)))) 42 | (mode-line-hud:notification 43 | :message (propertize "Ktlint not installed" 'face 'font-lock-keyword-face) 44 | :seconds 1))) 45 | 46 | (provide 'periphery-ktlint) 47 | ;;; periphery-ktlint.el ends here 48 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/reload-periphery.el: -------------------------------------------------------------------------------- 1 | ;;; Reload all periphery components 2 | 3 | ;; Clear the parser registry 4 | (setq periphery-registered-parsers (make-hash-table :test 'eq)) 5 | 6 | ;; Reload all files in order 7 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-helper.el") 8 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-config.el") 9 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-core.el") 10 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery-parsers.el") 11 | (load-file "/Users/mikaelkonradsson/.emacs.d/localpackages/periphery/periphery.el") 12 | 13 | ;; Enable debug 14 | (setq periphery-debug t) 15 | 16 | ;; Re-initialize parsers 17 | (periphery-parsers-initialize) 18 | 19 | ;; Test that the parser is working 20 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'")) 21 | (message "\n=== RELOAD TEST ===") 22 | (message "Testing parser after reload...") 23 | 24 | ;; Check if parser is registered 25 | (let ((parser (periphery-get-parser 'compiler))) 26 | (if parser 27 | (message "✓ Compiler parser is registered") 28 | (message "✗ Compiler parser NOT registered"))) 29 | 30 | ;; Test parsing 31 | (let ((result (periphery-parser-compiler test-line))) 32 | (if result 33 | (progn 34 | (message "✓ Parser returns result") 35 | (message "Result: %S" result)) 36 | (message "✗ Parser returns nil"))) 37 | 38 | ;; Test highlighting 39 | (let ((highlighted (periphery-parser--apply-highlighting "type 'Style.Color' has no member 'primaryElemen'"))) 40 | (message "Highlighted: %s" highlighted) 41 | (message "Properties at quote: %S" (text-properties-at 5 highlighted)))) 42 | 43 | (message "Periphery reloaded. Try building now.") -------------------------------------------------------------------------------- /localpackages/periphery/tests/test-periphery.el: -------------------------------------------------------------------------------- 1 | ;;; Quick test for periphery parsing 2 | 3 | (load-file "periphery-config.el") 4 | (load-file "periphery-core.el") 5 | (load-file "periphery-parsers.el") 6 | (load-file "periphery.el") 7 | 8 | ;; Enable debug 9 | (setq periphery-debug t) 10 | 11 | ;; Test simple compiler output 12 | (let ((test-input "/Users/test/file.swift:10:5: error: test error message")) 13 | (message "\n===== Testing Periphery Parsing =====") 14 | (message "Input: %s" test-input) 15 | 16 | ;; Check if parsers are registered 17 | (message "\nRegistered parsers:") 18 | (maphash (lambda (id config) 19 | (message " %s: enabled=%s" id (plist-get config :enabled))) 20 | periphery-registered-parsers) 21 | 22 | ;; Test regex directly 23 | (message "\nTesting regex match:") 24 | (let ((regex (alist-get 'compiler periphery-builtin-patterns))) 25 | (message "Regex: %s" regex) 26 | (if (string-match regex test-input) 27 | (progn 28 | (message "MATCH!") 29 | (message " 1: %s" (match-string 1 test-input)) 30 | (message " 2: %s" (match-string 2 test-input)) 31 | (message " 3: %s" (match-string 3 test-input)) 32 | (message " 4: %s" (match-string 4 test-input)) 33 | (message " 5: %s" (match-string 5 test-input))) 34 | (message "NO MATCH"))) 35 | 36 | ;; Test parser directly 37 | (message "\nTesting parser directly:") 38 | (let ((result (periphery-parser-compiler test-input))) 39 | (if result 40 | (message "Parser result: %S" result) 41 | (message "Parser returned nil"))) 42 | 43 | ;; Test through core 44 | (message "\nTesting through periphery-core-parse:") 45 | (let ((results (periphery-core-parse :input test-input :type :compiler))) 46 | (message "Results: %S" results)) 47 | 48 | ;; Test through periphery-run-parser 49 | (message "\nTesting through periphery-run-parser:") 50 | (periphery-run-parser test-input) 51 | (message "periphery-errorList: %S" periphery-errorList)) -------------------------------------------------------------------------------- /localpackages/music-control/README.md: -------------------------------------------------------------------------------- 1 | # Music Control for Emacs 2 | 3 | Control Apple Music.app directly from Emacs. 4 | 5 | ## Features 6 | 7 | - Play/pause, next/previous track controls 8 | - Browse and play music by artist, album, or playlist 9 | - Display current track information in the modeline 10 | - Volume control 11 | - Customizable display options 12 | 13 | ## Installation 14 | 15 | 1. Clone this repository or copy `music-control.el` to your Emacs load path 16 | 2. Add to your Emacs configuration: 17 | 18 | ```elisp 19 | (require 'music-control) 20 | (music-control-mode 1) ;; Enable the global minor mode 21 | ``` 22 | 23 | ## Key Bindings 24 | 25 | | Key | Function | Description | 26 | |-----------|----------------------------------|----------------------------------| 27 | | `C-c m p` | `music-control-play-pause` | Toggle play/pause | 28 | | `C-c m n` | `music-control-next-track` | Play next track | 29 | | `C-c m b` | `music-control-previous-track` | Play previous track | 30 | | `C-c m a` | `music-control-browse-artist` | Browse and play by artist/album | 31 | | `C-c m l` | `music-control-browse-playlist` | Browse and play from playlists | 32 | | `C-c m i` | `music-control-display-current-track` | Show current track details | 33 | | `C-c m +` | `music-control-volume-up` | Increase volume | 34 | | `C-c m -` | `music-control-volume-down` | Decrease volume | 35 | 36 | ## Customization 37 | 38 | ```elisp 39 | ;; Show current track in modeline 40 | (setq music-control-show-in-modeline t) 41 | 42 | ;; Set modeline update interval (seconds) 43 | (setq music-control-modeline-update-interval 5) 44 | 45 | ;; Set volume adjustment step 46 | (setq music-control-volume-step 5) 47 | ``` 48 | 49 | ## Requirements 50 | 51 | - macOS with Music.app 52 | - Emacs 27.1 or later 53 | - nerd-icons package 54 | 55 | ❤️ [Please sponsor me if you like this package](https://github.com/sponsors/konrad1977) 56 | -------------------------------------------------------------------------------- /init.el: -------------------------------------------------------------------------------- 1 | ;;; init.el --- optimized init file -*- no-byte-compile: t; lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | ;; Personal Emacs configuration with optimized startup and modern packages. 5 | ;; Features include Evil mode, LSP support, project management, and development tools. 6 | 7 | ;;; Code: 8 | 9 | ;; Suppress all warnings when loading packages 10 | ;; Load warning suppression 11 | 12 | (setopt debug-on-error nil) 13 | 14 | (load (expand-file-name "suppress-warnings" user-emacs-directory) nil t) 15 | 16 | (dolist (path (list 17 | (expand-file-name "modules" user-emacs-directory))) 18 | (add-to-list 'load-path path)) 19 | 20 | (require 'mk-core) 21 | (require 'mk-emacs) 22 | (require 'mk-evil) 23 | (require 'mk-completion) 24 | (require 'mk-code-completion) 25 | (require 'mk-development) 26 | (require 'mk-editing) 27 | (require 'mk-ios-development) 28 | ;; ;; (require 'mk-kotlin-development) 29 | (require 'mk-lisp) 30 | (require 'mk-misc) 31 | (require 'mk-org) 32 | (require 'mk-term) 33 | (require 'mk-theme) 34 | (require 'mk-vc) 35 | (require 'mk-treemacs) 36 | (require 'mk-ui) 37 | (require 'mk-ai) 38 | ;; (require 'mk-notifications) 39 | ;; (require 'mk-web) 40 | ;; ;; (require 'mk-elfeed) 41 | 42 | (use-package welcome-dashboard 43 | :ensure nil 44 | :config 45 | (setq welcome-dashboard-latitude 56.7365 46 | welcome-dashboard-longitude 16.2981 47 | welcome-dashboard-use-nerd-icons t 48 | welcome-dashboard-max-number-of-projects 8 49 | welcome-dashboard-show-weather-info t 50 | welcome-dashboard-use-fahrenheit nil 51 | welcome-dashboard-max-left-padding 1 52 | welcome-dashboard-max-number-of-todos 5 53 | welcome-dashboard-path-max-length 70 54 | welcome-dashboard-min-left-padding 10 55 | welcome-dashboard-image-file "~/.emacs.d/themes/emacs.png" 56 | welcome-dashboard-image-width 200 57 | welcome-dashboard-image-height 200 58 | welcome-dashboard-title "Welcome Mikael. Have a great day!") 59 | (welcome-dashboard-create-welcome-hook)) 60 | 61 | (provide 'init) 62 | ;;; init.el ends here 63 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/debug-regex-parts.el: -------------------------------------------------------------------------------- 1 | ;;; Debug each part of the regex 2 | 3 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'")) 4 | 5 | (message "\n=== DETAILED REGEX DEBUG ===") 6 | (message "Test line: %s" test-line) 7 | 8 | ;; Test up to column with optional group 9 | (let ((regex1 "\\(/[^:]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\)?")) 10 | (if (string-match regex1 test-line) 11 | (progn 12 | (message "✓ File+line+optional_col matches") 13 | (message " Match: '%s'" (match-string 0 test-line)) 14 | (message " Groups: file='%s' line='%s' col='%s'" 15 | (match-string 1 test-line) 16 | (match-string 2 test-line) 17 | (match-string 3 test-line))) 18 | (message "✗ File+line+optional_col FAILS"))) 19 | 20 | ;; Test what comes after the column part 21 | (message "Characters after :44 are: '%s'" (substring test-line 104)) 22 | 23 | ;; Test just the severity pattern after :44 24 | (let ((after-col ": error: type 'Style.Color' has no member 'primaryElemen'")) 25 | (message "Testing against: '%s'" after-col) 26 | 27 | ;; Test different space patterns 28 | (if (string-match ":\\s+\\(\\w+\\):" after-col) 29 | (message "✓ Space+word+colon matches: '%s'" (match-string 1 after-col)) 30 | (message "✗ Space+word+colon FAILS")) 31 | 32 | (if (string-match ":\\s*\\(\\w+\\):" after-col) 33 | (message "✓ Optional_space+word+colon matches: '%s'" (match-string 1 after-col)) 34 | (message "✗ Optional_space+word+colon FAILS")) 35 | 36 | (if (string-match ":\\s+\\(\\w+\\):\\s*\\(.*\\)" after-col) 37 | (message "✓ Full pattern matches: type='%s' msg='%s'" 38 | (match-string 1 after-col) (match-string 2 after-col)) 39 | (message "✗ Full pattern FAILS"))) 40 | 41 | ;; Test the complete regex piece by piece 42 | (let ((complete-regex "\\(/[^:]+\\):\\([0-9]+\\):\\([0-9]+\\):\\s+\\(\\w+\\):\\s*\\(.*\\)")) 43 | (message "\nTesting complete regex: %s" complete-regex) 44 | (if (string-match complete-regex test-line) 45 | (message "✓ Complete regex matches!") 46 | (message "✗ Complete regex FAILS")))) -------------------------------------------------------------------------------- /localpackages/periphery/periphery-multiline.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-multiline.el --- Multi-line error reconstruction -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | ;; Handles multi-line compiler output where errors span multiple lines 5 | 6 | ;;; Code: 7 | 8 | (require 'periphery-core) 9 | (require 'cl-lib) 10 | 11 | (defun periphery-parse-multiline-compiler-output (input) 12 | "Parse INPUT that may contain multi-line compiler errors. 13 | Reconstructs split error messages and passes complete lines to the parser." 14 | (let ((lines (split-string input "\n")) 15 | (current-error nil) 16 | (reconstructed-lines '())) 17 | 18 | (dolist (line lines) 19 | (cond 20 | ;; Start of a new error - has path and line number 21 | ((and (string-match "^\\(/[^:]+\\):\\([0-9]+\\):" line) 22 | (not (string-match ":\\s*\\(error\\|warning\\|note\\):" line))) 23 | ;; This line has a path but might be missing the error type 24 | ;; Look ahead to see if we need to combine with next line 25 | (setq current-error line)) 26 | 27 | ;; Continuation of previous line - might have the error type 28 | ((and current-error 29 | (string-match "^\\s*\\(error\\|warning\\|note\\):" line)) 30 | ;; Combine with previous line 31 | (let ((combined (concat current-error " " (string-trim line)))) 32 | (push combined reconstructed-lines)) 33 | (setq current-error nil)) 34 | 35 | ;; Complete error line 36 | ((string-match "^\\(/[^:]+\\):\\([0-9]+\\):\\(?:[0-9]+:\\)?\\s*\\(error\\|warning\\|note\\):" line) 37 | (push line reconstructed-lines) 38 | (setq current-error nil)) 39 | 40 | ;; Regular line, preserve as is 41 | (t 42 | (when current-error 43 | ;; Previous line was incomplete, add it as is 44 | (push current-error reconstructed-lines) 45 | (setq current-error nil)) 46 | (push line reconstructed-lines)))) 47 | 48 | ;; Handle any remaining current-error 49 | (when current-error 50 | (push current-error reconstructed-lines)) 51 | 52 | ;; Join back and parse 53 | (let ((reconstructed (string-join (nreverse reconstructed-lines) "\n"))) 54 | (when periphery-debug 55 | (message "Reconstructed %d lines" (length reconstructed-lines))) 56 | (periphery-core-parse :input reconstructed :type :compiler)))) 57 | 58 | ;; Override the default parser to use multiline handling 59 | (defun periphery-run-parser-multiline (input) 60 | "Parse INPUT with multi-line error handling." 61 | (when periphery-debug 62 | (message "periphery-run-parser-multiline called")) 63 | (let ((errors (periphery-parse-multiline-compiler-output input))) 64 | (setq periphery-errorList errors) 65 | (when (or (periphery--is-buffer-visible) periphery-errorList) 66 | (periphery--listing-command periphery-errorList)) 67 | (not (null periphery-errorList)))) 68 | 69 | (provide 'periphery-multiline) 70 | ;;; periphery-multiline.el ends here -------------------------------------------------------------------------------- /localpackages/periphery/tests/periphery-test.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-test.el --- Test periphery parsing -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | ;; Test file to debug periphery parsing issues 5 | 6 | ;;; Code: 7 | 8 | (require 'periphery) 9 | (require 'periphery-core) 10 | (require 'periphery-parsers) 11 | 12 | (defun periphery-test-compiler-output () 13 | "Test parsing of compiler output." 14 | (interactive) 15 | (let ((periphery-debug t) 16 | (test-output "/Users/test/project/Source/File.swift:42:15: error: cannot find 'someVariable' in scope 17 | someVariable = 42 18 | ^~~~~~~~~~~~ 19 | /Users/test/project/Source/Another.swift:100:5: warning: initialization of immutable value 'unused' was never used 20 | let unused = computeValue() 21 | ^~~")) 22 | 23 | (message "========== TESTING PERIPHERY ==========") 24 | (message "Test output:\n%s" test-output) 25 | 26 | ;; Test direct parser 27 | (message "\n--- Testing direct parser ---") 28 | (let ((lines (split-string test-output "\n"))) 29 | (dolist (line lines) 30 | (message "Line: %s" line) 31 | (let ((result (periphery-parser-compiler line))) 32 | (if result 33 | (message " PARSED: %S" result) 34 | (message " NO MATCH"))))) 35 | 36 | ;; Test through periphery-run-parser 37 | (message "\n--- Testing periphery-run-parser ---") 38 | (let ((result (periphery-run-parser test-output))) 39 | (message "Result: %s" result) 40 | (message "Error list: %S" periphery-errorList)) 41 | 42 | ;; Check registered parsers 43 | (message "\n--- Registered parsers ---") 44 | (let ((compiler-parser (periphery-get-parser 'compiler))) 45 | (message "Compiler parser: %S" compiler-parser)) 46 | 47 | ;; Test regex directly 48 | (message "\n--- Testing regex directly ---") 49 | (let ((regex (alist-get 'compiler periphery-builtin-patterns))) 50 | (message "Regex: %s" regex) 51 | (dolist (line (split-string test-output "\n")) 52 | (when (string-match regex line) 53 | (message "REGEX MATCH on: %s" line) 54 | (message " File: %s" (match-string 1 line)) 55 | (message " Line: %s" (match-string 2 line)) 56 | (message " Col: %s" (match-string 3 line)) 57 | (message " Type: %s" (match-string 4 line)) 58 | (message " Msg: %s" (match-string 5 line))))))) 59 | 60 | (defun periphery-test-simple () 61 | "Test with a very simple error." 62 | (interactive) 63 | (let ((periphery-debug t)) 64 | (message "Testing simple error...") 65 | (periphery-run-parser "/path/to/file.swift:10:5: error: test error message"))) 66 | 67 | (defun periphery-test-check-parsers () 68 | "Check what parsers are registered." 69 | (interactive) 70 | (message "Checking registered parsers...") 71 | (maphash (lambda (id config) 72 | (message "Parser %s: %S" id config)) 73 | periphery-registered-parsers)) 74 | 75 | (provide 'periphery-test) 76 | ;;; periphery-test.el ends here -------------------------------------------------------------------------------- /localpackages/periphery/tests/simple-regex-test.el: -------------------------------------------------------------------------------- 1 | ;;; Simple regex test without loading files 2 | 3 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'") 4 | (regex "\\(/[^:]+\\):\\([0-9]+\\):\\(?:\\([0-9]+\\):\\)?\\s*\\(\\w+\\):\\s*\\(.*\\)")) 5 | 6 | (message "\n=== REGEX TEST ===") 7 | (message "Test line: %s" test-line) 8 | (message "Regex: %s" regex) 9 | 10 | (if (string-match regex test-line) 11 | (progn 12 | (message "SUCCESS - Regex matches!") 13 | (message "Groups:") 14 | (message " 1 (file): %s" (match-string 1 test-line)) 15 | (message " 2 (line): %s" (match-string 2 test-line)) 16 | (message " 3 (col): %s" (match-string 3 test-line)) 17 | (message " 4 (type): %s" (match-string 4 test-line)) 18 | (message " 5 (msg): %s" (match-string 5 test-line))) 19 | (message "FAILED - Regex does NOT match!"))) 20 | 21 | ;; Test without optional column 22 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'") 23 | (regex2 "\\(/[^:]+\\):\\([0-9]+\\):\\([0-9]+\\):\\s*\\(\\w+\\):\\s*\\(.*\\)")) 24 | 25 | (message "\n=== REGEX TEST 2 (required column) ===") 26 | (message "Regex2: %s" regex2) 27 | 28 | (if (string-match regex2 test-line) 29 | (progn 30 | (message "SUCCESS - Regex2 matches!") 31 | (message "Groups:") 32 | (message " 1 (file): %s" (match-string 1 test-line)) 33 | (message " 2 (line): %s" (match-string 2 test-line)) 34 | (message " 3 (col): %s" (match-string 3 test-line)) 35 | (message " 4 (type): %s" (match-string 4 test-line)) 36 | (message " 5 (msg): %s" (match-string 5 test-line))) 37 | (message "FAILED - Regex2 does NOT match!"))) 38 | 39 | ;; Test each part step by step 40 | (let ((test-line "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'")) 41 | (message "\n=== STEP BY STEP TEST ===") 42 | 43 | ;; Test just the file part 44 | (if (string-match "\\(/[^:]+\\)" test-line) 45 | (message "File part matches: %s" (match-string 1 test-line)) 46 | (message "File part FAILS")) 47 | 48 | ;; Test file + line 49 | (if (string-match "\\(/[^:]+\\):\\([0-9]+\\)" test-line) 50 | (message "File+line matches: %s:%s" (match-string 1 test-line) (match-string 2 test-line)) 51 | (message "File+line FAILS")) 52 | 53 | ;; Test file + line + column 54 | (if (string-match "\\(/[^:]+\\):\\([0-9]+\\):\\([0-9]+\\)" test-line) 55 | (message "File+line+col matches: %s:%s:%s" (match-string 1 test-line) (match-string 2 test-line) (match-string 3 test-line)) 56 | (message "File+line+col FAILS")) 57 | 58 | ;; Test the severity part 59 | (if (string-match ":\\s*\\(\\w+\\):" test-line) 60 | (message "Severity matches: %s" (match-string 1 test-line)) 61 | (message "Severity FAILS"))) -------------------------------------------------------------------------------- /modules/mk-vc.el: -------------------------------------------------------------------------------- 1 | ;;; mk-vc.el --- Version Control Configuration -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Configuration for version control systems in Emacs using Magit, Git Gutter, 4 | 5 | ;;; Code: 6 | 7 | ;; Ensure transient is installed and loaded before magit 8 | (unless (package-installed-p 'transient) 9 | (package-install 'transient)) 10 | (require 'transient) 11 | 12 | (use-package magit 13 | :ensure t 14 | :after (transient evil-collection) 15 | :commands (magit-status magit-ediff-show-working-tree) 16 | :custom 17 | (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1) 18 | :init 19 | (setq magit-save-repository-buffers nil 20 | magit-repository-directories nil) 21 | :config 22 | (require 'magit-section) 23 | (setq magit-format-file-function #'magit-format-file-nerd-icons 24 | magit-diff-refine-hunk 'all) 25 | (evil-collection-init 'magit)) 26 | 27 | (use-package git-timemachine 28 | :ensure t 29 | :defer t 30 | :commands (git-timemachine git-timemachine-toggle)) 31 | 32 | ;; (use-package git-gutter 33 | ;; :defer 5 34 | ;; :hook (prog-mode . git-gutter-mode) 35 | ;; :diminish git-gutter-mode 36 | ;; :config 37 | ;; (setq git-gutter:modified-sign "┃" 38 | ;; git-gutter:added-sign "┃" 39 | ;; git-gutter:deleted-sign "┃") 40 | ;; (setq git-gutter:window-width 1) ;; Set to minimum width 41 | ;; (setq git-gutter:update-interval 3)) 42 | 43 | (use-package consult-gh 44 | :after consult 45 | :defer t 46 | :config 47 | (consult-gh-enable-default-keybindings)) 48 | 49 | (use-package diff-hl 50 | :defer t 51 | :ensure t 52 | :after prog-mode 53 | :hook 54 | (prog-mode . (lambda () 55 | ;; (global-diff-hl-mode) ;; Enable Diff-HL mode for all files. 56 | ;; (diff-hl-flydiff-mode) ;; Automatically refresh diffs. 57 | (diff-hl-margin-mode))) ;; Show diff indicators in the margin. 58 | :custom 59 | (diff-hl-side 'left) ;; Set the side for diff indicators. 60 | (diff-hl-margin-symbols-alist '((insert . "┃") ;; Customize symbols for each change type. 61 | (delete . "-") 62 | (change . "┃") 63 | (unknown . "┆") 64 | (ignored . "i")))) 65 | 66 | 67 | ;; 68 | ;; (use-package blamer 69 | ;; :commands blamer-mode 70 | ;; :config 71 | ;; (setq blamer-tooltip-function 'blamer-tooltip-author-info) 72 | ;; (setq blamer-view 'overlay 73 | ;; blamer-type 'overlay-popup 74 | ;; blamer-max-commit-message-length 270 75 | ;; blamer-force-truncate-long-line nil 76 | ;; blamer-show-avatar-p t 77 | ;; blamer-author-formatter " ✎ %s " 78 | ;; blamer-commit-formatter "● \'%s\' ● ") 79 | ;; :custom 80 | ;; (blamer-idle-time 1.0) 81 | ;; :custom-face 82 | ;; (blamer-face ((t :foreground "#E46876" 83 | ;; :height 130 84 | ;; :bold t 85 | ;; :italic t)))) 86 | ;; 87 | 88 | ;;; Provide 89 | (provide 'mk-vc) 90 | ;;; mk-vc.el ends here. 91 | -------------------------------------------------------------------------------- /localpackages/domain-blocker.el: -------------------------------------------------------------------------------- 1 | ;;; domain-blocker.el --- Block/unblock domains via /etc/hosts -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | ;; A simple package to manage domain blocking via /etc/hosts file. 5 | ;; Useful for development environments where you need to temporarily 6 | ;; block certain domains. 7 | 8 | ;;; Code: 9 | 10 | (defgroup domain-blocker nil 11 | "Domain blocking utilities." 12 | :group 'tools 13 | :prefix "domain-blocker-") 14 | 15 | (defcustom domain-blocker-target-domain "developerservices2.apple.com" 16 | "The domain to block/unblock." 17 | :type 'string 18 | :group 'domain-blocker) 19 | 20 | (defvar domain-blocker-hosts-backup nil 21 | "Temporary backup of /etc/hosts content.") 22 | 23 | (defvar domain-blocker-debug nil 24 | "Enable debug output when non-nil.") 25 | 26 | (defun domain-blocker-log (format-string &rest args) 27 | "Log debug message using FORMAT-STRING and ARGS when debug is enabled." 28 | (when domain-blocker-debug 29 | (apply #'message (concat "[Domain Blocker Debug] " format-string) args))) 30 | 31 | 32 | ;;;###autoload 33 | (defun domain-blocker-block () 34 | "Block domain by adding it to /etc/hosts." 35 | (interactive) 36 | (unless domain-blocker-target-domain 37 | (error "No target domain specified")) 38 | (domain-blocker-log "Attempting to block domain: %s" domain-blocker-target-domain) 39 | (unless (domain-blocker-is-blocked-p) 40 | (let ((command (format "osascript -e 'do shell script \"echo \\\"127.0.0.1 %s\\\" >> /etc/hosts\" with administrator privileges'" 41 | domain-blocker-target-domain))) 42 | (call-process-shell-command command nil 1) 43 | (domain-blocker-log "Blocking domain command initiated")))) 44 | 45 | ;;;###autoload 46 | (defun domain-blocker-unblock () 47 | "Unblock domain by removing it from /etc/hosts." 48 | (interactive) 49 | (domain-blocker-log "Attempting to unblock domain") 50 | (when domain-blocker-target-domain 51 | (let ((command (format "osascript -e 'do shell script \"awk '!/%s/' /etc/hosts > /tmp/hosts.tmp && cp /tmp/hosts.tmp /etc/hosts\" with administrator privileges'" 52 | (regexp-quote domain-blocker-target-domain)))) 53 | (call-process-shell-command command nil 0) 54 | (domain-blocker-log "Unblocking domain command initiated")))) 55 | 56 | ;;;###autoload 57 | (defun domain-blocker-is-blocked-p () 58 | "Check if the target domain is currently blocked." 59 | (when domain-blocker-target-domain 60 | (with-temp-buffer 61 | (insert-file-contents "/etc/hosts") 62 | (goto-char (point-min)) 63 | (search-forward domain-blocker-target-domain (point-max) t)))) 64 | 65 | ;;;###autoload 66 | (defun domain-blocker-status () 67 | "Show the current blocking status of the target domain." 68 | (interactive) 69 | (if domain-blocker-target-domain 70 | (message "Domain %s is currently %s" 71 | domain-blocker-target-domain 72 | (if (domain-blocker-is-blocked-p) 73 | "BLOCKED" 74 | "NOT BLOCKED")) 75 | (message "No target domain specified"))) 76 | 77 | (defun domain-blocker--cleanup () 78 | "Cleanup any temporary files and restore /etc/hosts if needed." 79 | (when domain-blocker-hosts-backup 80 | (domain-blocker-unblock))) 81 | 82 | ;; Ensure cleanup on Emacs exit 83 | (add-hook 'kill-emacs-hook #'domain-blocker--cleanup) 84 | 85 | (provide 'domain-blocker) 86 | ;;; domain-blocker.el ends here 87 | -------------------------------------------------------------------------------- /modules/mk-treemacs.el: -------------------------------------------------------------------------------- 1 | ;;; mk-treemacs.el --- Treemacs configuration -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Treemacs configuration with Nerd Icons and integration with Magit. 4 | ;;; Code: 5 | 6 | (use-package treemacs 7 | :defer t 8 | :commands (treemacs treemacs-select-window) 9 | :hook ((treemacs-mode . treemacs-project-follow-mode)) 10 | :bind (("M-J" . #'treemacs-find-file) 11 | ("M-0" . #'treemacs)) 12 | :config 13 | (let* ((font-family "SF Pro Display") 14 | (font-height 0.8)) 15 | (custom-set-faces 16 | `(treemacs-directory-face ((t (:family ,font-family :height ,font-height)))) 17 | `(treemacs-directory-opened-face ((t (:family ,font-family :height ,font-height)))) 18 | `(treemacs-directory-closed-face ((t (:family ,font-family :height ,font-height)))) 19 | `(treemacs-file-face ((t (:family ,font-family :height ,font-height)))) 20 | `(treemacs-file-collapsed-face ((t (:family ,font-family :height ,font-height)))) 21 | `(treemacs-tags-face ((t (:family ,font-family :height ,font-height)))) 22 | `(treemacs-directory-collapsed-face ((t (:family ,font-family :height ,font-height)))) 23 | `(treemacs-git-ignored-face ((t (:family ,font-family :height ,font-height :slant italic)))) 24 | `(treemacs-git-conflict-face ((t (:family ,font-family :height ,font-height :slant italic)))) 25 | `(treemacs-git-unmodified-face ((t (:family ,font-family :height ,font-height)))) 26 | `(treemacs-git-untracked-face ((t (:family ,font-family :height ,font-height)))) 27 | `(treemacs-git-added-face ((t (:family ,font-family :height ,font-height)))) 28 | `(treemacs-git-deleted-face ((t (:family ,font-family :height ,font-height)))) 29 | `(treemacs-git-renamed-face ((t (:family ,font-family :height ,font-height)))) 30 | `(treemacs-git-modified-face ((t (:family ,font-family :height ,font-height)))) 31 | `(treemacs-tags-face ((t (:family ,font-family :height ,font-height)))))) 32 | (setq treemacs-follow-after-init t 33 | treemacs-hide-gitignored-files-mode t 34 | treemacs-hide-dot-git-directory t 35 | treemacs-space-between-root-nodes 10 36 | treemacs-project-follow-cleanup t 37 | treemacs-width-is-initially-locked nil 38 | treemacs-collapse-dirs 3 39 | treemacs-display-in-side-window t 40 | treemacs-is-never-other-window nil 41 | treemacs-indentation 2 42 | treemacs-indentation-string " " 43 | treemacs-filewatch-mode t 44 | treemacs-git-mode 'deferred 45 | treemacs-move-files-by-mouse-dragging nil 46 | treemacs-move-forward-on-expand t 47 | treemacs-pulse-on-success t 48 | treemacs-file-event-delay 0 49 | treemacs-deferred-git-apply-delay 0 50 | treemacs-git-commit-diff-mode 1 51 | treemacs-show-hidden-files nil 52 | treemacs-sorting 'treemacs--sort-alphabetic-case-insensitive-asc 53 | treemacs-width 40)) 54 | 55 | (use-package treemacs-nerd-icons 56 | :after treemacs 57 | :functions treemacs-load-theme 58 | :preface 59 | (defun treemacs--propagate-new-icons (_theme)) 60 | :custom-face (cfrs-border-color ((t (:inherit posframe-border)))) 61 | :config (treemacs-load-theme "nerd-icons")) 62 | 63 | (use-package treemacs-magit 64 | :after treemacs magit) 65 | 66 | (use-package treemacs-evil 67 | :after (treemacs evil)) 68 | 69 | (use-package project-treemacs 70 | :after treemacs) 71 | 72 | (provide 'mk-treemacs) 73 | ;;; mk-treemacs.el ends here 74 | -------------------------------------------------------------------------------- /localpackages/periphery/tests/debug-full-chain.el: -------------------------------------------------------------------------------- 1 | ;;; Debug the full parsing chain 2 | 3 | ;; Load all components 4 | (load-file "periphery-config.el") 5 | (load-file "periphery-core.el") 6 | (load-file "periphery-parsers.el") 7 | (load-file "periphery-helper.el") 8 | (load-file "periphery.el") 9 | 10 | (setq periphery-debug t) 11 | 12 | (message "\n===== DEBUGGING FULL PARSING CHAIN =====\n") 13 | 14 | ;; Your exact error 15 | (defvar test-error "/Users/mikaelkonradsson/Documents/git/bruce/bruce-ios/Bruce/Screens/Classes/Views/ClassesDateHeader.swift:17:44: error: type 'Style.Color' has no member 'primaryElemen'") 16 | 17 | ;; Step 1: Check if parsers are initialized 18 | (message "Step 1: Checking parser registration") 19 | (message "Number of registered parsers: %d" (hash-table-count periphery-registered-parsers)) 20 | (let ((compiler-parser (gethash 'compiler periphery-registered-parsers))) 21 | (if compiler-parser 22 | (progn 23 | (message "Compiler parser found:") 24 | (message " Name: %s" (plist-get compiler-parser :name)) 25 | (message " Type: %s" (plist-get compiler-parser :type)) 26 | (message " Enabled: %s" (plist-get compiler-parser :enabled)) 27 | (message " Parse-fn: %s" (plist-get compiler-parser :parse-fn))) 28 | (message "ERROR: Compiler parser NOT FOUND!"))) 29 | 30 | ;; Step 2: Test the regex directly 31 | (message "\nStep 2: Testing regex match") 32 | (let ((regex (alist-get 'compiler periphery-builtin-patterns))) 33 | (message "Regex: %s" regex) 34 | (if (string-match regex test-error) 35 | (message "Regex MATCHES") 36 | (message "ERROR: Regex does NOT match"))) 37 | 38 | ;; Step 3: Test the parser function directly 39 | (message "\nStep 3: Testing parser function") 40 | (let ((result (periphery-parser-compiler test-error))) 41 | (if result 42 | (progn 43 | (message "Parser returned a result:") 44 | (message " Result type: %s" (type-of result)) 45 | (message " Result: %S" result)) 46 | (message "ERROR: Parser returned nil"))) 47 | 48 | ;; Step 4: Test periphery-core-build-entry 49 | (message "\nStep 4: Testing periphery-core-build-entry") 50 | (let ((entry (periphery-core-build-entry 51 | :path "/test/file.swift:10:5" 52 | :file "/test/file.swift" 53 | :line "10" 54 | :column "5" 55 | :severity "error" 56 | :message "test message" 57 | :face-fn (lambda (s) 'periphery-error-face)))) 58 | (message "Built entry: %S" entry)) 59 | 60 | ;; Step 5: Test through periphery-core-parse 61 | (message "\nStep 5: Testing periphery-core-parse") 62 | (let ((results (periphery-core-parse :input test-error :type :compiler))) 63 | (message "Core parse results: %d items" (length results)) 64 | (when results 65 | (message "First result: %S" (car results)))) 66 | 67 | ;; Step 6: Test through periphery-run-parser 68 | (message "\nStep 6: Testing periphery-run-parser") 69 | (setq periphery-errorList nil) 70 | (let ((has-errors (periphery-run-parser test-error))) 71 | (message "periphery-run-parser returned: %s" has-errors) 72 | (message "periphery-errorList has %d items" (length periphery-errorList)) 73 | (when periphery-errorList 74 | (message "First error: %S" (car periphery-errorList)))) 75 | 76 | ;; Step 7: Check if the display buffer would show 77 | (message "\nStep 7: Checking display") 78 | (if (get-buffer periphery-buffer-name) 79 | (message "Buffer %s exists" periphery-buffer-name) 80 | (message "Buffer %s does not exist" periphery-buffer-name)) -------------------------------------------------------------------------------- /modules/mk-core.el: -------------------------------------------------------------------------------- 1 | ;;; early-init.el --- summary -*- lexical-binding: t; no-byte-compile: t; mode: emacs-lisp; coding:utf-8; fill-column: 80 -*- 2 | ;;; Commentary: 3 | ;; Early initialization file to optimize Emacs startup performance. 4 | 5 | ;;; Code: 6 | 7 | (eval-when-compile 8 | (defvar display-time-24hr-format t) 9 | (defvar display-time-default-load-average nil)) 10 | 11 | ;; Bootstrap use-package 12 | (unless (package-installed-p 'use-package) 13 | (package-refresh-contents) 14 | (package-install 'use-package)) 15 | 16 | (require 'use-package-ensure) ;; Load use-package-always-ensure 17 | 18 | (use-package use-package 19 | :ensure t 20 | :custom 21 | (use-package-always-defer nil) 22 | (use-package-verbose nil) 23 | (use-package-minimum-reported-time 0) 24 | (use-package-expand-minimally t) 25 | (use-package-compute-statistics t) 26 | (use-package-always-ensure t) 27 | (use-package-enable-imenu-support t)) 28 | 29 | (require 'package) 30 | 31 | (setopt package-archives '(("melpa" . "https://melpa.org/packages/") 32 | ("nongnu" . "https://elpa.nongnu.org/nongnu/") 33 | ("gnu" . "https://elpa.gnu.org/packages/")) 34 | package-archive-priorities '(("gnu" . 99) 35 | ("nongnu" . 85) 36 | ("melpa" . 75))) 37 | (package-initialize) 38 | (when (package-installed-p 'compat) 39 | (require 'compat nil t)) 40 | 41 | (dolist (path (list 42 | (expand-file-name "localpackages/kanagawa-emacs" user-emacs-directory) 43 | (expand-file-name "localpackages/mito-laser-emacs" user-emacs-directory) 44 | (expand-file-name "localpackages/neofusion-emacs" user-emacs-directory))) 45 | (add-to-list 'custom-theme-load-path path)) 46 | 47 | 48 | ;; Add local packages directory to load-path 49 | (let ((dir (expand-file-name "localpackages" user-emacs-directory))) 50 | (when (file-directory-p dir) 51 | (add-to-list 'load-path dir) 52 | (let ((default-directory dir)) 53 | (normal-top-level-add-subdirs-to-load-path)))) 54 | 55 | (let ((paths '("/opt/homebrew/bin" 56 | "/opt/homebrew/sbin" 57 | "/usr/local/bin" 58 | "/System/Cryptexes/App/usr/bin" 59 | "/usr/bin" 60 | "/bin" 61 | "/usr/sbin" 62 | "/Library/TeX/texbin" 63 | "/sbin" 64 | "~/.local/bin" 65 | "~/.nvm/versions/node/v22.11.0/bin" 66 | "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin" 67 | "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin" 68 | "/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin"))) 69 | (setenv "PATH" (string-join paths ":")) 70 | (setq exec-path paths)) 71 | 72 | (global-unset-key (kbd "C-")) 73 | (global-unset-key (kbd "C-")) 74 | (global-unset-key [C-wheel-up]) 75 | (global-unset-key [C-wheel-down]) 76 | (global-set-key (kbd "M-w") 'ns-do-hide-emacs) 77 | 78 | (use-package auto-compile 79 | :ensure t 80 | :defer 1 81 | :custom 82 | (auto-compile-display-buffer nil) 83 | (auto-compile-mode-line-counter nil) 84 | (auto-compile-use-mode-line nil) 85 | (auto-compile-update-autoloads t) 86 | :config 87 | (auto-compile-on-load-mode) 88 | (auto-compile-on-save-mode)) 89 | 90 | (use-package nerd-icons 91 | :defer t 92 | :demand t) 93 | 94 | (provide 'mk-core) 95 | ;;; mk-core.el ends here 96 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-swiftformat.el: -------------------------------------------------------------------------------- 1 | ;;; Periphery-swiftformat --- Validate swift-format and show the result as flycheck list. -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | ;;; Package for showing linting as result in a tabulated list 5 | 6 | ;;; Code: 7 | 8 | (require 'periphery) 9 | (require 'periphery-helper) 10 | (require 'cl-lib) 11 | (require 'mode-line-hud) 12 | 13 | (defvar swiftformat-command "swiftformat") 14 | (defvar swift-version "6.0") 15 | (defvar disabled-rules-list '( 16 | "blankLinesAroundMark" 17 | "blankLinesAtStartOfScope" 18 | "trailingCommas" 19 | "unusedArguments" 20 | "wrapArguments" 21 | "wrapMultilineStatementBraces" 22 | )) 23 | 24 | (defun send-swiftformat-result-to-periphery (text) 25 | "Let periphery parse the (as TEXT)." 26 | (periphery-run-parser text)) 27 | 28 | (defun periphery--create-disable-rules-list (list) 29 | "Create disable block for swift format (as LIST)." 30 | (if (> (length list) 0) 31 | (concat "--disable " (mapconcat 'identity list ",")) 32 | "")) 33 | 34 | (cl-defun periphery-run-swiftformat-buffer (&key command &key file) 35 | "Run swiftformat for current buffer (as COMMAND FILE)." 36 | (if (executable-find swiftformat-command) 37 | (progn 38 | (mode-line-hud:notification :message 39 | (format "Formatting %s" 40 | (propertize (file-name-sans-extension (file-name-nondirectory file)) 'face 'success)) 41 | :seconds 3) 42 | 43 | (async-start-command-to-string 44 | :command command 45 | :callback '(lambda (result) 46 | (send-swiftformat-result-to-periphery result)))) 47 | 48 | (mode-line-hud:notification 49 | :message (propertize "Swiftformat not installed" 'face 'font-lock-keyword-face) 50 | :seconds 2))) 51 | 52 | ;;;###autoload 53 | (defun periphery-swiftformat-lint-buffer() 54 | "Lint current buffer using swiftsyntax." 55 | (interactive) 56 | (if-let* ((file (buffer-file-name))) 57 | (periphery-run-swiftformat-buffer 58 | :command (concat swiftformat-command " " file " --lint " (periphery--create-disable-rules-list disabled-rules-list) " --swiftversion " swift-version) 59 | :file file))) 60 | 61 | ;;;###autoload 62 | (defun periphery-swiftformat-autocorrect-buffer() 63 | "Autocorrect current buffer using swiftsyntax." 64 | (interactive) 65 | (save-some-buffers t) 66 | (if-let* ((file (buffer-file-name))) 67 | (periphery-run-swiftformat-buffer 68 | :command (concat swiftformat-command " " file " " (periphery--create-disable-rules-list disabled-rules-list) " --swiftversion " swift-version) 69 | :file file))) 70 | 71 | ;;;###autoload 72 | (defun periphery-run-swiftformat-for-project() 73 | "Run LOCO linter." 74 | (interactive) 75 | (if (executable-find swiftformat-command) 76 | (progn 77 | (let ((default-directory (periphery-helper:project-root-dir))) 78 | (async-start-command-to-string 79 | :command (concat swiftformat-command " . --lint " (periphery--create-disable-rules-list disabled-rules-list) " --swiftversion " swift-version) 80 | :callback '(lambda (result) 81 | (send-swiftformat-result-to-periphery result)))) 82 | 83 | (mode-line-hud:notification :message 84 | (format "Formatting %s" 85 | (propertize (file-name-nondirectory (directory-file-name (file-name-directory (vc-root-dir)))))) 86 | :seconds 2)) 87 | 88 | (mode-line-hud:update :message (propertize "Swiftformat not installed" 'face 'font-lock-keyword-face)))) 89 | 90 | (provide 'periphery-swiftformat) 91 | 92 | ;;; periphery-swiftformat.el ends here. 93 | -------------------------------------------------------------------------------- /early-init.el: -------------------------------------------------------------------------------- 1 | ;;; early-init.el --- summary -*- lexical-binding: t; no-byte-compile: t; mode: emacs-lisp; coding:utf-8; fill-column: 80 -*- 2 | 3 | ;;; Commentary: 4 | ;; Emacs early initialization file loaded before package system and UI. 5 | ;; Optimized for maximum performance and minimal startup time. 6 | 7 | ;;; Code: 8 | 9 | ;; ;; Must be set very early to suppress all warnings 10 | (setq package-enable-at-startup nil) 11 | (setq warning-minimum-level :error) 12 | (setq byte-compile-warnings nil) 13 | (setq warning-suppress-types '((comp) (bytecomp) (obsolete))) 14 | (setq warning-suppress-log-types '((comp) (bytecomp) (obsolete))) 15 | (setq-default mode-line-format nil) 16 | 17 | (defvar file-name-handler-alist-original file-name-handler-alist) 18 | (setq file-name-handler-alist nil) 19 | 20 | (setopt native-comp-async-report-warnings-errors nil) 21 | 22 | ;; Native-comp settings 23 | (setopt native-comp-speed 2) 24 | (setopt native-comp-deferred-compilation t) 25 | 26 | (setopt frame-inhibit-implied-resize t 27 | frame-title-format "\n" 28 | gc-cons-threshold most-positive-fixnum 29 | inhibit-compacting-font-caches t 30 | inhibit-default-init t 31 | inhibit-splash-screen t 32 | inhibit-startup-buffer-menu t 33 | inhibit-startup-echo-area-message t 34 | inhibit-startup-message t 35 | inhibit-startup-screen t 36 | initial-buffer-choice nil 37 | initial-major-mode 'fundamental-mode 38 | initial-scratch-message nil 39 | message-log-max nil 40 | default-directory "~/" 41 | read-process-output-max (* 8 1024 1024) 42 | default-frame-alist '((background-color . "#13131a") 43 | (foreground-color . "#a0a0ae") 44 | (vertical-scroll-bars . nil) 45 | (min-height . 1) 46 | (min-width . 1) 47 | (height . 45) 48 | (width . 81) 49 | (internal-border-width . 24) 50 | (left-fringe . 1) 51 | (right-fringe . 1) 52 | (horizontal-scroll-bars . nil) 53 | (mac-transparent-titlebar . t) 54 | (ns-transparent-titlebar . t) 55 | (undecorated-round . t) 56 | (fullscreen . maximized))) 57 | 58 | ;; And set these to nil so users don't have to toggle the modes twice to 59 | ;; reactivate them. 60 | (setopt tool-bar-mode nil 61 | menu-bar-mode nil 62 | tooltip-mode nil 63 | scroll-bar-mode nil) 64 | 65 | ;; (add-hook 'window-setup-hook 'toggle-frame-maximized t) 66 | 67 | ;; ;; ;; Font settings with error handling 68 | (condition-case nil 69 | (let ((mono-font "Iosevka Fixed Curly") 70 | (variable-font "Iosevka Aile")) 71 | (set-face-attribute 'default nil :family mono-font :width 'condensed :weight 'extra-light :height 180) 72 | (set-face-attribute 'fixed-pitch nil :family mono-font) 73 | (set-face-attribute 'variable-pitch nil :family variable-font :height 1.0)) 74 | (error nil)) 75 | 76 | ;; Emoji font fallback 77 | (set-fontset-font t 'unicode (font-spec :family "Apple Color Emoji") nil 'append) 78 | ;; restore threshold to normal value after startup 79 | (add-hook 'emacs-startup-hook 80 | (lambda () 81 | ;; Restore file handlers and GC settings 82 | (setq file-name-handler-alist file-name-handler-alist-original 83 | gc-cons-threshold (* 256 1024 1024) 84 | gc-cons-percentage 0.2) 85 | 86 | ;; Schedule periodic GC during idle time 87 | (run-with-idle-timer 5 t (lambda () 88 | (let ((inhibit-message t)) 89 | (garbage-collect)))) 90 | 91 | ;; Log startup time 92 | (message "Emacs started in %s with %d garbage collections." 93 | (format "%.2f seconds" 94 | (float-time 95 | (time-subtract after-init-time before-init-time))) 96 | gcs-done)) 97 | 100) 98 | 99 | (provide 'early-init) 100 | ;;; early-init.el ends here 101 | -------------------------------------------------------------------------------- /modules/mk-elfeed.el: -------------------------------------------------------------------------------- 1 | ;;; mk-elfeed.el --- Elfeed configuration -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Configuration for Elfeed RSS reader with custom icons and tags. 4 | ;;; Code: 5 | 6 | (use-package restclient 7 | :defer t) 8 | 9 | (use-package elfeed 10 | :commands elfeed 11 | :config 12 | 13 | (defun add-icon-to-title (icon tag all-tags title) 14 | "Add ICON if TAG is present in ALL-TAGS to the TITLE string." 15 | (if (member tag all-tags) 16 | (concat icon " ") 17 | "")) 18 | ; 19 | (defun my/elfeed-search-print-entry (entry) 20 | "Print ENTRY to the buffer." 21 | (let* ((date (elfeed-search-format-date (elfeed-entry-date entry))) 22 | (title (or (elfeed-meta entry :title) (elfeed-entry-title entry) "")) 23 | (title-faces (if (member 'unread (elfeed-entry-tags entry)) 24 | (elfeed-search--faces (elfeed-entry-tags entry)) 25 | '(:weight thin :inherit font-lock-comment-face))) 26 | (feed (elfeed-entry-feed entry)) 27 | (feed-title (when feed 28 | (or (elfeed-meta feed :title) (elfeed-feed-title feed)))) 29 | (tags (seq-filter 30 | (lambda (tag) (not (string-equal feed-title tag))) 31 | (mapcar #'symbol-name (elfeed-entry-tags entry)))) 32 | (icons '(("swift" . "") 33 | ("swiftui" . "") 34 | ("emacs" . "") 35 | ("neovim" . "") 36 | ("artificialInteligence" . "") 37 | ("singularity" . "") 38 | ("kotlin" . "") 39 | ("techcrunch" . ""))) 40 | (title-with-icons (concat 41 | (mapconcat 42 | (lambda (icon-pair) 43 | (add-icon-to-title (cdr icon-pair) (car icon-pair) tags " ")) 44 | icons "") 45 | " " 46 | title)) 47 | (tags-str (mapconcat 48 | (lambda (s) (propertize s 'face 'elfeed-search-tag-face)) 49 | tags ",")) 50 | (title-width (- (window-width) 10 elfeed-search-trailing-width)) 51 | (title-column (elfeed-format-column 52 | title-with-icons (elfeed-clamp 53 | elfeed-search-title-min-width 54 | title-width 55 | elfeed-search-title-max-width) 56 | :left))) 57 | (insert (propertize date 'face 'elfeed-search-date-face) " ") 58 | (insert (propertize title-column 'face title-faces 'kbd-help title) " ") 59 | ;; (when feed-title 60 | ;; (insert (propertize feed-title 'face 'elfeed-search-feed-face) " ")) 61 | (when tags 62 | (insert tags-str)))) 63 | 64 | (setq elfeed-search-print-entry-function #'my/elfeed-search-print-entry) 65 | (setq elfeed-feeds '( 66 | ("https://www.reddit.com/r/emacs.rss" emacs) 67 | ("https://www.reddit.com/r/neovim.rss" neovim) 68 | ("https://www.reddit.com/r/kotlin.rss" kotlin) 69 | ("https://www.reddit.com/r/swift.rss" swift) 70 | ("https://www.reddit.com/r/swiftui.rss" swiftui) 71 | ("https://www.reddit.com/r/artificialInteligence.rss" artificialInteligence) 72 | ;; ("https://techcrunch.com/rss" techcrunch) 73 | )) 74 | 75 | (setq elfeed-search-face-alist 76 | '((emacs font-lock-function-name-face) 77 | (neovim font-lock-type-face) 78 | (kotlin font-lock-keyword-face) 79 | (swift font-lock-constant-face) 80 | (techcrunch font-lock-variable-name-face) 81 | (ai font-lock-number-face) 82 | (singularity font-lock-number-face) 83 | (read font-lock-comment-face))) 84 | (setq elfeed-search-filter "@4-days-ago +unread" 85 | elfeed-search-title-max-width 140 86 | elfeed-search-title-min-width 140)) 87 | 88 | (provide 'mk-elfeed) 89 | ;; mk-elfeed.el ends here 90 | -------------------------------------------------------------------------------- /modules/mk-ai.el: -------------------------------------------------------------------------------- 1 | ;;; mk-ai.el --- AI integrations -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; AI integrations for Emacs, including Copilot and Claude Code IDE. 4 | ;;; Code: 5 | 6 | (require 'corfu) 7 | 8 | ;; (defun mk/tab-completion () 9 | ;; "Smart TAB: Corfu > Copilot > Completion → indent. Vertico endast i minibuffer." 10 | ;; (interactive) 11 | ;; (if (minibuffer-window-active-p (selected-window)) 12 | ;; (call-interactively 13 | ;; (or (lookup-key vertico-map (kbd "")) 14 | ;; #'vertico-exit)) 15 | ;; (cond 16 | ;; ;; 1. Corfu popup visible → accept 17 | ;; ((and (bound-and-true-p corfu-mode) 18 | ;; (bound-and-true-p completion-in-region-mode)) 19 | ;; (corfu-insert)) 20 | ;; ;; 2. Copilot active → accept 21 | ;; ((and (bound-and-true-p copilot-mode) 22 | ;; (copilot--overlay-visible)) 23 | ;; (copilot-accept-completion)) 24 | ;; ((bound-and-true-p corfu-mode) 25 | ;; (completion-at-point)) 26 | ;; ;; 4. Fallback 27 | ;; (t 28 | ;; (indent-for-tab-command))))) 29 | 30 | ;; ;; Smart Tab in Evil Insert mode 31 | ;; (with-eval-after-load 'evil 32 | ;; (define-key evil-insert-state-map (kbd "TAB") #'mk/tab-completion) 33 | ;; (define-key evil-insert-state-map (kbd "") #'mk/tab-completion) 34 | ;; (define-key evil-insert-state-map (kbd "C-i") #'mk/tab-completion)) 35 | 36 | (use-package copilot 37 | :ensure t 38 | :defer 3 39 | :hook ((prog-mode localizeable-mode) . copilot-mode) 40 | :config 41 | (setq copilot-indent-offset-warning-disable t) 42 | ;; Keybindings for copilot completion 43 | (define-key copilot-completion-map (kbd "C-") 'copilot-accept-completion) 44 | (define-key copilot-completion-map (kbd "C-c C-n") 'copilot-next-completion) 45 | (define-key copilot-completion-map (kbd "C-c C-p") 'copilot-previous-completion)) 46 | 47 | (use-package copilot-chat 48 | :defer t 49 | :vc (copilot-chat :url "https://github.com/chep/copilot-chat.el.git" :branch "main" :rev :newest) 50 | :hook ((copilot-chat . visual-line-mode) 51 | (git-commit-setup . copilot-chat-insert-commit-message)) 52 | :config 53 | (setq copilot-chat-backend 'curl 54 | copilot-chat-frontend 'org 55 | copilot-chat-follow t)) 56 | 57 | ;; (use-package claude-code-ide 58 | ;; :defer t 59 | ;; :vc (:url "https://github.com/manzaltu/claude-code-ide.el" :rev :newest) 60 | ;; :config 61 | ;; (setopt claude-code-ide-vterm-anti-flicker t 62 | ;; claude-code-ide-vterm-render-delay 0.2) 63 | ;; (claude-code-ide-emacs-tools-setup)) 64 | 65 | ;; 66 | ;; (use-package dall-e-shell 67 | ;; :defer t 68 | ;; :config 69 | ;; (setq dall-e-shell-openai-key (shell-command-to-string "echo $OPENAI_API_KEY"))) 70 | ;; 71 | ;; (use-package chatgpt-shell 72 | ;; :defer t 73 | ;; :bind 74 | ;; ("C-x C-v" . chatgpt-shell-quick-insert) 75 | ;; ("C-x C-p" . chatgpt-shell-prompt-compose) 76 | ;; ("C-x c g s" . chatgpt-shell-send-and-review-region) 77 | ;; ("C-x c g r" . chatgpt-shell-refactor-code) 78 | ;; ("C-x C-s" . (lambda () 79 | ;; (interactive) 80 | ;; (split-window-right) 81 | ;; (other-window 1) 82 | ;; (chatgpt-shell))) 83 | ;; :config 84 | ;; (setf chatgpt-shell-anthropic-key (getenv "ANTHROPIC_API_KEY")) 85 | ;; (setf chatgpt-shell-openai-key (getenv "OPENAI_API_KEY")) 86 | ;; (setf chatgpt-shell-deepseek-key (getenv "DEEPSEEK_API_KEY")) 87 | ;; (setq chatgpt-shell-model-version "claude-3-5-sonnet-latest")) 88 | ;; 89 | ;; (use-package ob-chatgpt-shell 90 | ;; :ensure nil 91 | ;; :commands (org-babel-execute:chatgpt-shell) 92 | ;; :config 93 | ;; (ob-chatgpt-shell-setup)) 94 | ;; 95 | ;; 96 | 97 | ;; (use-package aidermacs 98 | ;; :ensure t 99 | ;; :commands aidermacs-transient-menu 100 | ;; :vc (aidermacs 101 | ;; :url "https://github.com/MatthewZMD/aidermacs" 102 | ;; :branch "main" 103 | ;; :rev :newest) 104 | ;; :config 105 | ;; (setq aidermacs-auto-commits nil 106 | ;; aidermacs-use-architect-mode nil 107 | ;; aidermacs-show-diff-after-change t) 108 | ;; ;; (setq aidermacs-args '("--model" "anthropic/claude-3-5-sonnet-20241022")) 109 | ;; ;; (setq aidermacs-args '("--model" "deepseek/deepseek-reasoner")) 110 | ;; (setq aidermacs-args '("--model" "deepseek/deepseek-chat")) 111 | ;; :bind (:map global-map 112 | ;; ("C-c a" . aidermacs-transient-menu))) 113 | 114 | 115 | ;;; Provide 116 | (provide 'mk-ai) 117 | ;;; mk-ai.el ends here. 118 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-search.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-search.el --- Search using Ag/Rg and show the result as flycheck list. -*- lexical-binding: t; -*- 2 | ;;; Commentary: Package for showing search as result in a tabulated list 3 | 4 | ;;; Code: 5 | 6 | (require 'periphery-helper) 7 | (require 'periphery) 8 | (require 'thingatpt) 9 | (require 'mode-line-hud) 10 | 11 | (defvar current-query "") 12 | (defvar periphery-quick:debug nil) 13 | 14 | (defun run-async-command (command callback) 15 | "Run COMMAND asynchronously and call CALLBACK with the result." 16 | (let ((output-buffer (generate-new-buffer "*async-command-output*"))) 17 | (set-process-sentinel 18 | (start-process-shell-command "async-command" output-buffer command) 19 | (lambda (process event) 20 | (when (string= event "finished\n") 21 | (with-current-buffer output-buffer 22 | (let ((result (string-trim (buffer-string)))) 23 | (funcall callback result)) 24 | (kill-buffer output-buffer))))))) 25 | 26 | (defun periphery-run-query (searcher text) 27 | "Search using (SEARCHER) with (TEXT)." 28 | (when (> (length text) 1) 29 | (setq current-query nil) 30 | (if (executable-find "rg") 31 | (let ((default-directory (periphery-helper:project-root-dir))) 32 | (setq current-query (regexp-quote text)) 33 | (let ((command (format "%s \"%s\" --color=never --no-heading --with-filename --line-number --column --sort path" 34 | searcher current-query))) 35 | (when periphery-quick:debug 36 | (message "Running command: %s" command)) 37 | (run-async-command command 38 | (lambda (result) 39 | (when periphery-quick:debug 40 | (message "Search result: %s" result)) 41 | (if (string-empty-p result) 42 | (periphery-parse-search-result :text "" :query current-query) 43 | (send-search-result-to-periphery result)))))) 44 | (message-with-color :tag "[FAILED]" :text (format "Install %s to use this command." searcher) :attributes 'warning)))) 45 | 46 | (defun send-search-result-to-periphery (text) 47 | "Send result (as TEXT) to periphery." 48 | (when (and (stringp text) (> (length text) 4)) 49 | (periphery-parse-search-result :text text :query current-query))) 50 | 51 | (defun periphery--search-thing-at-point () 52 | "Search thing at point." 53 | (let ((extension (file-name-extension (buffer-file-name)))) 54 | (if (use-region-p) 55 | (let ((text (buffer-substring-no-properties (region-beginning) (region-end)))) 56 | (when (> (length text) 1) 57 | (periphery-run-query (format "rg -g '*.%s' -s -e" extension) (escape-string text)))) 58 | (periphery-run-query (format "rg -g '*.%s' -w -s -e" extension) (thing-at-point 'symbol))))) 59 | 60 | (defun escape-string (text) 61 | "Escape TEXT." 62 | (let ((str text)) 63 | (setq str (replace-regexp-in-string "{" "\\\\{" str)) 64 | (setq str (replace-regexp-in-string "}" "\\\\}" str)) 65 | (setq str (replace-regexp-in-string "(" "\\\\(" str)) 66 | (setq str (replace-regexp-in-string ")" "\\\\)" str)) 67 | str)) 68 | 69 | (defun periphery--search-for (searcher) 70 | "Search using (as SEARCHER)." 71 | (let ((query (read-string "Query:"))) 72 | (periphery-run-query searcher query) 73 | (mode-line-hud:update :message 74 | (format "Searching for '%s' with rg" 75 | (propertize query 'face 'font-lock-string-face))))) 76 | 77 | ;;;###autoload 78 | (defun periphery-search-rg () 79 | "Search using RG (Ripgrep)." 80 | (interactive) 81 | (periphery--search-for "rg ")) 82 | 83 | ;;;###autoload 84 | (defun periphery-query-todos-and-fixmes () 85 | "Query todos and fixmes in the project." 86 | (interactive) 87 | (if (executable-find "rg") 88 | (periphery-run-query "rg -e" "(TODO|NOTE|FIX|FIXME|HACK|PERF):") 89 | (message-with-color :tag "[FAILED]" :text "Install 'rg' to use this command." :attributes 'warning))) 90 | 91 | ;;;###autoload 92 | (defun periphery-query-marks () 93 | "Query mark in the project." 94 | (interactive) 95 | (mode-line-hud:update :message (propertize "Showing marks" 'face 'font-lock-keyword-face)) 96 | (periphery-run-query "rg -w" "\\'MARK'")) 97 | 98 | ;;;###autoload 99 | (defun periphery-search-dwiw-rg () 100 | "Search using rg (ripgrep)." 101 | (interactive) 102 | (mode-line-hud:update :message (propertize "Searching" 'face 'font-lock-keyword-face)) 103 | (periphery--search-thing-at-point)) 104 | 105 | (provide 'periphery-search) 106 | ;;; periphery-search.el ends here. 107 | -------------------------------------------------------------------------------- /etc/yasnippet/snippets/swift-mode/.yas-setup.el: -------------------------------------------------------------------------------- 1 | ;;; -*- lexical-binding: t; -*- 2 | 3 | ;; Swift helpers adjusted from: 4 | ;; https://github.com/jorgenschaefer/elpy/blob/060a4eb78ec8eba9c8fe3466c40a414d84b3dc81/snippets/python-mode/.yas-setup.el 5 | 6 | (defun swift-snippet-init-assignments (arg-string) 7 | "Return init assignments for arguments." 8 | (let ((indentation (make-string (save-excursion 9 | (goto-char start-point) 10 | (current-indentation)) 11 | ?\s))) 12 | (string-trim (mapconcat (lambda (arg) 13 | (if (string-match "^\\*" arg) 14 | "" 15 | (format "self.%s = %s\n%s" 16 | arg arg indentation))) 17 | (swift-snippet-split-args arg-string) 18 | "")))) 19 | 20 | (defun swift-snippet-split-args (arg-string) 21 | "Split a python argument string into ((name, default)..) tuples" 22 | (mapcar (lambda (x) 23 | (if (and x (string-match "\\([[:alnum:]]*\\):" x)) 24 | (match-string-no-properties 1 x) 25 | x)) 26 | (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t))) 27 | 28 | (defun swift-class-or-struct-vars-at-point () 29 | "Return a list of class or struct vars in the form '(((name . \"foo\") (type . \"Foo\")))." 30 | (cl-assert (seq-contains local-minor-modes 'tree-sitter-mode) "tree-sitter-mode not enabled") 31 | (let* ((node (or (tree-sitter-node-at-point 'struct_declaration) 32 | (tree-sitter-node-at-point 'class_declaration))) 33 | (vars) 34 | (var)) 35 | (unless node 36 | (error "Neither in class nor struct")) 37 | (mapc 38 | (lambda (item) 39 | (cond ((eq 'identifier 40 | (tsc-node-type (cdr item))) 41 | (when var 42 | (setq vars (append vars (list var)))) 43 | (setq var (list (cons 'name (tsc-node-text 44 | (cdr item)))))) 45 | ((eq 'type 46 | (tsc-node-type (cdr item))) 47 | (setq var (map-insert var 'type (tsc-node-text 48 | (cdr item))))) 49 | ((eq 'string 50 | (tsc-node-type (cdr item))) 51 | (setq var (map-insert var 'type "String"))) 52 | ((eq 'number 53 | (tsc-node-type (cdr item))) 54 | (setq var (map-insert var 'type "Int"))) 55 | (t (message "%s" (tsc-node-type (cdr item)))))) 56 | (tsc-query-captures 57 | (tsc-make-query tree-sitter-language 58 | "(struct_declaration (variable_declaration (identifier) @name (type) @type)) 59 | (struct_declaration (variable_declaration (identifier) @name (string) @value)) 60 | (struct_declaration (variable_declaration (identifier) @name (number) @value)) 61 | (struct_declaration (constant_declaration (identifier) @name (type) @value)) 62 | (struct_declaration (constant_declaration (identifier) @name (string) @value)) 63 | (struct_declaration (constant_declaration (identifier) @name (number) @value)) 64 | (class_declaration (variable_declaration (identifier) @name (type) @type)) 65 | (class_declaration (variable_declaration (identifier) @name (string) @value)) 66 | (class_declaration (variable_declaration (identifier) @name (number) @value)) 67 | (class_declaration (constant_declaration (identifier) @name (type) @type)) 68 | (class_declaration (constant_declaration (identifier) @name (string) @value)) 69 | (class_declaration (constant_declaration (identifier) @name (number) @value))") 70 | node nil)) 71 | (when var 72 | (setq vars (append vars (list var)))) 73 | vars)) 74 | 75 | (defun swift-class-or-struct-initializer-text (vars) 76 | (cl-assert (seq-contains local-minor-modes 'tree-sitter-mode) "tree-sitter-mode not enabled") 77 | (format 78 | (string-trim 79 | " 80 | init(%s) { 81 | %s 82 | }") 83 | (seq-reduce (lambda (reduced var) 84 | (format "%s%s%s: %s" 85 | reduced 86 | (if (string-empty-p reduced) 87 | "" ", ") 88 | (map-elt var 'name) 89 | (map-elt var 'type))) 90 | vars "") 91 | (string-join 92 | (mapcar (lambda (var) 93 | (format "self.%s = %s" 94 | (map-elt var 'name) 95 | (map-elt var 'name))) 96 | vars) 97 | "\n "))) 98 | -------------------------------------------------------------------------------- /modules/mk-editing.el: -------------------------------------------------------------------------------- 1 | ;;; mk-editing.el --- Editing configurations -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | ;; This file contains configurations related to editing in Emacs. 5 | ;;; Code: 6 | 7 | (require 'cl-lib) 8 | (require 'project) 9 | 10 | ;; Override custom-declare-variable temporarily to handle all missing variables 11 | ;; This is a comprehensive workaround for Emacs 30.2.50 compatibility issues 12 | (cl-letf* ((original-func (symbol-function 'custom-declare-variable)) 13 | ((symbol-function 'custom-declare-variable) 14 | (lambda (symbol value &rest args) 15 | (condition-case nil 16 | (apply original-func symbol value args) 17 | (void-variable 18 | (unless (boundp symbol) 19 | (set symbol (if (functionp value) 20 | (ignore-errors (funcall value)) 21 | value))) 22 | symbol) 23 | (error 24 | (unless (boundp symbol) 25 | (set symbol nil)) 26 | symbol)))))) 27 | 28 | (use-package isearch 29 | :ensure nil 30 | :defer t 31 | :config 32 | (setq isearch-allow-scroll t 33 | isearch-lazy-count t) 34 | 35 | (defun mk/project-search-from-isearch () 36 | (interactive) 37 | (let ((query (if isearch-regexp 38 | isearch-string 39 | (regexp-quote isearch-string))) 40 | (search-nonincremental-instead t)) 41 | (isearch-update-ring isearch-string isearch-regexp) 42 | (isearch-done t t) 43 | (consult-ripgrep (project-root (project-current)) query))) 44 | 45 | (defun isearch-consult-line () 46 | (interactive) 47 | (let ((query (if isearch-regexp 48 | isearch-string 49 | (regexp-quote isearch-string)))) 50 | (isearch-update-ring isearch-string isearch-regexp) 51 | (let (search-nonincremental-instead) 52 | (ignore-errors (isearch-done t t))) 53 | (consult-line query))) 54 | 55 | (defun isearch-with-region-or-thing () 56 | "Use region as isearch text if active, otherwise use thing at point. 57 | Uses regexp search with word boundaries." 58 | (interactive) 59 | (let ((search-text 60 | (if (region-active-p) 61 | (buffer-substring-no-properties 62 | (region-beginning) 63 | (region-end)) 64 | (let ((bounds (bounds-of-thing-at-point 'symbol))) 65 | (when bounds 66 | (buffer-substring-no-properties (car bounds) (cdr bounds))))))) 67 | (when search-text 68 | (when isearch-mode 69 | (isearch-done)) 70 | (deactivate-mark) 71 | (isearch-forward-regexp nil t) 72 | (setq isearch-case-fold-search nil) 73 | (setq isearch-string (format "\\<%s\\>" (regexp-quote search-text))) 74 | (setq isearch-message isearch-string) 75 | (isearch-search-and-update)))) 76 | :bind 77 | (:map isearch-mode-map 78 | ("C-r" . isearch-repeat-backward) 79 | ("C-o" . isearch-occur) 80 | ("C-e" . iedit-mode) 81 | ("M-e" . isearch-edit-string) 82 | ("M-f" . isearch-consult-line) 83 | ("C-f" . (lambda () 84 | (interactive) 85 | (condition-case nil 86 | (mk/project-search-from-isearch) 87 | (quit (isearch-abort))))) 88 | ("C-d" . isearch-with-region-or-thing))) 89 | 90 | (use-package iedit 91 | :ensure t 92 | :defer t 93 | :bind 94 | (:map iedit-mode-keymap 95 | ("C-" . iedit-toggle-selection) 96 | ("C-j" . iedit-next-occurrence) 97 | ("C-k" . iedit-prev-occurrence) 98 | ("C-g" . iedit--quit))) 99 | 100 | (use-package ultra-scroll 101 | :ensure t 102 | :defer t 103 | :vc (ultra-scroll 104 | :url "https://github.com/jdtsmith/ultra-scroll" 105 | :main-file "ultra-scroll.el" 106 | :branch "main" 107 | :rev :newest) 108 | :init 109 | (setq scroll-conservatively 3 110 | scroll-margin 0) 111 | :config (ultra-scroll-mode 1)) 112 | 113 | (use-package wgrep 114 | :defer t 115 | :config 116 | (setq wgrep-auto-save-buffer t)) 117 | 118 | (use-package rg 119 | :ensure t 120 | :defer t) 121 | 122 | (use-package visual-replace 123 | :defer t 124 | :bind (("C-c r" . visual-replace) 125 | :map isearch-mode-map 126 | ("C-c r" . visual-replace-from-isearch))) 127 | 128 | (use-package avy 129 | :defer t 130 | :bind 131 | ("M-g" . avy-goto-word-1) 132 | (:map isearch-mode-map 133 | ("C-a" . avy-isearch)) 134 | :config 135 | (setq avy-single-candidate-jump t)) 136 | 137 | (provide 'mk-editing) 138 | ;;; mk-editing.el ends here 139 | -------------------------------------------------------------------------------- /modules/mk-completion.el: -------------------------------------------------------------------------------- 1 | ;;; mk-completion.el --- Completion configuration -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | ;; Completion configuration using Vertico, Marginalia, and Nerd Icons. 5 | ;;; Code: 6 | 7 | (use-package vertico 8 | :ensure t 9 | :defer t 10 | :hook (after-init . vertico-mode) 11 | :bind 12 | (:map vertico-map 13 | ("C-j" . vertico-next) 14 | ("C-k" . vertico-previous) 15 | ("C-d" . vertico-scroll-down) 16 | ("C-u" . vertico-scroll-up) 17 | ("C-g" . abort-recursive-edit)) 18 | :config 19 | (advice-add #'vertico--format-candidate :around 20 | (lambda (orig cand prefix suffix index _) 21 | (setq cand (funcall orig cand prefix suffix index _)) 22 | (concat 23 | (if (= vertico--index index) 24 | (propertize "» " 'face '(:inherit font-lock-operator-face :weight black)) 25 | " ") 26 | cand))) 27 | (setq vertico-resize t 28 | vertico-count 13 29 | vertico-cycle t)) 30 | 31 | (use-package vertico-posframe 32 | :ensure t 33 | :after vertico 34 | :config 35 | (setq vertico-posframe-poshandler #'posframe-poshandler-frame-center 36 | vertico-posframe-min-height 2 37 | vertico-posframe-truncate-lines t 38 | vertico-posframe-min-width 120 39 | vertico-posframe-border-width 20 40 | vertico-posframe-parameters '((alpha . 0.9))) 41 | (setq vertico-multiform-commands 42 | '((consult-line (:not posframe)) 43 | (xref-find-references (:not posframe)) 44 | (consult-eglot-symbols (:not posframe)) 45 | (consult-ripgrep (:not posframe)) 46 | (consult-org-heading (:not posframe)) 47 | (consult-xref (:not posframe)) 48 | (t posframe))) 49 | (vertico-multiform-mode) 50 | (vertico-posframe-cleanup)) 51 | 52 | (custom-set-faces 53 | '(vertico-posframe-border ((t (:inherit vertico-posframe))))) 54 | 55 | (use-package marginalia 56 | :ensure t 57 | :after (vertico vertico-posframe) 58 | :config 59 | (marginalia-mode)) 60 | 61 | (use-package vertico-directory 62 | :hook (rfn-eshadow-update-overlay . vertico-directory-tidy) 63 | :commands (find-file) 64 | :ensure nil 65 | :bind (:map vertico-map 66 | ("" . vertico-directory-enter) 67 | ("DEL" . vertico-directory-delete-char) 68 | ("M-DEL" . vertico-directory-delete-word))) 69 | 70 | (use-package nerd-icons-completion 71 | :ensure t 72 | :after (nerd-icons marginalia) 73 | :hook (marginalia-mode . nerd-icons-completion-marginalia-setup) 74 | :config 75 | (nerd-icons-completion-mode)) 76 | 77 | (use-package nerd-icons-dired 78 | :ensure t 79 | :hook (dired-mode . nerd-icons-dired-mode)) 80 | 81 | (use-package consult 82 | :defer t 83 | :ensure t 84 | :hook 85 | (completion-list-mode . consult-preview-at-point-mode) 86 | :bind 87 | ( 88 | ("M-f" . (lambda () (interactive) (consult-line (thing-at-point 'symbol)))) 89 | ;; ("M-f" . consult-line) 90 | ("" . #'consult-buffer) 91 | ("C-c C-a" . #'consult-apropos) 92 | ("C-c m m" . #'consult-imenu-multi) 93 | ("C-c m b" . #'consult-imenu) 94 | ("C-" . #'consult-project-buffer) 95 | ("M-R" . #'consult-recent-file) 96 | :map isearch-mode-map 97 | ("C-M-e" . #'consult-isearch-history) 98 | ("M-s e" . #'consult-isearch-history) 99 | ("M-s L" . #'consult-line-multi) 100 | ("M-s l" . #'consult-line)) 101 | :init 102 | (setq register-preview-delay 0.4 103 | register-preview-function #'consult-register-format 104 | xref-show-xrefs-function #'consult-xref 105 | xref-show-definitions-function #'consult-xref) 106 | (advice-add #'register-preview :override #'consult-register-window) 107 | :config 108 | (consult-customize 109 | consult-theme :preview-key '(:debounce 0.2 any) 110 | consult-ripgrep consult-git-grep consult-grep 111 | consult-bookmark consult-recent-file consult-xref 112 | consult--source-bookmark consult--source-file-register 113 | consult--source-recent-file consult--source-project-recent-file 114 | :preview-key '(:debounce 0.4 any)) 115 | (setq consult-narrow-key "<")) 116 | 117 | (use-package embark 118 | :commands (embark-act embark-collect-snapshot embark-collect-live) 119 | :bind 120 | (:map minibuffer-local-map 121 | ("C-." . embark-act)) 122 | (:map embark-collect-mode-map 123 | (("C-." . embark-act))) 124 | :custom 125 | (embark-quit-after-action nil)) 126 | 127 | (use-package embark-consult 128 | :after (:all embark consult) 129 | :hook 130 | (embark-collect-mode . consult-preview-at-point-mode)) 131 | 132 | ;; (with-eval-after-load 'vertico 133 | ;; (define-key evil-insert-state-map (kbd "") #'vertico-directory-enter) 134 | ;; (define-key evil-insert-state-map (kbd "DEL") #'vertico-directory-delete-char)) 135 | 136 | (provide 'mk-completion) 137 | ;;; mk-completion.el ends here 138 | -------------------------------------------------------------------------------- /modules/mk-ios-development.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;;; Code: 3 | 4 | ;; knockknock notification integration - MUST be loaded first before any 5 | ;; package that might trigger notifications to prevent startup crashes 6 | (use-package knockknock 7 | :ensure nil 8 | :demand t ;; Load immediately, don't defer 9 | :config 10 | ;; Initialize knockknock early to prevent crashes when multiple 11 | ;; notifications are shown rapidly during startup 12 | (knockknock-init) 13 | ;; Use theme colors instead of hardcoded values 14 | (setopt knockknock-border-color "#292929") 15 | (setopt knockknock-darken-background-percent 35) 16 | (defun my-xcode-knockknock-notify (&rest args) 17 | "Custom notification function using knockknock for xcode-project. 18 | Accepts keyword arguments from xcode-project-notify: 19 | :message - The message to display 20 | :delay - Optional delay (ignored for knockknock) 21 | :seconds - How long to show notification 22 | :reset - Whether to reset (ignored for knockknock) 23 | :face - Face for styling (ignored for knockknock)" 24 | (let* ((message-text (plist-get args :message)) 25 | (seconds (or (plist-get args :seconds) 3)) 26 | ;; Choose icon based on message content 27 | (icon (cond 28 | ((string-match-p "\\(success\\|complete\\|passed\\)" message-text) 29 | "nf-cod-check") 30 | ((string-match-p "\\(error\\|fail\\)" message-text) 31 | "nf-cod-error") 32 | ((string-match-p "\\(warning\\|warn\\)" message-text) 33 | "nf-cod-warning") 34 | ((string-match-p "\\(build\\|compil\\)" message-text) 35 | "nf-cod-tools") 36 | (t "nf-dev-xcode"))) 37 | ;; Try to extract title from message if it contains a colon 38 | (parts (split-string message-text ": " t)) 39 | (title (if (> (length parts) 1) (car parts) "Swift-development")) 40 | (msg (if (> (length parts) 1) 41 | (string-join (cdr parts) ": ") 42 | message-text))) 43 | (knockknock-notify 44 | :title title 45 | :message msg 46 | :icon icon 47 | :duration seconds))) 48 | 49 | ;; Configure xcode-project to use custom backend 50 | (setq xcode-project-notification-backend 'custom) 51 | (setq xcode-project-notification-function #'my-xcode-knockknock-notify)) 52 | 53 | (use-package swift-ts-mode 54 | :mode ("\\.swift\\'" "\\.swiftinterface\\'") 55 | :ensure nil 56 | :bind 57 | (:map swift-ts-mode-map 58 | ("C-c t s" . #'swift-ts:split-func-list)) 59 | :custom 60 | (swift-ts-basic-offset 4) 61 | (swift-ts:indent-trailing-call-member t)) 62 | 63 | (use-package localizeable-mode 64 | :ensure nil 65 | :after swift-ts-mode 66 | :mode "\\.strings\\'" 67 | :bind (:map localizeable-mode-map 68 | ("C-c C-k" . #'periphery-run-loco))) 69 | 70 | (use-package objc-mode 71 | :mode "\\.h\\'" 72 | :defer t 73 | :ensure nil) 74 | 75 | (use-package ios-simulator 76 | :ensure nil 77 | :after swift-ts-mode) 78 | 79 | (use-package swift-cache 80 | :ensure nil 81 | :after swift-ts-mode) 82 | 83 | (use-package swift-development 84 | :ensure nil 85 | :after swift-ts-mode 86 | :custom 87 | (swift-development-use-periphery t)) 88 | 89 | (use-package swift-features 90 | :ensure nil 91 | :after swift-ts-mode) 92 | 93 | (use-package domain-blocker 94 | :ensure nil 95 | :after swift-ts-mode) 96 | 97 | (use-package xcode-project 98 | :ensure nil 99 | :after swift-ts-mode) 100 | 101 | (use-package xcode-build-config 102 | :ensure nil 103 | :after swift-ts-mode) 104 | 105 | (use-package swift-refactor 106 | :ensure nil 107 | :after (swift-ts-mode kotlin-ts-mode) 108 | :bind 109 | (:map kotlin-ts-mode-map 110 | ("C-c r s" . #'code-refactor-split-function-list) 111 | ("M-t" . #'swift-refactor-insert-todo) 112 | ("M-m" . #'swift-refactor-insert-mark))) 113 | 114 | ;; (use-package apple-docs-query 115 | ;; :ensure nil 116 | ;; :after swift-ts-mode 117 | ;; :bind 118 | ;; (:map swift-ts-mode-map 119 | ;; ("C-x D" . #'apple-docs/query-thing-at-point) 120 | ;; ("C-x d" . #'apple-docs/query))) 121 | 122 | 123 | (use-package periphery-swiftformat 124 | :ensure nil 125 | :after (swift-ts-mode swift-mode) 126 | :bind 127 | (:map swift-ts-mode-map 128 | ("C-c C-o" . #'periphery-swiftformat-lint-buffer) 129 | ("M-o" . #'periphery-swiftformat-autocorrect-buffer) 130 | ("C-c C-p" . #'periphery-run-swiftformat-for-project))) 131 | 132 | ;; Load the unified minor mode that provides all Swift development keybindings 133 | ;; This mode automatically activates for swift-ts-mode, localizeable-mode, and ios-simulator buffers 134 | (use-package swift-development-mode 135 | :ensure nil 136 | :after (swift-ts-mode swift-development ios-simulator xcode-project swift-refactor)) 137 | 138 | ;;; Provide 139 | (provide 'mk-ios-development) 140 | ;;; mk-ios-development.el ends here. 141 | -------------------------------------------------------------------------------- /localpackages/filer.el: -------------------------------------------------------------------------------- 1 | ;;; filer.el --- A small package for quickly searching for files using ripgrep -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | ;; This package provides functionality for quickly searching and opening files 5 | ;; using ripgrep (rg) and Emacs' built-in completion system. 6 | 7 | ;;; Code: 8 | 9 | (require 'periphery-helper) 10 | (require 'nerd-icons) 11 | 12 | (defgroup filer nil 13 | "Customization group for filer package." 14 | :group 'files) 15 | 16 | (defface filer-filename-face 17 | '((t (:inherit default :foreground nil))) 18 | "Face for filenames in filer results." 19 | :group 'filer) 20 | 21 | (defface filer-path-face 22 | '((t (:inherit font-lock-comment-face))) 23 | "Face for file paths in filer results." 24 | :group 'filer) 25 | 26 | (defface filer-project-name-face 27 | '((t (:inherit font-lock-number-face))) 28 | "Face for project names in filer results." 29 | :group 'filer) 30 | 31 | (defface filer-path-delimiter-face 32 | '((t (:inherit font-lock-delimiter-face))) 33 | "Face for path delimiters in filer results." 34 | :group 'filer) 35 | 36 | (defcustom filer-show-full-path nil 37 | "When non-nil, show full file paths in results." 38 | :group 'filer 39 | :type 'boolean) 40 | 41 | (defcustom filer-include-project-name t 42 | "When non-nil, include project name in results." 43 | :group 'filer 44 | :type 'boolean) 45 | 46 | (defcustom filer-max-results 1000 47 | "Maximum number of results to process." 48 | :group 'filer 49 | :type 'integer) 50 | 51 | (defcustom filer-path-position 'right 52 | "Position of the file path relative to the filename. 53 | Can be either 'left or 'right." 54 | :group 'filer 55 | :type '(choice (const :tag "Right side" right) 56 | (const :tag "Left side" left))) 57 | 58 | (defun filer-format-candidate (file project-root) 59 | "Format FILE as a candidate for completion, relative to PROJECT-ROOT." 60 | (let* ((full-path (expand-file-name file)) 61 | (relative-path (file-relative-name full-path project-root)) 62 | (file-name (file-name-nondirectory relative-path)) 63 | (file-dir (file-name-directory relative-path)) 64 | (project-name (file-name-nondirectory (directory-file-name project-root))) 65 | (icon (nerd-icons-icon-for-file full-path)) 66 | (path-part 67 | (concat 68 | (if filer-include-project-name 69 | (propertize (or project-name "") 'face 'filer-project-name-face) 70 | "") 71 | (if (and file-dir (not (string= file-dir ""))) 72 | (concat (propertize "/" 'face 'filer-path-delimiter-face) 73 | (propertize (directory-file-name file-dir) 74 | 'face 'filer-path-face)) 75 | "")))) 76 | (cons 77 | (if filer-show-full-path 78 | (format "%s %s" 79 | icon 80 | (propertize relative-path 'face 'filer-filename-face)) 81 | (pcase filer-path-position 82 | ('right (format "%s %s %s" 83 | icon 84 | (propertize file-name 'face 'filer-filename-face) 85 | path-part)) 86 | ('left (format "%s %s %s" 87 | icon 88 | path-part 89 | (propertize file-name 'face 'filer-filename-face))))) 90 | full-path))) 91 | 92 | (defun filer-find-file () 93 | "Interactively find and open a file using ripgrep and completion." 94 | (interactive) 95 | (let* ((project-root (periphery-helper:project-root-dir)) 96 | (default-directory project-root) 97 | (command "rg --files --color=never --no-heading --sortr=accessed --follow --smart-case") 98 | (process (start-process-shell-command "filer-rg" nil command)) 99 | (candidates '()) 100 | (candidate-count 0) 101 | (selection nil) 102 | (done nil)) 103 | 104 | (set-process-filter 105 | process 106 | (lambda (_process output) 107 | (dolist (file (split-string output "\n" t)) 108 | (when (and (< candidate-count filer-max-results) 109 | (file-regular-p (expand-file-name file project-root))) 110 | (push (filer-format-candidate file project-root) candidates) 111 | (setq candidate-count (1+ candidate-count)))))) 112 | (set-process-sentinel 113 | process 114 | (lambda (process _event) 115 | (when (eq (process-status process) 'exit) 116 | (setq done t)))) 117 | (while (not done) 118 | (accept-process-output process 0.1)) 119 | (setq candidates (nreverse candidates)) 120 | (setq selection (completing-read "Select file: " candidates nil t)) 121 | (when selection 122 | (let ((file (cdr (assoc selection candidates)))) 123 | (if file 124 | (if (file-exists-p file) 125 | (find-file file) 126 | (message "File not found: %s" file)) 127 | (message "No matching file found for selection: %s" selection)))))) 128 | 129 | (provide 'filer) 130 | ;;; filer.el ends here 131 | -------------------------------------------------------------------------------- /modules/mk-emacs.el: -------------------------------------------------------------------------------- 1 | ;;; mk-emacs.el --- General Emacs settings -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; General Emacs settings for improved usability and performance. 4 | ;;; Code: 5 | 6 | ;; Predefine variables to avoid void-variable errors during macro expansion 7 | ;; This is a workaround for Emacs 30.2.50 compatibility issues 8 | 9 | (use-package emacs 10 | :hook (after-init . (lambda () 11 | (global-hl-line-mode 1) 12 | (display-battery-mode 1) 13 | (save-place-mode 1) 14 | (global-auto-revert-mode 1))) 15 | :custom 16 | (auto-save-file-name-transforms `((".*" ,(expand-file-name "var/auto-save/" user-emacs-directory) t))) 17 | (auto-save-list-file-prefix (expand-file-name "var/auto-save/.saves-" user-emacs-directory)) 18 | (auto-save-no-message t) 19 | (auto-save-timeout 20) 20 | (auto-window-vscroll nil) 21 | (backup-by-copying t) 22 | (backward-delete-char-untabify-method 'hungry) 23 | (column-number-mode nil) 24 | (completion-ignore-case t) 25 | (confirm-kill-processes t) 26 | (context-menu-mode t) 27 | (create-lockfiles nil) 28 | (cursor-in-non-selected-windows nil) 29 | (delete-by-moving-to-trash t) 30 | (display-time-default-load-average nil) ; this information is useless for most 31 | (find-file-visit-truename nil) 32 | (global-auto-revert-non-file-buf t) 33 | (help-window-select t) 34 | ;; (indicate-buffer-boundaries 'right) ; Show buffer top and bottom in the margin 35 | (line-number-mode nil) 36 | (make-backup-files nil) 37 | (read-buffer-completion-ignore-case t) 38 | (read-extended-command-predicate #'command-completion-default-include-p) 39 | (read-file-name-completion-ignore-case t) 40 | (use-dialog-box nil) 41 | (use-file-dialog nil) 42 | (visible-bell nil) 43 | (window-combination-resize t) 44 | (window-sides-vertical t) 45 | :config 46 | (set-display-table-slot standard-display-table 0 ?\ ) 47 | (set-window-fringes (selected-window) 16 10) 48 | (set-window-margins (selected-window) 10 10) 49 | (setq confirm-kill-emacs (lambda (prompt) 50 | (y-or-n-p-with-timeout prompt 2 nil))) 51 | (setopt history-length 300) 52 | (setopt auto-revert-interval 5) ;; Check for changes every secondhh 53 | (setopt auto-revert-avoid-polling t) ;; Automatically reread from disk if the underlying file changes 54 | (setopt auto-revert-check-vc-info t) 55 | (setopt indicate-empty-lines nil) 56 | (setopt initial-major-mode 'fundamental-mode) ; default mode for the *scratch* buffer 57 | (setopt kept-new-versions 6) 58 | (setopt kept-old-versions 2) 59 | (setopt load-prefer-newer t) 60 | (setopt kill-do-not-save-duplicates t) 61 | (setopt large-file-warning-threshold (* 15 1024 1024)) 62 | (setopt line-move-visual nil) 63 | (setopt read-answer-short t) 64 | (setopt read-buffer-completion-ignore-case t) 65 | (setopt read-extended-command-predicate #'command-completion-default-include-p) 66 | (setopt recentf-auto-cleanup (if (daemonp) 300 'never)) 67 | (setopt recentf-max-menu-items 15) 68 | (setopt compilation-skip-threshold 2) 69 | (setopt recentf-max-saved-items 300) 70 | (setopt redisplay-skip-fontification-on-input nil) 71 | (setopt ring-bell-function 'ignore) 72 | (setopt split-width-threshold 300) 73 | (setopt switch-to-buffer-obey-display-actions t) 74 | (setopt use-short-answers t) 75 | (setopt version-control t) 76 | (setopt warning-minimum-level :emergency) 77 | (setopt xref-search-program 'ripgrep) 78 | (setopt project-vc-ignores '(".git/" ".direnv/" "node_modules/" "dist/" ".*")) 79 | (setopt grep-find-ignored-directories 80 | '("SCCS" "RCS" "CVS" "MCVS" ".src" ".svn" ".git" ".hg" ".bzr" "_MTN" "_darcs" "{arch}" "node_modules" "build" "dist")) 81 | (setopt backup-directory-alist `(("." . "~/.saves"))) 82 | (setopt custom-file (expand-file-name "var/custom.el" user-emacs-directory)) 83 | (setopt delete-old-versions t) 84 | (setopt ad-redefinition-action 'accept) 85 | (when (eq system-type 'darwin) 86 | (setq 87 | mac-command-modifier 'meta 88 | mac-option-modifier 'none 89 | ;; ns-use-proxy-icon nil 90 | ;; ns-pop-up-frames nil 91 | ns-use-thin-smoothing t 92 | dired-use-ls-dired t 93 | insert-directory-program "/opt/homebrew/bin/gls" 94 | dired-listing-switches "-aBhl --group-directories-first" 95 | browse-url-browser-function #'mk/browser-split-window))) 96 | 97 | ;;;###autoload 98 | (defun mk/safe-kill-buffer-and-window () 99 | "Safely kill the current buffer and delete its window if possible. 100 | - If the buffer is shown elsewhere, only delete this window. 101 | - If it's a special buffer or the minibuffer, don't delete the window." 102 | (interactive) 103 | (let* ((buf (current-buffer)) 104 | (win (selected-window))) 105 | (cond 106 | ;; Never kill the minibuffer 107 | ((minibufferp buf) 108 | (message "Cannot kill the minibuffer.")) 109 | ;; Buffer shown elsewhere: just delete this window 110 | ((cl-remove win (get-buffer-window-list buf nil t)) 111 | (delete-window win)) 112 | ;; Buffer is special? Just kill buffer, keep window 113 | ((or (string-match-p "^\\*" (buffer-name buf)) 114 | (not (window-live-p win))) 115 | (kill-buffer buf)) 116 | ;; Normal case: kill buffer and delete window 117 | (t 118 | (when (kill-buffer buf) 119 | (when (window-live-p win) 120 | (delete-window win))))))) 121 | 122 | (defun mk/browser-split-window (url &optional new-window) 123 | "Create a new browser (as URL as NEW-WINDOW) window to the right of the current one." 124 | (interactive) 125 | (let ((ignore-window-parameters t) 126 | (dedicated-p (window-dedicated-p))) 127 | (delete-other-windows) 128 | (split-window-horizontally) 129 | (other-window 1) 130 | (xwidget-webkit-browse-url url))) 131 | 132 | (provide 'mk-emacs) 133 | ;;; mk-emacs.el ends here 134 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-quick.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-quick.el --- A small package for quickly finding symbols -*- lexical-binding: t -*- 2 | ;;; Code: 3 | 4 | (require 'periphery-helper) 5 | (require 'project) 6 | 7 | (defconst periphery-quick-regex-parser "\\([^:]+\\):\\([0-9]+\\)?:\\([0-9]+\\):\s?\\(.+\\)" 8 | "Parse vimgrep like strings (compilation).") 9 | 10 | (defvar periphery-quick:debug nil 11 | "Enable debug logging.") 12 | 13 | (defun periphery-quick:debug-log (msg &rest args) 14 | "Log debug MSG with ARGS." 15 | (when periphery-quick:debug 16 | (apply #'message (concat "DEBUG: " msg) args))) 17 | 18 | (defun periphery-quick:parse (input) 19 | "Parse as (INPUT)." 20 | (periphery-quick:debug-log "Starting parse with input: %s" (substring input 0 (min 100 (length input)))) 21 | (setq list '()) 22 | (dolist (line (split-string input "\n")) 23 | (let ((entry (periphery-quick:parse-line line))) 24 | (if entry 25 | (push entry list) 26 | (periphery-quick:debug-log "Failed to parse line: %s" line)))) 27 | (periphery-quick:debug-log "Parsed %d entries" (length list)) 28 | (if (null list) 29 | (message "No results found.") 30 | (condition-case err 31 | (let* ((choices (seq-map (lambda (item) (car item)) list)) 32 | (choice (completing-read "Select result: " choices)) 33 | (selected (assoc choice list))) 34 | (periphery-quick:debug-log "Selected: %s" selected) 35 | (when selected 36 | (let* ((file-info (split-string (cadr selected) ":")) 37 | (file (car file-info)) 38 | (line (string-to-number (cadr file-info)))) 39 | (periphery-quick:debug-log "Opening file: %s at line %d" file line) 40 | (periphery-quick:goto-file-line file line)))) 41 | (error (periphery-quick:debug-log "Error in parse: %s" err) 42 | (message "An error occurred: %s" err))))) 43 | 44 | 45 | (defun add-right-padding-up-to (word max-length) 46 | "Add padding to (as WORD) if smaller then (as MAX-LENGTH)." 47 | (if (> (length word) max-length) 48 | (concat (substring word 0 max-length) "") 49 | (progn 50 | (setq copy word) 51 | (while (< (string-width copy) max-length) 52 | (setq copy (concat copy " ")))) 53 | copy)) 54 | 55 | (defun periphery-quick:parse-line (line) 56 | "Parse (as LINE)." 57 | (periphery-quick:debug-log "Parsing line: %s" line) 58 | (save-match-data 59 | (if (string-match periphery-quick-regex-parser line) 60 | (let* ((file (match-string 1 line)) 61 | (linenumber (or (match-string 2 line) "1")) 62 | (column (or (match-string 3 line) "1")) 63 | (text (string-trim-left (or (match-string 4 line) ""))) 64 | (fileWithLine (format "%s:%s:%s" file linenumber column)) 65 | (display (format "%s %s" 66 | (propertize 67 | (add-right-padding-up-to 68 | (file-name-sans-extension 69 | (file-name-nondirectory file)) 70 | 24) 71 | 'face 'periphery-filename-face) 72 | text))) 73 | (periphery-quick:debug-log "Parsed line: %s" display) 74 | (list display fileWithLine)) 75 | (periphery-quick:debug-log "Failed to match line") 76 | nil))) 77 | 78 | (defun periphery-quick:goto-file-line (file line) 79 | "Go to LINE in FILE, handling the case where FILE is the current buffer." 80 | (let* ((current-file (buffer-file-name)) 81 | (project-root (periphery-helper:project-root-dir)) 82 | (full-file-path (expand-file-name file project-root))) 83 | (periphery-quick:debug-log "Full file path: %s" full-file-path) 84 | (if (and current-file (file-equal-p full-file-path current-file)) 85 | (progn 86 | (periphery-quick:debug-log "Navigating within current file to line %d" line) 87 | (goto-char (point-min)) 88 | (forward-line (1- line))) 89 | (if (file-exists-p full-file-path) 90 | (progn 91 | (find-file full-file-path) 92 | (goto-char (point-min)) 93 | (forward-line (1- line))) 94 | (message "File not found: %s" full-file-path))))) 95 | 96 | ;;;###autoload 97 | (defun periphery-quick:run-query (query) 98 | "Run query (as QUERY)." 99 | (periphery-quick:debug-log "Running query: %s" query) 100 | (let ((default-directory (periphery-helper:project-root-dir))) 101 | (periphery-quick:debug-log "Default directory: %s" default-directory) 102 | (async-start-command-to-string 103 | :command (format "rg -wse '%s' --color=never --no-heading --with-filename --line-number --column --sort path" query) 104 | :callback (lambda (output) 105 | (periphery-quick:debug-log "Query output received, length: %d" (length output)) 106 | (periphery-quick:parse output))))) 107 | 108 | (defun periphery-quick:run-query-file (query file) 109 | "Run query (as QUERY) on file." 110 | (let ((file file) 111 | (query query)) 112 | (async-start-command-to-string 113 | :command (format "rg -wse \'%s\' %s --color=never --no-heading --with-filename --line-number --column" query file) 114 | :callback (lambda (output) 115 | (periphery-quick:parse output))))) 116 | 117 | (defun periphery-quick:find-in-file () 118 | "Quick find in file." 119 | (interactive) 120 | (let ((file (buffer-file-name))) 121 | (if-let* ((query (thing-at-point 'symbol))) 122 | (periphery-quick:run-query-file query file) 123 | (periphery-quick:run-query-file (read-string "Query: ") file)))) 124 | 125 | (defun periphery-quick:find-ask () 126 | "Quickfind but ask user for input." 127 | (interactive) 128 | (let ((default-directory (periphery-helper:project-root-dir)) 129 | (query (read-string "Query: "))) 130 | (when (> (length query) 0) 131 | (async-start-command-to-string 132 | :command (format "rg -S \'%s\' --color=never --no-heading --with-filename --line-number --column" query) 133 | :callback (lambda (output) 134 | (periphery-quick:parse output)))))) 135 | 136 | (defun periphery-quick:find () 137 | "Quick find something in project." 138 | (interactive) 139 | (if-let* ((query (thing-at-point 'symbol))) 140 | (periphery-quick:run-query query) 141 | (periphery-quick:run-query (read-string "Query: ")))) 142 | 143 | (defun periphery-quick:todos () 144 | "Find the todos in the project." 145 | (interactive) 146 | (periphery-quick:run-query (regexp-quote "(NOTE|FIXME|FIX|TODO|HACK|PERF):"))) 147 | 148 | (cl-defun periphery-quick:showmenu-with-title (&key title &key list) 149 | "Build menu with (TITLE LIST)." 150 | (let* ((choices (seq-map (lambda (item) item) list)) 151 | (choice (completing-read title choices))) 152 | (car (cdr (assoc choice choices))))) 153 | 154 | (provide 'periphery-quick) 155 | ;;; periphery-quick.el ends here 156 | 157 | 158 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-core.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-core.el --- Core functionality for periphery system -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | ;; Core parsing engine that uses the configuration system to process various inputs. 5 | 6 | ;;; Code: 7 | 8 | (require 'periphery-config) 9 | (require 'periphery-helper) 10 | (require 'cl-lib) 11 | 12 | ;; Forward declaration to avoid circular dependency 13 | (defvar periphery-debug) 14 | 15 | (defvar periphery-core-error-list '() 16 | "Current list of parsed errors/warnings/matches.") 17 | 18 | (defvar periphery-core-last-input nil 19 | "Cache of last processed input for debugging.") 20 | 21 | ;;;###autoload 22 | (cl-defun periphery-core-parse (&key input type parsers callback query) 23 | "Parse INPUT using parsers of given TYPE or specific PARSERS list. 24 | TYPE can be :compiler, :search, :linter, or :test. 25 | PARSERS can be a list of parser IDs to use. 26 | CALLBACK is called with the parsed results. 27 | QUERY is an optional search query for highlighting in search results." 28 | (when periphery-debug 29 | (message "periphery-core-parse called with type: %s, query: %s" type query)) 30 | 31 | (setq periphery-core-last-input input) 32 | (setq periphery-core-error-list '()) 33 | 34 | (let ((parsers-to-use (or parsers 35 | (mapcar #'car (periphery-get-parsers-by-type type))))) 36 | 37 | (when periphery-debug 38 | (message "Parsers to use: %S" parsers-to-use)) 39 | 40 | ;; Process input through each parser 41 | (dolist (parser-id parsers-to-use) 42 | (when-let ((config (periphery-get-parser parser-id))) 43 | (when periphery-debug 44 | (message "Applying parser: %s" parser-id)) 45 | (periphery-core--apply-parser input config query))) 46 | 47 | ;; Remove duplicates and sort 48 | (setq periphery-core-error-list 49 | (periphery-core--sort-results 50 | (delete-dups periphery-core-error-list))) 51 | 52 | (when periphery-debug 53 | (message "Found %d errors" (length periphery-core-error-list))) 54 | 55 | ;; Call callback if provided 56 | (when callback 57 | (funcall callback periphery-core-error-list)) 58 | 59 | periphery-core-error-list)) 60 | 61 | (defun periphery-core--apply-parser (input config &optional query) 62 | "Apply parser CONFIG to INPUT and collect results. 63 | Optional QUERY is passed to the parser function if it accepts it." 64 | (when-let ((parse-fn (plist-get config :parse-fn))) 65 | ;; Apply filter if provided 66 | (let ((filter-fn (plist-get config :filter-fn))) 67 | (when filter-fn 68 | (setq input (funcall filter-fn input)))) 69 | 70 | ;; Parse each line 71 | (dolist (line (split-string input "\n")) 72 | (when (and line (not (string-empty-p line))) 73 | (when periphery-debug 74 | (message " Parsing line (%d chars): %s" (length line) line)) 75 | (let ((result (if query 76 | (funcall parse-fn line query) 77 | (funcall parse-fn line)))) 78 | (when result 79 | (when periphery-debug 80 | (message " -> Got result!")) 81 | (push result periphery-core-error-list))))))) 82 | 83 | (defun periphery-core--sort-results (results) 84 | "Sort RESULTS by severity and file." 85 | (sort results 86 | (lambda (a b) 87 | (let ((severity-a (periphery-core--get-severity (car a))) 88 | (severity-b (periphery-core--get-severity (car b)))) 89 | (if (equal severity-a severity-b) 90 | (string< (car a) (car b)) 91 | (< severity-a severity-b)))))) 92 | 93 | (defun periphery-core--get-severity (entry) 94 | "Get numeric severity from ENTRY for sorting. 95 | Errors = 1, Warnings = 2, Info = 3, etc." 96 | (let ((type (downcase (or (ignore-errors (aref (cadr entry) 0)) "")))) 97 | (cond 98 | ((string-match-p "error" type) 1) 99 | ((string-match-p "warning" type) 2) 100 | ((string-match-p "fixme\\|fix" type) 3) 101 | ((string-match-p "todo" type) 4) 102 | ((string-match-p "note\\|info" type) 5) 103 | (t 6)))) 104 | 105 | ;;;###autoload 106 | (cl-defun periphery-core-build-entry (&key path file line column 107 | severity message face-fn) 108 | "Build a standard periphery entry. 109 | PATH is the full path with line:column. 110 | FILE is the file path. 111 | LINE is the line number. 112 | COLUMN is optional column number. 113 | SEVERITY is the error/warning type. 114 | MESSAGE is the description. 115 | FACE-FN is a function to determine face from severity." 116 | (let ((face (if face-fn 117 | (funcall face-fn severity) 118 | 'periphery-error-face))) 119 | (list path 120 | (vector 121 | (periphery-core--propertize-severity severity face) 122 | (propertize (file-name-sans-extension 123 | (file-name-nondirectory file)) 124 | 'face 'periphery-filename-face) 125 | (propertize (or line "0") 'face 'periphery-linenumber-face) 126 | ;; Don't overwrite existing face properties in message 127 | (if (periphery-core--has-face-properties message) 128 | message ; Keep existing properties 129 | (propertize message 'face 'periphery-message-face)))))) 130 | 131 | (defun periphery-core--has-face-properties (string) 132 | "Check if STRING has any face properties." 133 | (let ((pos 0) 134 | (len (length string)) 135 | (has-face nil)) 136 | (while (and (< pos len) (not has-face)) 137 | (when (get-text-property pos 'face string) 138 | (setq has-face t)) 139 | (setq pos (1+ pos))) 140 | has-face)) 141 | 142 | (defun periphery-core--propertize-severity (severity face) 143 | "Format and colorize SEVERITY with FACE." 144 | (let* ((type (upcase (string-trim severity))) 145 | (display (if (> (string-width type) 8) 146 | (substring type 0 8) 147 | type))) 148 | (propertize (format " %s " (periphery-core--center-text display)) 149 | 'face face))) 150 | 151 | (defun periphery-core--center-text (text) 152 | "Center TEXT to standard width." 153 | (let* ((target-width 8) 154 | (text-width (string-width text)) 155 | (padding (/ (- target-width text-width) 2)) 156 | (result (concat (make-string padding ?\s) text))) 157 | (while (< (string-width result) (1- target-width)) 158 | (setq result (concat result " "))) 159 | result)) 160 | 161 | ;;;###autoload 162 | (defun periphery-core-run-async (input type callback) 163 | "Parse INPUT asynchronously using parsers of TYPE. 164 | CALLBACK is called with results when complete." 165 | (run-with-idle-timer 166 | 0.1 nil 167 | (lambda () 168 | (condition-case err 169 | (periphery-core-parse 170 | :input input 171 | :type type 172 | :callback callback) 173 | (error 174 | (message "Periphery async parse failed: %s" 175 | (error-message-string err))))))) 176 | 177 | ;;;###autoload 178 | (defun periphery-core-clear () 179 | "Clear current error list and cached data." 180 | (interactive) 181 | (setq periphery-core-error-list '() 182 | periphery-core-last-input nil) 183 | (message "Periphery data cleared")) 184 | 185 | ;; Compatibility layer - moved to main periphery.el to avoid circular dependencies 186 | 187 | (provide 'periphery-core) 188 | ;;; periphery-core.el ends here -------------------------------------------------------------------------------- /modules/mk-ui.el: -------------------------------------------------------------------------------- 1 | ;;; mk-ui.el --- UI enhancements -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; UI enhancements and visual improvements for Emacs. 4 | ;;; Code: 5 | 6 | (use-package spotlight-mode 7 | :ensure nil 8 | :hook (after-init . spotlight-mode) 9 | :config 10 | (setopt spotlight-mode-ignore-buffers '("*Messages*" "*scratch*" "*Android Emulator*") 11 | spotlight-mode-always-color-buffers '() 12 | spotlight-mode-always-darken-buffers-regexp '("\\*.*\\*") 13 | spotlight-active-dim-percentage 0 14 | spotlight-inactive-lighten-percentage 5 15 | spotlight-always-darken-percentage 15)) 16 | 17 | (use-package darkroom 18 | :defer t 19 | :bind ("C-x C-d" . darkroom-tentative-mode) 20 | :config 21 | (setq darkroom-text-scale-increase 1.4 22 | darkroom-margins '(5 . 0))) 23 | 24 | (use-package punch-line 25 | :ensure nil 26 | :defer t 27 | :bind(("C-x t n" . punch-line-what-am-i-doing-next) 28 | ("C-x t N" . punch-line-what-am-i-doing-next-task) 29 | ("C-x t d" . punch-line-what-am-i-doing-done) 30 | ("C-x t a" . punch-line-what-am-i-doing-show-all) 31 | (:repeat-map punch-line-repeat-map 32 | ("n" . punch-line-what-am-i-doing-next) 33 | ("N" . punch-line-what-am-i-doing-next-task) 34 | ("d" . punch-line-what-am-i-doing-done) 35 | ("a" . punch-line-what-am-i-doing-show-all))) 36 | :hook ((after-init . punch-line-mode) 37 | (after-init . punch-weather-update) 38 | (after-init . punch-load-tasks)) 39 | :config 40 | (setopt punch-show-project-info nil 41 | punch-line-modal-use-fancy-icon nil 42 | punch-line-modal-divider-style 'none 43 | punch-line-modal-size 'large 44 | punch-line-left-separator " " 45 | punch-line-right-separator " " 46 | punch-line-section-padding 10 47 | punch-show-git-info t 48 | punch-show-lsp-info t 49 | punch-line-vc-use-github-icon nil 50 | punch-show-copilot-info nil 51 | punch-show-battery-info t 52 | punch-show-flycheck-info t 53 | punch-show-weather-info t 54 | punch-weather-latitude "56.7365" 55 | punch-weather-longitude "16.2981" 56 | punch-line-music-max-length 80 57 | punch-line-section-backgrounds nil 58 | punch-line-section-background-tint-start -15 59 | punch-line-section-background-tint-step 50 60 | punch-line-music-info '(:service apple))) 61 | 62 | 63 | (use-package imenu-list 64 | :after imenu-list 65 | :defer t 66 | :bind 67 | ("C-c i" . 'imenu-list-smart-toggle) 68 | :custom 69 | (imenu-list-focus-after-activation t) 70 | (imenu-list-auto-resize t)) 71 | 72 | (use-package candyshop 73 | ;; :hook (emacs-startup . candyshop-init) 74 | :ensure nil 75 | :custom 76 | (candyshop-alpha-values '(100 92)) 77 | :bind ("C-c t c" . candyshop-toggle)) 78 | 79 | (use-package nerd-icons-ibuffer 80 | :ensure t 81 | :hook (ibuffer-mode . nerd-icons-ibuffer-mode) 82 | :custom 83 | (setq nerd-icons-ibuffer-icon t) 84 | (setq nerd-icons-ibuffer-color-icon t) 85 | (setq nerd-icons-ibuffer-human-readable-size t)) 86 | 87 | (use-package dired 88 | :ensure nil 89 | :defer t 90 | :custom 91 | (dired-listing-switches "-aBhl --group-directories-first") 92 | :config 93 | (with-eval-after-load 'evil-collection 94 | (evil-collection-define-key 'normal 'dired-mode-map 95 | "h" 'dired-up-directory 96 | "l" 'dired-find-file))) 97 | 98 | (use-package which-key 99 | :ensure nil 100 | :defer t 101 | :init 102 | (run-with-idle-timer 1.5 nil #'which-key-mode) 103 | :custom 104 | (which-key-use-C-h-commands t) 105 | (which-key-separator " → ") 106 | (which-key-side-window-location 'bottom) 107 | (which-key-sort-order #'which-key-prefix-then-key-order) 108 | (which-key-sort-uppercase-first nil) 109 | (which-key-add-column-padding 2) 110 | (which-key-min-display-lines 6) 111 | (which-key-idle-delay 1.0) 112 | (which-key-max-description-length 45) 113 | (which-key-allow-imprecise-window-fit t) 114 | :config 115 | (which-key-setup-minibuffer)) 116 | 117 | (use-package mode-line-hud 118 | :ensure nil 119 | :config 120 | (setq show-in-echo-area nil)) 121 | 122 | ;; Window management configuration 123 | (use-package window 124 | :ensure nil 125 | :bind (("C-x C-f" . #'toggle-frame-fullscreen) 126 | ("C-x C-w" . #'toggle-frame-maximized) 127 | ("C-x C-s" . #'window-toggle-side-windows) 128 | ("C-x C-x" . #'mk/safe-kill-buffer-and-window)) 129 | :custom 130 | (transient-display-buffer-action 131 | '(display-buffer-below-selected 132 | (window-height . fit-window-to-buffer))) 133 | (window-resize-pixelwise nil) 134 | (window-divider-default-places t) 135 | (window-divider-default-bottom-width 1) 136 | (window-divider-default-right-width 1) 137 | (display-buffer-alist 138 | '(("\\*Async Shell Command\\*" (display-buffer-no-window)) 139 | ("\\*xwidget\\*\\|\\*xref\\*" 140 | (display-buffer-in-side-window display-buffer-reuse-mode-window display-buffer-reuse-window) 141 | (body-function . select-window) 142 | (window-width . 0.4) 143 | (slot . 1) 144 | (side . left)) 145 | ("evil-marks\\*" 146 | (display-buffer-in-side-window) 147 | (body-function . select-window) 148 | (window-height . (lambda (win) (fit-window-to-buffer win 20 10))) 149 | (window-width . 0.10) 150 | (side . right) 151 | (slot . 0)) 152 | ("\\*iOS Simulator\\|\\*swift package\\|\\*ios-device" 153 | (display-buffer-reuse-window display-buffer-in-side-window display-buffer-at-bottom) 154 | (window-height . (lambda (win) (fit-window-to-buffer win 20 10))) 155 | (window-parameters . ((mode-line-format . none))) 156 | (slot . 100)) 157 | ("\\*Embark*" 158 | (display-buffer-in-side-window display-buffer-reuse-mode-window display-buffer-at-bottom) 159 | (window-height . (lambda (win) (fit-window-to-buffer win 20 10))) 160 | (window-parameters . ((select-window . t))) 161 | (slot . 5)) 162 | ("\\*Copilot Chat*" 163 | (display-buffer-in-side-window) 164 | (body-function . select-window) 165 | (window-width . 0.45) 166 | (side . right) 167 | (slot . 2) 168 | (window-parameters . ((mode-line-format . none)))) 169 | ("\\*Periphery\\*\\|\\*compilation\\*" 170 | (display-buffer-reuse-window display-buffer-in-side-window display-buffer-at-bottom) 171 | (body-function . select-window) 172 | (window-height . (lambda (win) (fit-window-to-buffer win 20 10))) 173 | (slot . 10)) 174 | ("\\*Android Emulator\\*\\|\\*Android Logcat\\*\\|\\*Android Emulator Error\\*" 175 | (display-buffer-reuse-window display-buffer-in-side-window display-buffer-at-bottom) 176 | (body-function . select-window) 177 | (window-height . 0.2) 178 | (window-width . 0.70) 179 | (slot . 2)) 180 | ("\\*Faces\\|[Hh]elp\\*\\|\\*Copilot*\\|\\*Occur\\*" 181 | (display-buffer-in-side-window) 182 | (body-function . select-window) 183 | (window-width . 0.4) 184 | (side . right) 185 | (slot . 1)) 186 | ("\\*e?shell\\|*ellama\\|\\*vterm\\*" 187 | (display-buffer-at-bottom display-buffer-reuse-window) 188 | (body-function . select-window) 189 | (window-height . 0.13) 190 | (window-parameters . ((mode-line-format . none))) 191 | (side . bottom) 192 | (slot . 10)) 193 | ("\\*\\(Flycheck\\|Package-Lint\\).*" 194 | (display-buffer-reuse-window display-buffer-below-selected) 195 | (window-height . (lambda (win) (fit-window-to-buffer win 20 10))) 196 | (dedicated . t) 197 | (window-parameters . ((no-other-window . t) 198 | (mode-line-format . none))))))) 199 | 200 | 201 | ;;; Provide 202 | (provide 'mk-ui) 203 | ;;; mk-ui.el ends here. 204 | -------------------------------------------------------------------------------- /localpackages/periphery/periphery-helper.el: -------------------------------------------------------------------------------- 1 | ;;; periphery-helper.el --- Process and text helping package ;;; -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;;; Utility package for handling xcode-projects and json data. 4 | 5 | ;;; Code: 6 | 7 | (require 'async) 8 | (require 'json) 9 | (require 'project) 10 | (require 'cl-lib) 11 | 12 | (defconst periphery-parse-line-regex "^\\([^:]+\\):\\([0-9]+\\)?:\\(\\([0-9]+\\)\\)?" 13 | "Parse linenumber and columns.") 14 | 15 | ;;;###autoload 16 | (defun periphery-helper:project-root-dir () 17 | "Get the root directory of the current project." 18 | (let ((project (project-current nil))) 19 | (if project 20 | (directory-file-name 21 | (file-name-as-directory 22 | (expand-file-name (project-root project)))) 23 | default-directory))) 24 | 25 | (cl-defun async-start-shell-command-to-json (&key command &key callback) 26 | "Async shell command to JSON run async (as COMMAND CALLBACK)." 27 | (async-start-command-to-string 28 | :command command 29 | :callback (lambda (result) 30 | (let* ((json-object (json-read-from-string result))) 31 | (funcall ,callback json-object))))) 32 | 33 | (cl-defun async-start-command-to-string (&key command callback (update-callback nil) (debug nil)) 34 | "Run COMMAND asynchronously, optionally call UPDATE-CALLBACK with incremental output, and CALLBACK with the final result." 35 | (when debug 36 | (message "Starting async-start-command-to-string with command: %s" command)) 37 | (let ((output-buffer (generate-new-buffer "*async-command-output*")) 38 | (process nil)) 39 | (setq process 40 | (make-process 41 | :name "async-command" 42 | :buffer output-buffer 43 | :command (list shell-file-name shell-command-switch command) 44 | :filter (lambda (proc string) 45 | (when debug (message "Received output chunk (length %d): %s" (length string) string)) 46 | (when (functionp update-callback) 47 | (condition-case err 48 | (funcall update-callback string) 49 | (error (message "Error in update-callback: %S" err)))) 50 | (with-current-buffer (process-buffer proc) 51 | (goto-char (point-max)) 52 | (insert string))) 53 | :sentinel (lambda (process event) 54 | (when debug (message "Process event: %s" event)) 55 | (when (string= event "finished\n") 56 | (when debug (message "Process finished, preparing to call callback")) 57 | (let ((result (with-current-buffer (process-buffer process) 58 | (buffer-string)))) 59 | (when debug 60 | (message "Result length: %d" (length result)) 61 | (message "Result content: %s" result)) 62 | (if (functionp callback) 63 | (condition-case err 64 | (progn 65 | (when debug (message "Calling callback")) 66 | (funcall callback result)) 67 | (error (message "Error in callback: %S" err))))) 68 | (kill-buffer output-buffer))))) 69 | (when debug 70 | (message "Process started with PID: %s" (process-id process))) 71 | process)) 72 | 73 | (cl-defun async-start-command (&key command &key callback) 74 | "Async shell command run async (as COMMAND) and call (as CALLBACK)." 75 | (async-start 76 | `(lambda () 77 | (shell-command ,command)) 78 | `(lambda (result) 79 | (funcall ,callback)))) 80 | 81 | (cl-defun message-with-color (&key tag &key text &key attributes) 82 | "Print a TAG and TEXT with ATTRIBUTES." 83 | (message "%s %s" (propertize tag 'face attributes) text)) 84 | 85 | ;;; Processes 86 | (defun command-string-to-list (cmd) 87 | "Split the CMD unless it is a list. This function respects quotes." 88 | (if (listp cmd) cmd (split-string-and-unquote cmd))) 89 | 90 | (cl-defun run-async-command-in-buffer (&key command &key buffername) 91 | "Run async-command in xcodebuild buffer (as COMMAND and BUFFERNAME)." 92 | (inhibit-sentinel-messages #'async-shell-command command buffername)) 93 | 94 | (defun inhibit-sentinel-messages (fun &rest args) 95 | "Inhibit messages in all sentinels started by FUN and ARGS." 96 | (cl-letf* ((old-set-process-sentinel (symbol-function 'set-process-sentinel)) 97 | ((symbol-function 'set-process-sentinel) 98 | (lambda (process sentinel) 99 | (funcall 100 | old-set-process-sentinel 101 | process 102 | `(lambda (&rest args) 103 | (cl-letf (((symbol-function 'message) #'ignore)) 104 | (apply (quote ,sentinel) args))))))) 105 | (apply fun args))) 106 | 107 | (defun periphery-helper:filter-keep-beginning-paths (text) 108 | "Filter lines starting with '/' from TEXT." 109 | (with-temp-buffer 110 | (insert text) 111 | (keep-lines "^/") 112 | (buffer-string))) 113 | 114 | (defun open-current-line-with (data) 115 | "Open current line with DATA." 116 | (when data 117 | ;; Handle build failures and other non-file paths 118 | (cond 119 | ;; Skip if data looks like a build command or contains build failure info 120 | ((or (string-match-p "^/Applications/Xcode.app" data) 121 | (string-match-p "swift-frontend" data) 122 | (string= data "_Build Failure")) 123 | (message "Cannot open file for build failure or command: %s" 124 | (if (> (length data) 100) 125 | (concat (substring data 0 100) "...") 126 | data))) 127 | ;; Normal file path handling 128 | (t 129 | (save-match-data 130 | (and (string-match periphery-parse-line-regex data) 131 | (when-let* ((file (match-string 1 data)) 132 | (linenumber (string-to-number (match-string 2 data))) 133 | (column (match-string 3 data)) 134 | (project-root (periphery-helper:project-root-dir)) 135 | (full-file-path (if (file-name-absolute-p file) 136 | file 137 | (expand-file-name file project-root)))) 138 | (if (file-exists-p full-file-path) 139 | (with-current-buffer (find-file full-file-path) 140 | (when (> linenumber 0) 141 | (goto-char (point-min)) 142 | (when (> linenumber 1) 143 | (forward-line (1- linenumber))) 144 | (if-let* ((columnnumber (string-to-number column))) 145 | (when (> columnnumber 0) 146 | (forward-char (1- columnnumber))))) 147 | (recenter)) 148 | (message "File not found: %s" full-file-path))))))))) 149 | 150 | (cl-defun async-shell-command-to-string (&key process-name &key command &key callback) 151 | "Execute shell command COMMAND asynchronously in the background. 152 | PROCESS-NAME is the name of the process." 153 | (let* ((output-buffer (generate-new-buffer process-name)) 154 | (callback-fun callback)) 155 | (set-process-sentinel 156 | (start-process process-name output-buffer shell-file-name shell-command-switch command) 157 | (lambda (process signal) 158 | (when (memq (process-status process) '(exit signal)) 159 | (with-current-buffer output-buffer 160 | (let ((output-string 161 | (buffer-substring-no-properties 162 | (point-min) 163 | (point-max)))) 164 | (funcall callback-fun output-string))) 165 | (kill-buffer output-buffer)))) 166 | output-buffer)) 167 | 168 | (defun do-call-process (executable infile destination display args) 169 | "Wrapper for `call-process'. 170 | 171 | EXECUTABLE may be a string or a list. The string is split by spaces, 172 | then unquoted. 173 | For INFILE, DESTINATION, DISPLAY, see `call-process'. 174 | ARGS are rest arguments, appended to the argument list. 175 | Returns the exit status." 176 | (let ((command-list 177 | (append (command-string-to-list executable) args))) 178 | (apply 'call-process 179 | (append 180 | (list (car command-list)) 181 | (list infile destination display) 182 | (cdr command-list))))) 183 | 184 | (defun call-process-to-json (executable &rest args) 185 | "Call EXECUTABLE synchronously in separate process. 186 | 187 | The output is parsed as a JSON document. 188 | EXECUTABLE may be a string or a list. The string is split by spaces, 189 | then unquoted. 190 | ARGS are rest arguments, appended to the argument list." 191 | (with-temp-buffer 192 | (unless (zerop 193 | (do-call-process executable 194 | nil 195 | ;; Disregard stderr output, as it 196 | ;; corrupts JSON. 197 | (list t nil) 198 | nil 199 | args)) 200 | (error "%s: %s %s %s" "Cannot invoke executable" executable (buffer-string) default-directory)) 201 | (goto-char (point-min)) 202 | (json-read))) 203 | 204 | (provide 'periphery-helper) 205 | 206 | ;;; periphery-helper.el ends here 207 | -------------------------------------------------------------------------------- /modules/mk-org.el: -------------------------------------------------------------------------------- 1 | ;; -*- lexical-binding: t; -*- 2 | ;;; Code: 3 | (use-package org 4 | :hook ((org-mode . org-display-inline-images) 5 | (org-mode . my/org-prettify-symbols)) 6 | :config 7 | (defun my/org-prettify-symbols () 8 | (setq prettify-symbols-alist 9 | (mapcan (lambda (x) (list x (cons (upcase (car x)) (cdr x)))) 10 | '(("#+begin_src" . 9998) ; ✎ 11 | ("#+end_src" . " ") ; 12 | ("#+results:" . 9776) ; ☰ 13 | ("#+attr_latex:" . "🄛") 14 | ("#+attr_html:" . "🄗") 15 | ("#+attr_org:" . "🄞") 16 | ("#+name:" . "🄝") ; 127261 17 | ("#+caption:" . "🄒") ; 127250 18 | ("#+startup:" . 10034) ; ✲ 19 | ("#+options:" . 9965) ; ⛭ 20 | ("#+begin_quote" . 187) ; » 21 | ("#+end_quote" . 171) ; « 22 | ("#+begin_results" . 8943) ; ⋯ 23 | ("#+end_results" . 8943) ; ⋯ 24 | ))) 25 | (setq prettify-symbols-unprettify-at-point t) 26 | (prettify-symbols-mode 1)) 27 | 28 | (setq org-lowest-priority ?F) ;; Gives us priorities A through F 29 | (setq org-default-priority ?E) ;; If an item has no priority, it is considered [#E]. 30 | 31 | (setq org-priority-faces 32 | '((65 . "#BF616A") 33 | (66 . "#EBCB8B") 34 | (67 . "#B48EAD") 35 | (68 . "#81A1C1") 36 | (69 . "#5E81AC") 37 | (70 . "#4C566A"))) 38 | 39 | (setq org-ellipsis "…" 40 | ;; org-agenda-files '("work.org" "projekt.org") 41 | org-agenda-block-separator ?─ 42 | org-agenda-files '("~/Desktop/org/agenda.org") 43 | org-agenda-skip-deadline-if-done t 44 | org-agenda-skip-scheduled-if-deadline-is-shown t 45 | org-agenda-skip-scheduled-if-done t 46 | org-agenda-skip-timestamp-if-deadline-is-shown t 47 | org-agenda-skip-timestamp-if-done t 48 | org-agenda-span 1 49 | org-agenda-start-day "+0d" 50 | org-agenda-tags-column 0 51 | org-agenda-time-grid 52 | '((daily today require-timed) 53 | (800 1000 1200 1400 1600 1800 2000) 54 | " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") 55 | org-agenda-custom-commands '(("v" "Agenda and todos" 56 | ((tags "PRIORITY=\"A\"" 57 | ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) 58 | (org-agenda-overriding-header "HIGH PRIORITY unfinished tasks:"))) 59 | (tags "PRIORITY=\"B\"" 60 | ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) 61 | (org-agenda-overriding-header "MEDIUM PRIORITY unfinished tasks:"))) 62 | (tags "PRIORITY=\"C\"" 63 | ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) 64 | (org-agenda-overriding-header "LOW PRIORITY unfinished tasks:"))) 65 | (agenda "") 66 | (alltodo "")))) 67 | org-auto-align-tags nil 68 | org-clock-sound "~/.emacs.d/etc/sound/bell.mp3" 69 | org-confirm-babel-evaluate nil 70 | org-cycle-separator-lines 2 71 | org-directory "~/Desktop/org/Todo/" 72 | org-fontify-emphasized-text t 73 | org-fontify-whole-heading-line t 74 | org-hide-emphasis-markers t 75 | org-adapt-indentation t 76 | org-hide-leading-stars t 77 | org-log-done 'time 78 | org-log-into-drawer t 79 | org-pretty-entities t 80 | org-return-follows-link t 81 | org-src-edit-src-content-indentation 0 82 | org-src-fontify-natively t 83 | org-src-tab-acts-natively t 84 | org-fontify-whole-heading-line t 85 | org-src-preserve-indentation t 86 | font-lock-maximum-decoration t 87 | org-element-use-cache t 88 | org-src-tab-acts-natively t 89 | org-startup-folded nil 90 | org-startup-with-inline-images t 91 | org-tags-column 0 92 | org-agenda-current-time-string 93 | "◀── now ─────────────────────────────────────────────────") 94 | 95 | (setq org-todo-keywords 96 | '((sequence 97 | "TODO" "PROJ" "READ" "CHECK" "IDEA" ; Needs further action 98 | "|" 99 | "DONE"))) ; Needs no action currently 100 | 101 | (setq org-todo-keyword-faces 102 | '(("TODO" :inherit (org-todo region) :foreground "#A3BE8C" :weight bold) 103 | ("PROJ" :inherit (org-todo region) :foreground "#88C0D0" :weight bold) 104 | ("READ" :inherit (org-todo region) :foreground "#8FBCBB" :weight bold) 105 | ("CHECK" :inherit (org-todo region) :foreground "#81A1C1" :weight bold) 106 | ("IDEA" :inherit (org-todo region) :foreground "#EBCB8B" :weight bold) 107 | ("DONE" :inherit (org-todo region) :foreground "#30343d" :weight bold))) 108 | 109 | ) 110 | 111 | (defun mk/play-sound (origin-fn sound) 112 | "Play a sound when a task is marked as done. 113 | ORIGIN-FN is the original function being advised. 114 | SOUND is the sound specification to play." 115 | (cl-destructuring-bind (_ _ file) sound 116 | (make-process :name (concat "play-sound-" file) 117 | :connection-type 'pipe 118 | :command `("afplay" ,file)))) 119 | (advice-add 'play-sound :around 'mk/play-sound) 120 | 121 | (with-eval-after-load 'org 122 | 123 | (add-hook 'org-babel-after-execute-hook (lambda () 124 | (when org-inline-image-overlays 125 | (org-redisplay-inline-images)))) 126 | 127 | (require 'org-tempo) 128 | ;; (require 'ob-swiftui) 129 | ;; (ob-swiftui-setup) 130 | 131 | (setq-local org-confirm-babel-evaluate t) 132 | 133 | (custom-set-faces 134 | '(org-level-1 ((t (:inherit outline-1 :height 1.3 :weight bold)))) 135 | '(org-level-2 ((t (:inherit outline-2 :height 1.18 :weight bold)))) 136 | '(org-level-3 ((t (:inherit outline-3 :height 1.16 :weight bold)))) 137 | '(org-level-4 ((t (:inherit outline-4 :height 1.15 :weight bold)))) 138 | '(org-level-5 ((t (:inherit outline-5 :height 1.1 :weight bold)))) 139 | '(org-level-6 ((t (:inherit outline-5 :height 1 :weight bold)))) 140 | '(org-level-7 ((t (:inherit outline-5 :height 1 :weight semi-bold)))) 141 | '(org-block-begin-line ((t (:foreground "#678" :underline t :background nil)))) 142 | '(org-block-end-line ((t (:foreground "#678" :overline t :background nil ))))) 143 | 144 | (setq org-custom-todo-faces ' 145 | (("TODO" :background "#FF5D62" :distant-foreground "#FF5D62" :foreground "#FFFFFF" :weight 'bold) 146 | ("NEXT" :background "#7FB4CA" :distant-foreground "#7FB4CA" :foreground "#1c1c24" :weight 'bold) 147 | ("STARTED" :background "#957FB8" :foreground "#FFFFFF" :weight 'bold) 148 | ("DELEGATED" :background "#7AA89F" :foreground "#1c1c24" :weight 'bold) 149 | ("QA" :background "#54536D" :weight 'bold))) 150 | 151 | (org-babel-do-load-languages 'org-babel-load-languages 152 | '((emacs-lisp . t) 153 | ;; (swift . t) 154 | ;; (kotlin . t) 155 | (shell . t) 156 | ;; (restclient . t) 157 | )) 158 | 159 | (add-to-list 'org-structure-template-alist '("sh" . "src shell")) 160 | (add-to-list 'org-structure-template-alist '("sw" . "src swift")) 161 | (add-to-list 'org-structure-template-alist '("sr" . "src restclient")) 162 | (add-to-list 'org-structure-template-alist '("swiftui" . "src swiftui :view CustomView")) 163 | (add-to-list 'org-structure-template-alist '("elisp" . "src emacs-lisp")) 164 | (add-to-list 'org-modules 'org-tempo t)) 165 | 166 | ;; (use-package ob-restclient 167 | ;; :defer t) 168 | ;; 169 | (use-package ob-swift 170 | :defer t 171 | :after org 172 | :config 173 | (add-to-list 'org-src-lang-modes '("swift" . swift)) 174 | (org-babel-do-load-languages 'org-babel-load-languages 175 | (append org-babel-load-languages 176 | '((swift . t))))) 177 | (use-package ob-swiftui 178 | :defer t 179 | :after org 180 | :config 181 | (add-hook 'org-babel-after-execute-hook (lambda () 182 | (when org-inline-image-overlays 183 | (org-redisplay-inline-images)))) 184 | (add-to-list 'org-babel-tangle-lang-exts 185 | '("swiftui" . "swift")) 186 | (add-to-list 'org-src-lang-modes 187 | '("swiftui" . swift)) 188 | (ob-swiftui-setup)) 189 | ;; 190 | ;; (use-package ob-kotlin 191 | ;; :defer t 192 | ;; :after org-mode 193 | ;; :config 194 | ;; (add-to-list 'org-babel-tangle-lang-exts 195 | ;; '("kotlin" . "kt")) 196 | ;; (add-to-list 'org-src-lang-modes 197 | ;; '("kotlin" . kotlin)) 198 | ;; (ob-kotlin-setup)) 199 | 200 | (use-package org-superstar 201 | :after org 202 | :config 203 | (setq org-superstar-leading-bullet ?\s) 204 | (setq org-superstar-leading-bullet " ") 205 | (setq org-superstar-special-todo-items t) ;; Makes TODO header bullets into boxes 206 | (setq org-superstar-todo-bullet-alist '(("TODO" . 9744) 207 | ("DONE" . 9744) 208 | ("READ" . 9744) 209 | ("IDEA" . 9744) 210 | ("WAITING" . 9744) 211 | ("CANCELLED" . 9744) 212 | ("PROJECT" . 9744) 213 | ("POSTPONED" . 9744)))) 214 | 215 | (use-package org-modern 216 | :hook ((org-mode . global-org-modern-mode)) 217 | :config 218 | (setq 219 | org-auto-align-tags t 220 | org-tags-column 0 221 | org-fold-catch-invisible-edits 'show-and-error 222 | org-special-ctrl-a/e t 223 | org-insert-heading-respect-content t 224 | org-modern-block t 225 | org-modern-block-name nil 226 | org-modern-star '("❶" "❷" "❸" "❹" "❺" "❻" "❼") 227 | 228 | ;; Don't style the following 229 | org-modern-tag nil 230 | org-modern-priority nil 231 | org-modern-todo nil 232 | org-modern-table nil 233 | 234 | ;; Agenda styling 235 | org-agenda-tags-column 0 236 | org-agenda-block-separator ?─ 237 | org-agenda-time-grid 238 | '((daily today require-timed) 239 | (800 1000 1200 1400 1600 1800 2000) 240 | " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") 241 | org-agenda-current-time-string 242 | "⭠ now ─────────────────────────────────────────────────")) 243 | 244 | (use-package olivetti 245 | :hook ((org-mode . olivetti-mode)) 246 | :custom 247 | (olivetti-style 'fancy) 248 | (olivetti-body-width 120) 249 | (olivetti-hide-mode-line t)) 250 | 251 | ;;; Provide 252 | (provide 'mk-org) 253 | ;;; mk-org.el ends here. 254 | -------------------------------------------------------------------------------- /modules/mk-code-completion.el: -------------------------------------------------------------------------------- 1 | ;;; mk-code-completion.el --- Code completion configuration -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; This file contains configurations related to code completion in Emacs. 4 | ;;; Code: 5 | 6 | ;; Dependencies loaded on demand 7 | (declare-function eglot-ensure "eglot") 8 | (declare-function eldoc-box-hover-mode "eldoc-box") 9 | 10 | (defun mk/setup-elisp-capf () 11 | "Set `completion-at-point-functions´ for Elisp." 12 | (setq-local completion-at-point-functions 13 | (list (cape-capf-super 14 | #'cape-elisp-symbol 15 | #'cape-elisp-block 16 | #'cape-dabbrev 17 | #'cape-file 18 | #'cape-keyword 19 | #'elisp-completion-at-point)))) 20 | (use-package cape 21 | :ensure t 22 | :after evil 23 | :init 24 | (add-hook 'completion-at-point-functions #'cape-dabbrev) ;; Complete word from current buffers 25 | (add-hook 'completion-at-point-functions #'cape-dict) ;; Dictionary completion 26 | (add-hook 'completion-at-point-functions #'cape-file) ;; Path completion 27 | (add-hook 'completion-at-point-functions #'cape-elisp-block) ;; Complete elisp in Org or Markdown mode 28 | (add-hook 'completion-at-point-functions #'cape-keyword) ;; Keyword completion 29 | ;; Add more Elisp specific backends 30 | (add-hook 'emacs-lisp-mode-hook #'mk/setup-elisp-capf) 31 | ;; (add-hook 'minibuffer-setup-hook #'mk/setup-elisp-capf) 32 | 33 | :bind ( 34 | ("C-c p p" . completion-at-point) ;; capf 35 | ("C-c p d" . cape-dabbrev) ;; or dabbrev-completion 36 | ("C-c p h" . cape-history) 37 | ("C-c p f" . cape-file) 38 | ("C-c p k" . cape-keyword) 39 | ("C-c p s" . cape-symbol) 40 | ("C-c p a" . cape-abbrev) 41 | ("C-c p i" . cape-ispell) 42 | ("C-c p l" . cape-line) 43 | ("C-c p w" . cape-dict) 44 | ("C-c p r" . cape-rfc1345)) 45 | :config 46 | (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent) 47 | (advice-add #'eglot-completion-at-point :around #'cape-wrap-buster)) 48 | 49 | (use-package eglot 50 | :defer t 51 | :hook (((swift-ts-mode) . (lambda () 52 | (require 'swift-lsp) 53 | (eglot-ensure))) 54 | ((kotlin-mode kotlin-ts-mode) . (lambda () (eglot-ensure)))) 55 | :ensure nil 56 | :bind 57 | ("C-c e f" . #'eglot-code-action-quickfix) 58 | ("C-c e a" . #'eglot-code-actions) 59 | ("C-c e e" . #'eglot-code-action-extract) 60 | ("C-c e R" . #'eglot-code-action-rewrite) 61 | ("C-c e r" . #'eglot-rename) 62 | ("C-c e m" . #'eglot-menu) 63 | ("C-c e d" . #'eglot-find-declaration) 64 | ("C-c e D" . #'eglot-find-typeDefinition) 65 | ("C-c e i" . #'eglot-find-implementation) 66 | ("C-c e b" . #'eglot-format-buffer) 67 | :custom 68 | (eglot-autoshutdown t) 69 | (eglot-extend-to-xref t) 70 | (eglot-ignored-server-capabilities '(:semanticTokensProvider 71 | :codeActionProvider) 72 | ) 73 | (eglot-connect-timeout 90) 74 | (eglot-report-progress nil) 75 | (eglot-events-buffer-size 0) 76 | (eglot-code-action-indicators nil) 77 | (eglot-events-buffer-config '(size: 0 :format full)) 78 | ;; (eldoc-documentation-strategy 'eldoc-documentation-compose) 79 | :config 80 | (add-to-list 'eglot-server-programs '(swift-ts-mode . swift-lsp-eglot-server-contact)) 81 | ;; (add-to-list 'eglot-server-programs 82 | ;; '((typescript-mode typescript-tsx-mode tsx-ts-mode) . ("typescript-language-server" "--stdio"))) 83 | ;; (add-hook 'typescript-mode-hook 'eglot-ensure) 84 | ;; (add-hook 'tsx-ts-mode-hook 'eglot-ensure) 85 | ;; (add-hook 'typescript-ts-mode-hook 'eglot-ensure) 86 | ;; (add-to-list 'eglot-server-programs 87 | ;; '(kotlin-mode . ("~/kotlin-lsp/kotlin-0.252.16998/kotlin-lsp.sh" "--stdio"))) 88 | ;; (add-to-list 'eglot-server-programs 89 | ;; '(kotlin-ts-mode . ("bash" "/Users/mikaelkonradsson/kotlin-lsp/kotlin-lsp.sh" "--stdio"))) 90 | (setq eglot-stay-out-of '(corfu flycheck flymake)) 91 | (setq jsonrpc-event-hook nil) 92 | (advice-add 'jsonrpc--log-event :override #'ignore)) 93 | 94 | (use-package eldoc-box 95 | :after (eldoc eglot) 96 | :custom 97 | (eldoc-box-hover-mode 1) 98 | :config 99 | (setopt eldoc-box-border-width 1 100 | eldoc-box-clear-with-C-g t)) 101 | 102 | (use-package corfu 103 | :ensure t 104 | :defer t 105 | :hook (prog-mode . global-corfu-mode) 106 | :bind 107 | (:map corfu-map 108 | ("SPC" . corfu-insert-separator) 109 | ("" . corfu-quit) 110 | ("C-g" . corfu-quit) 111 | ("C-n" . corfu-next) 112 | ("C-p" . corfu-previous) 113 | ("RET" . corfu-insert) 114 | ("C-d" . corfu-show-documentation) 115 | ("C-e" . corfu-show-location) 116 | ("C-h" . corfu-show-location) 117 | ("M-RET" . corfu-complete) 118 | ("C-j" . corfu-next) 119 | ("C-k" . corfu-previous)) 120 | :custom 121 | (corfu-auto t) 122 | (corfu-auto-prefix 2) 123 | (corfu-separator ?\s) 124 | (corfu-popupinfo-mode 'dedicated) 125 | :config 126 | (setq corfu-preselect 'valid 127 | corfu-max-width 140 128 | corfu-preview-current nil ; No preview insertion, wait for TAB 129 | corfu-quit-at-boundary 'separator 130 | corfu-scroll-margin 4 131 | corfu-quit-no-match t) 132 | :init 133 | (corfu-history-mode)) 134 | 135 | (use-package corfu-popupinfo 136 | :after corfu 137 | :ensure nil 138 | :hook (corfu-mode . corfu-popupinfo-mode) 139 | :custom 140 | (corfu-popupinfo-delay 0.1) 141 | ;; (corfu-popupinfo-delay '(0.25 . 0.1)) 142 | ;; (corfu-popupinfo-hide nil) 143 | :config 144 | (corfu-popupinfo-mode)) 145 | 146 | (use-package nerd-icons-corfu 147 | :ensure t 148 | :defer t 149 | :after (:all corfu)) 150 | 151 | (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter) 152 | 153 | (use-package savehist 154 | :ensure t 155 | :defer 5 156 | :hook (after-init . savehist-mode) 157 | :config 158 | (setq history-delete-duplicates t) 159 | (setq savehist-save-minibuffer-history t)) 160 | 161 | 162 | ;; (use-package kind-icon 163 | ;; :ensure t 164 | ;; :after corfu 165 | ;; :custom 166 | ;; (kind-icon-extra-space t) 167 | ;; (kind-icon-use-icons t) 168 | ;; (kind-icon-blend-background t) 169 | ;; (kind-icon-default-face 'corfu-default) ; only needed with blend-background 170 | ;; (kind-icon-blend-frac 0.31) ; only needed with blend-background) 171 | ;; (kind-icon-default-style 172 | ;; '(:padding -0.1 :stroke 0 :margin 0 :radius 0 :height 0.8 :scale 1.0)) 173 | ;; ;; (kind-icon-formatted 'variable) 174 | ;; :config 175 | ;; (setq kind-icon-mapping 176 | ;; '((array "a" :icon "symbol-array" :face font-lock-type-face :collection "vscode") 177 | ;; (boolean "b" :icon "symbol-boolean" :face font-lock-builtin-face :collection "vscode") 178 | ;; (color "#" :icon "symbol-color" :face success :collection "vscode") 179 | ;; (command "cm" :icon "chevron-right" :face default :collection "vscode") 180 | ;; (constant "co" :icon "symbol-constant" :face font-lock-constant-face :collection "vscode") 181 | ;; (class "c" :icon "symbol-class" :face font-lock-type-face :collection "vscode") 182 | ;; (constructor "cn" :icon "symbol-method" :face font-lock-function-name-face :collection "vscode") 183 | ;; (enum "e" :icon "symbol-enum" :face font-lock-builtin-face :collection "vscode") 184 | ;; (enummember "em" :icon "symbol-enum-member" :face font-lock-builtin-face :collection "vscode") 185 | ;; (enum-member "em" :icon "symbol-enum-member" :face font-lock-builtin-face :collection "vscode") 186 | ;; (event "ev" :icon "symbol-event" :face font-lock-warning-face :collection "vscode") 187 | ;; (field "fd" :icon "symbol-field" :face font-lock-variable-name-face :collection "vscode") 188 | ;; (file "f" :icon "symbol-file" :face font-lock-string-face :collection "vscode") 189 | ;; (folder "d" :icon "folder" :face font-lock-doc-face :collection "vscode") 190 | ;; (function "f" :icon "symbol-method" :face font-lock-function-name-face :collection "vscode") 191 | ;; (interface "if" :icon "symbol-interface" :face font-lock-type-face :collection "vscode") 192 | ;; (keyword "kw" :icon "symbol-keyword" :face font-lock-keyword-face :collection "vscode") 193 | ;; (macro "mc" :icon "lambda" :face font-lock-keyword-face) 194 | ;; (magic "ma" :icon "lightbulb-autofix" :face font-lock-builtin-face :collection "vscode") 195 | ;; (method "m" :icon "symbol-method" :face font-lock-function-name-face :collection "vscode") 196 | ;; (module "{" :icon "file-code-outline" :face font-lock-preprocessor-face) 197 | ;; (numeric "nu" :icon "symbol-numeric" :face font-lock-builtin-face :collection "vscode") 198 | ;; (operator "op" :icon "symbol-operator" :face font-lock-comment-delimiter-face :collection "vscode") 199 | ;; (param "pa" :icon "gear" :face default :collection "vscode") 200 | ;; (property "pr" :icon "symbol-property" :face font-lock-variable-name-face :collection "vscode") 201 | ;; (reference "rf" :icon "library" :face font-lock-variable-name-face :collection "vscode") 202 | ;; (snippet "S" :icon "symbol-snippet" :face font-lock-string-face :collection "vscode") 203 | ;; (string "s" :icon "symbol-string" :face font-lock-string-face :collection "vscode") 204 | ;; (struct "%" :icon "symbol-structure" :face font-lock-variable-name-face :collection "vscode") 205 | ;; (text "tx" :icon "symbol-key" :face font-lock-doc-face :collection "vscode") 206 | ;; (typeparameter "tp" :icon "symbol-parameter" :face font-lock-type-face :collection "vscode") 207 | ;; (type-parameter "tp" :icon "symbol-parameter" :face font-lock-type-face :collection "vscode") 208 | ;; (unit "u" :icon "symbol-ruler" :face font-lock-constant-face :collection "vscode") 209 | ;; (value "v" :icon "symbol-enum" :face font-lock-builtin-face :collection "vscode") 210 | ;; (variable "va" :icon "symbol-variable" :face font-lock-variable-name-face :collection "vscode") 211 | ;; (t "." :icon "question" :face font-lock-warning-face :collection "vscode"))) 212 | ;; (defun my-kind-icon--extra-space (orig-fun &rest args) 213 | ;; "Custom advice for `kind-icon--extra-space`." 214 | ;; (let ((_ (apply orig-fun args))) 215 | ;; (propertize " " 'display '(space :width 1.0)))) ; Adjusted width to 1.0 216 | ;; (advice-add 'kind-icon--extra-space :around #'my-kind-icon--extra-space) 217 | ;; (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)) 218 | 219 | (use-package orderless 220 | :ensure t 221 | :custom 222 | (completion-styles '(orderless basic)) 223 | (completion-category-overrides '((file (styles basic partial-completion))))) 224 | 225 | (provide 'mk-code-completion) 226 | ;;; mk-code-completion.el ends here 227 | -------------------------------------------------------------------------------- /themes/nordic-theme.el: -------------------------------------------------------------------------------- 1 | ;;; package: --- A beautiful theme inspired by neon lights -*- lexical-binding: t -*- 2 | 3 | ;;; Commentary: 4 | ;; A neon theme 5 | 6 | ;;; Code: 7 | 8 | (eval-when-compile 9 | (require 'cl-lib)) 10 | 11 | (require 'autothemer) 12 | 13 | (unless (>= emacs-major-version 24) 14 | (error "Requires Emacs 24 or later")) 15 | 16 | (autothemer-deftheme 17 | nordic "A port of the Neovim theme" 18 | 19 | ((((class color) (min-colors #xFFFFFF)) ; col 1 GUI/24bit 20 | ((class color) (min-colors #xFF))) ; col 2 Xterm/256 21 | 22 | ;; Define our color palette 23 | (white3 "#ECEFF4" "#eee8d5") 24 | (black "#1d2129" "#1c1c1c") 25 | (black0 "#191D24" "#120e28") 26 | (black1 "#1E222A" "#1d1741") 27 | (black2 "#222630" "#271e56") 28 | (gray0 "#242933" "#201947") 29 | (gray1 "#2E3440" "#2e2466") 30 | (gray2 "#3B4252" "#352975") 31 | (gray3 "#434C5E" "#3e318a") 32 | (gray4 "#4C566A" "#322880") 33 | (gray5 "#69728A" "#423494") 34 | (gray6 "#888ea2" "#423494") 35 | (magent_d "#A97EA1" "#7E74CC") 36 | (magenta "#B48EAD" "#7E74CC") 37 | (magent_b "#BE9dB8" "#7E74CC") 38 | (red_d "#B74E58" "#ff1d8a") 39 | (red "#BF616A" "#ff047d") 40 | (red_b "#C5727A" "#e61d7e") 41 | (green "#A3BE8C" "#859900") 42 | (green_b "#B1c89D" "#b2c62d") 43 | (blue0 "#5E81AC" "#268bd2") 44 | (blue1 "#81A1c1" "#197ec5") 45 | (blue2 "#88C0D0" "#197ec5") 46 | (yellow_d "#E7C173" "#b58900") 47 | (yellow "#EBCB8B" "#b58900") 48 | (yellow_b "#EDD49F" "#c4980f") 49 | (orange_d "#CB775D" "#c85106") 50 | (orange "#D08770" "#c85106") 51 | (orange_b "#D79784" "#c85106") 52 | (cyan_d "#80B3B2" "#74c5aa") 53 | (cyan "#8FBCBB" "#37dcf6") 54 | ) 55 | 56 | ;; Customize faces 57 | ( 58 | (default (:background gray0 :foreground white3)) 59 | (file-name-shadow (:foreground gray5)) 60 | (fringe (:background gray0)) 61 | (hl-line (:background gray1)) 62 | (header-line (:background black1 :height 0.8 :box (:line-width 7 :color black1))) 63 | (line-number (:foreground gray2)) 64 | (line-number-current-line (:background gray1 :foreground white3 :weight 'semi-bold)) 65 | (region (:background magent_d :foreground black0)) 66 | (window-divider (:background black :foreground black)) 67 | (window-divider-first-pixel (:background black :foreground black)) 68 | (window-divider-last-pixel (:background black :foreground black)) 69 | 70 | (mode-line (:background gray0 :foreground gray5 )) 71 | (mode-line-inactive (:background gray0 :foreground gray6)) 72 | (mode-line-active (:inherit 'mode-line)) 73 | (mode-line-highlight (:foreground gray6)) 74 | (mode-line-buffer-id (:foreground blue1)) 75 | 76 | (vertical-border (:foreground black)) 77 | (link (:foreground blue0)) 78 | (custom-link (:foreground blue0)) 79 | (warning (:foreground yellow_b)) 80 | (error (:foreground red_b)) 81 | (success (:foreground cyan_d)) 82 | 83 | (vertico-posframe-border (:background black)) 84 | (vertico-posframe (:background black :foreground gray6 :weight 'light)) 85 | (vertico-current (:background gray3 :foreground blue2 :bold t)) 86 | (vertico-multiline (:background black0)) 87 | (vertico-group-title (:foreground gray3 :bold t)) 88 | (vertico-group-separator (:foreground gray5 :strike-through t)) 89 | 90 | (corfu-current (:background gray3 :foreground white3 :bold t)) 91 | (corfu-annotations (:background black0)) 92 | (corfu-default (:background black0 :foreground white3)) 93 | (corfu-border (:background black0)) 94 | (corfu-popupinfo (:background black0 :weight 'light)) 95 | 96 | (eldoc-box-body (:inherit 'vertico-posframe)) 97 | (eldoc-box-border (:background black2)) 98 | 99 | (orderless-match-face-0 (:foreground red_b :weight 'bold)) 100 | (orderless-match-face-1 (:foreground blue1 :weight 'bold)) 101 | (orderless-match-face-2 (:foreground yellow_b :weight 'bold)) 102 | (orderless-match-face-3 (:foreground cyan :weight 'bold)) 103 | 104 | (minibuffer-prompt-end (:foreground yellow_b)) 105 | (minibuffer-prompt (:foreground yellow_b :weight 'bold)) 106 | 107 | (window-stool-face (:background gray2)) 108 | 109 | ;;treemacs 110 | (treemacs-directory-collapsed-face (:foreground gray6 :weight 'thin)) 111 | (treemacs-directory-face (:foreground gray6)) 112 | (treemacs-file-face (:foreground white3)) 113 | (treemacs-fringe-indicator-face (:foreground red)) 114 | (treemacs-git-added-face (:foreground green)) 115 | (treemacs-git-ignored-face (:foreground gray5)) 116 | (treemacs-git-modified-face (:foreground green_b)) 117 | (treemacs-git-renamed-face (:foreground yellow_d)) 118 | (treemacs-git-renamed-face (:foreground orange_d)) 119 | (treemacs-git-unmodified-face (:foreground white3)) 120 | (treemacs-nerd-icons-file-face (:foreground orange :weight 'semi-bold)) 121 | (treemacs-nerd-icons-root-face (:foreground blue2 :weight 'semi-bold)) 122 | (treemacs-window-background-face (:background black)) 123 | 124 | (elisp-shorthand-font-lock-face (:foreground red_b)) 125 | 126 | (font-lock-bracket-face (:foreground blue0)) 127 | (font-lock-builtin-face (:foreground yellow)) 128 | (font-lock-comment-delimiter-face (:inherit 'font-lock-comment-face)) 129 | (font-lock-comment-face (:foreground gray5 :italic t :weight 'thin)) 130 | (font-lock-constant-face (:foreground magenta :weight 'semi-bold)) 131 | (font-lock-delimiter-face (:foreground red_d)) 132 | (font-lock-doc-face (:inherit 'font-lock-comment-face)) 133 | (font-lock-doc-markup-face (:inherit 'font-lock-doc-face)) 134 | (font-lock-function-call-face (:foreground blue1)) 135 | (font-lock-function-name-face (:foreground blue2 :italic t)) 136 | (font-lock-keyword-face (:foreground orange_d :weight 'bold)) 137 | (font-lock-misc-punctuation-face (:foreground yellow_b)) 138 | (font-lock-negation-char-face (:foreground red_b)) 139 | (font-lock-number-face (:foreground magenta)) 140 | (font-lock-operator-face (:foreground red)) 141 | (font-lock-preprocessor-face (:foreground orange)) 142 | (font-lock-property-name-face (:foreground white3)) 143 | (font-lock-property-use-face (:foreground magent_b)) 144 | (font-lock-punctuation-face (:foreground yellow_b :weight 'normal)) 145 | (font-lock-reference-face (:foreground yellow)) 146 | (font-lock-regexp-regex-face (:foreground red_b)) 147 | (font-lock-regexp-grouping-backslash (:foreground red_b)) 148 | (font-lock-regexp-grouping-construct (:foreground red_b)) 149 | (font-lock-string-face (:foreground green_b :italic t :weight 'light)) 150 | (font-lock-type-face (:foreground yellow_d)) 151 | (font-lock-variable-name-face (:foreground cyan)) 152 | (font-lock-variable-use-face (:foreground cyan_d)) 153 | (font-lock-warning-face (:foreground yellow_b)) 154 | 155 | (swift-ts-face-annotation (:foreground red_d)) 156 | (swift-ts-face-annotation.builtin (:foreground magenta :weight 'semi-bold)) 157 | (swift-ts-face-annotation.type (:foreground green)) 158 | 159 | (swift-ts-face-punctuation.type (:inherit 'font-lock-punctuation-face)) 160 | (swift-ts-face-compiler (:inherit 'font-lock-builtin-face)) 161 | (swift-ts-face-constructor.call (:inherit 'font-lock-function-call-face)) 162 | 163 | (swift-ts-face-face-label (:foreground green)) 164 | (swift-ts-face-method.call (:inherit 'font-lock-function-call-face)) 165 | (swift-ts-face-method.name (:inherit 'font-lock-function-name-face)) 166 | (swift-ts-face-keyword.annotation (:foreground red :weight 'light :italic t)) 167 | (swift-ts-face-keyword.type (:inherit 'font-lock-type-face)) 168 | (swift-ts-face-variable.synthesized (:foreground cyan)) 169 | (swift-ts-face-property.declaration (:foreground cyan_d)) 170 | 171 | 172 | (eglot-inlay-hint-face (:foreground cyan :height 0.8)) 173 | (eglot-parameter-hint-face (:foreground orange_b :height 0.8)) 174 | (eglot-type-hint-face (:foreground gray6 :height 0.8 :weight 'light)) 175 | 176 | ;;; Rainbow-delimiters 177 | (rainbow-delimiters-mismatched-face (:foreground red)) 178 | (rainbow-delimiters-unmatched-face (:foreground orange)) 179 | (rainbow-delimiters-base-error-face (:foreground red)) 180 | (rainbow-delimiters-base-face (:foreground green_b)) 181 | 182 | (rainbow-delimiters-depth-1-face (:foreground red)) 183 | (rainbow-delimiters-depth-2-face (:foreground magent_d)) 184 | (rainbow-delimiters-depth-3-face (:foreground blue0)) 185 | (rainbow-delimiters-depth-4-face (:foreground cyan_d)) 186 | (rainbow-delimiters-depth-5-face (:foreground gray5)) 187 | (rainbow-delimiters-depth-6-face (:foreground blue1)) 188 | (rainbow-delimiters-depth-7-face (:foreground red_d)) 189 | (rainbow-delimiters-depth-8-face (:foreground orange)) 190 | (rainbow-delimiters-depth-9-face (:foreground blue0)) 191 | 192 | (punch-line-evil-normal-face (:foreground black0 :background orange_b :weight 'semi-bold)) 193 | (punch-line-evil-visual-face (:foreground black0 :background red :weight 'semi-bold)) 194 | (punch-line-evil-replace-face (:foreground black0 :background magenta :weight 'semi-bold)) 195 | (punch-line-evil-insert-face (:foreground black0 :background green_b :weight 'semi-bold)) 196 | (punch-line-project-face (:foreground gray6 :weight 'bold)) 197 | (punch-line-buffer-name-face (:foreground white3 :weight 'bold)) 198 | (punch-line-time-face (:foreground black0)) 199 | (punch-line-major-mode-face (:foreground gray5)) 200 | (punch-line-separator-face (:foreground gray0 :weight 'thin)) 201 | 202 | (term (:background black0 :foreground magenta)) 203 | (term-color-black (:background black0 :foreground black0)) 204 | (term-color-yellow (:background yellow :foreground yellow)) 205 | (term-color-blue (:background blue1 :foreground blue1)) 206 | (term-color-green (:background green :foreground green)) 207 | (term-color-red (:background red :foreground red)) 208 | 209 | (ansi-color-bright-cyan (:background cyan :foreground cyan)) 210 | (ansi-color-blue (:background blue0 :foreground blue0)) 211 | (ansi-color-bright-magenta (:background red :foreground red)) 212 | 213 | (evil-mc-region-face (:background cyan_d :foreground black0)) 214 | (evil-mc-cursor-default-face (:background blue0 :foreground black0)) 215 | (evil-mc-cursor-bar-face (:background black0 :foreground cyan_d)) 216 | (evil-mc-cursor-hbar-face (:background cyan_d :foreground cyan_d)) 217 | 218 | (lazy-highlight (:inherit 'info-index-match)) 219 | (evil-ex-lazy-highlight (:inherit 'lazy-highlight)) 220 | 221 | (highlight-symbol-face (:foreground yellow_d :weight 'bold :underline t)) 222 | 223 | (smerge-base (:background magenta)) 224 | (smerge-markers (:background black1 :foreground magenta)) 225 | 226 | (smerge-upper (:background black2)) 227 | (smerge-lower (:background black2)) 228 | (smerge-refined-change (:background blue1)) 229 | (smerge-refined-removed (:background orange :strike-through t)) 230 | (smerge-refined-added (:background green :foreground black0)) 231 | 232 | (elfeed-search-tag-face (:foreground blue1)) 233 | 234 | (git-gutter:added (:foreground green_b)) 235 | (git-gutter:deleted (:foreground red_b)) 236 | (git-gutter:modified (:foreground blue1)) 237 | 238 | (package-description (:foreground orange :weight 'light)) 239 | (org-code (:foreground cyan)) 240 | 241 | (semel-symbol-at-mouse (:background blue0)) 242 | (semel-free-variable (:inherit 'font-lock-variable-name-face)) 243 | (semel-condition (:foreground red_b)) 244 | (semel-throw-tag (:foreground yellow_b)) 245 | (semel-condition (:foreground red_b)) 246 | (semel-non-local-exit (:foreground blue1 :underline "red")) 247 | (semel-local-variable (:inherit 'font-lock-property-use-face)) 248 | (semel-binding-variable (:inherit 'font-lock-property-name-face)) 249 | 250 | (diff-hl-change (:foreground blue1)) 251 | (diff-hl-delete (:foreground red)) 252 | (diff-hl-insert (:foreground green)) 253 | 254 | (diff-hl-margin-change (:foreground blue1)) 255 | (diff-hl-margin-delete (:foreground red)) 256 | (diff-hl-margin-insert (:foreground green)) 257 | 258 | 259 | (periphery-fix-face-full (:foreground gray1 :background magent_b :bold t)) 260 | (periphery-note-face-full (:foreground green_b :bold t)) 261 | (periphery-mark-face-full (:foreground gray6 :bold t)) 262 | (periphery-todo-face-full (:foreground blue2 :bold t)) 263 | (periphery-hack-face-full (:foreground red_b :background red_b :bold t)) 264 | (periphery-performance-face-full (:foreground gray1 :background magent_b :bold t)) 265 | (periphery-warning-face-full (:foreground orange_b :background nil :bold t)) 266 | (periphery-error-face-full (:foreground red_b :bold t)) 267 | (periphery-error-face (:foreground red :bold t)) 268 | (periphery-identifier-face (:foreground gray6 :italic t :weight 'light)) 269 | 270 | )) 271 | 272 | ;;;###autoload 273 | (when load-file-name 274 | (add-to-list 'custom-theme-load-path 275 | (file-name-as-directory (file-name-directory load-file-name)))) 276 | 277 | (provide-theme 'nordic) 278 | ;;; nordic-theme.el ends here 279 | -------------------------------------------------------------------------------- /modules/mk-evil.el: -------------------------------------------------------------------------------- 1 | ;;; mk-evil.el --- Konfiguration för Evil mode -*- lexical-binding: t; -*- 2 | ;;; Commentary: 3 | ;; Workaround för saknad evil-mode-buffers variabel 4 | ;;; Code: 5 | 6 | (use-package no-littering 7 | :ensure t) 8 | 9 | (use-package undo-tree 10 | :init 11 | (setq undo-tree-enable-undo-in-region t 12 | undo-tree-auto-save-history t 13 | undo-tree-history-directory-alist 14 | `(("." . ,(no-littering-expand-var-file-name "undo-tree/")))) 15 | :config 16 | (global-undo-tree-mode)) 17 | 18 | (defvar evil-mode-buffers nil 19 | "Lista över buffertar där Evil mode är aktivt.") 20 | 21 | (use-package evil 22 | :defer 0.5 23 | :ensure t 24 | :custom 25 | (evil-want-Y-yank-to-eol t) 26 | :init 27 | (setq-default evil-symbol-word-search t) 28 | (setq evil-want-integration t 29 | evil-want-keybinding nil 30 | evil-undo-system 'undo-tree 31 | evil-want-fine-undo t 32 | evil-want-C-u-scroll t 33 | evil-want-minibuffer t 34 | evil-respect-visual-line-mode t 35 | evil-search-module 'evil-search 36 | evil-vsplit-window-right t 37 | evil-ex-search-persistent-highlight nil ;; Don't keep highlights after search 38 | evil-ex-search-case 'smart ;; Smart case sensitivity 39 | evil-ex-search-vim-style-regexp t 40 | evil-split-window-below t 41 | evil-kill-on-visual-paste nil 42 | evil-default-cursor t 43 | evil-echo-state nil 44 | evil-want-C-i-jump t) 45 | :config 46 | (setq evil-leader/in-all-states t) 47 | 48 | (evil-set-leader 'normal (kbd "SPC")) 49 | (evil-set-leader 'visual (kbd "SPC")) 50 | 51 | (evil-define-key 'normal 'global (kbd "SPC") 'execute-extended-command) 52 | (evil-define-key 'normal 'global (kbd " .") 'embark-act) 53 | (evil-define-key 'normal 'global (kbd " P") 'package-install) 54 | (evil-define-key 'normal 'global (kbd " S") 'consult-line-multi) 55 | (evil-define-key 'normal 'global (kbd " F") 'consult-line) 56 | 57 | (evil-define-key 'normal 'global (kbd " a a") 'android-emulator-start-logcat) 58 | (evil-define-key 'normal 'global (kbd " a q") 'android-emulator-quit-logcat) 59 | (evil-define-key 'normal 'global (kbd " a r") 'android-emulator-restart-logcat) 60 | (which-key-add-key-based-replacements " a" "Android") 61 | 62 | (evil-define-key 'normal 'global (kbd "TAB") '(lambda () (interactive) (switch-to-buffer nil))) 63 | (evil-define-key 'normal 'global (kbd "'") '(lambda () (interactive) (toggle-vterm))) 64 | 65 | ;; (evil-define-key 'normal 'global (kbd " a a") 'android-emulator-start-logcat) 66 | ;; (evil-define-key 'normal 'global (kbd " a q") 'android-emulator-quit-logcat) 67 | ;; (evil-define-key 'normal 'global (kbd " a r") 'android-emulator-restart-logcat) 68 | ;;; Buffers 69 | (evil-define-key 'normal 'global (kbd " b b") 'consult-buffer) 70 | (evil-define-key 'normal 'global (kbd " b x") 'bury-buffer) 71 | (evil-define-key 'normal 'global (kbd " b i") 'ibuffer) 72 | (evil-define-key 'normal 'global (kbd " b k") 'kill-current-buffer) 73 | (evil-define-key 'normal 'global (kbd " b p") 'project-list-buffers) 74 | (evil-define-key 'normal 'global (kbd " b m") '(lambda () (interactive) (switch-to-buffer "*Messages*"))) 75 | (evil-define-key 'normal 'global (kbd " b s") '(lambda () (interactive) (switch-to-buffer "*scratch*"))) 76 | (which-key-add-key-based-replacements " b" "Buffers") 77 | 78 | (evil-define-key 'normal 'global (kbd " c p") 'copilot-chat-transient) 79 | (evil-define-key 'normal 'global (kbd " c c") 'claude-code-ide-menu) 80 | ;; (evil-define-key 'normal 'global (kbd " c a") 'aidermacs-transient-menu) 81 | (evil-define-key 'normal 'global (kbd " c e") 'consult-compile-error) 82 | (evil-define-key 'normal 'global (kbd " c l") 'mk/compilation-get-errors) 83 | (evil-define-key 'normal 'global (kbd " c m") 'copilot-chat-insert-commit-message) 84 | (which-key-add-key-based-replacements " c" "Code") 85 | 86 | (evil-define-key 'normal 'global (kbd " e a") 'embark-act) 87 | (which-key-add-key-based-replacements " e" "Embark") 88 | 89 | (evil-define-key 'normal 'global (kbd " f b") 'consult-buffer) 90 | (evil-define-key 'normal 'global (kbd " f d") 'delete-file) 91 | (evil-define-key 'normal 'global (kbd " f e") '(lambda () (interactive) (find-file user-init-file))) 92 | (evil-define-key 'normal 'global (kbd " f f") 'find-file) 93 | (evil-define-key 'normal 'global (kbd " f o") 'consult-find) 94 | (evil-define-key 'normal 'global (kbd " f l") 'consult-focus-lines) 95 | (evil-define-key 'normal 'global (kbd " f n") 'create-file-buffer) 96 | (evil-define-key 'normal 'global (kbd " f r") 'consult-recent-file) 97 | (evil-define-key 'normal 'global (kbd " f m") 'focus-mode) 98 | (evil-define-key 'normal 'global (kbd " f s") 'save-buffer) 99 | (evil-define-key 'normal 'global (kbd " f i") 'consult-imenu-multi) 100 | (which-key-add-key-based-replacements " f" "File") 101 | 102 | (evil-define-key 'normal 'global (kbd " h s") 'highlight-symbol-at-point) 103 | (evil-define-key 'normal 'global (kbd " h r") 'highlight-symbol-remove-all) 104 | (evil-define-key 'normal 'global (kbd " h n") 'highlight-symbol-next) 105 | (evil-define-key 'normal 'global (kbd " h N") 'highlight-symbol-prev) 106 | (which-key-add-key-based-replacements " h" "Highlight") 107 | 108 | (evil-define-key 'normal 'global (kbd " j j") 'jira-issues) 109 | (evil-define-key 'normal 'global (kbd " j m") 'jira-issues-menu) 110 | (evil-define-key 'normal 'global (kbd " j a") 'jira-issues-actions-menu) 111 | (which-key-add-key-based-replacements " j" "Jira") 112 | 113 | (evil-define-key 'normal 'global (kbd " m l") 'imenu-list-smart-toggle) 114 | (evil-define-key 'normal 'global (kbd " m i") 'consult-imenu) 115 | (evil-define-key 'normal 'global (kbd " m b") 'consult-bookmark) 116 | (evil-define-key 'normal 'global (kbd " m c") 'consult-mode-command) 117 | (which-key-add-key-based-replacements " m" "Misc") 118 | 119 | (evil-define-key 'normal 'global (kbd " g g") 'google-this) 120 | 121 | ;; Eval 122 | (evil-define-key 'normal 'global (kbd " e b") 'eval-buffer) 123 | (evil-define-key 'normal 'global (kbd " e l") 'eval-last-sexp) 124 | 125 | (evil-define-key 'normal 'global (kbd " s s") 'isearch-forward) 126 | (evil-define-key 'normal 'global (kbd " s l") 'isearch-consult-line) 127 | (evil-define-key 'normal 'global (kbd " s h") 'consult-isearch-history) 128 | (evil-define-key 'normal 'global (kbd " s o") 'occur) 129 | 130 | (evil-define-key 'normal 'global (kbd " t s") 'sort-lines) 131 | (evil-define-key 'normal 'global (kbd " t x") 'delete-trailing-whitespace) 132 | (evil-define-key 'normal 'global (kbd " t w") '(lambda () (interactive) (whitespace-mode 'toggle))) 133 | 134 | (evil-define-key 'normal 'global (kbd " p f") 'consult-ripgrep) 135 | (evil-define-key 'normal 'global (kbd " p d") 'project-dired) 136 | (evil-define-key 'normal 'global (kbd " p g") 'project-find-regexp) 137 | (evil-define-key 'normal 'global (kbd " p s") 'project-switch-project) 138 | (evil-define-key 'normal 'global (kbd " p k") 'project-kill-buffers) 139 | (evil-define-key 'normal 'global (kbd " p b") 'consult-project-buffer) 140 | 141 | 142 | (evil-define-key 'normal 'global (kbd " v s") 'magit-status) 143 | (evil-define-key 'normal 'global (kbd " v b") 'magit-diff-buffer-file) 144 | (evil-define-key 'normal 'global (kbd " v a") 'vc-annotate) 145 | (evil-define-key 'normal 'global (kbd " v l") 'magit-log-buffer-file) 146 | (evil-define-key 'normal 'global (kbd " v t") 'git-timemachine-toggle) 147 | 148 | (evil-define-key 'normal 'global (kbd " w w") 'weather-scout-show-forecast) 149 | 150 | (evil-define-key 'normal 'global (kbd " w t") 'window-transpose-layout) 151 | (evil-define-key 'normal 'global (kbd " w r") 'window-layout-rotate-clockwise) 152 | (evil-define-key 'normal 'global (kbd " w R") 'window-layout-rotate-anticlockwise) 153 | (evil-define-key 'normal 'global (kbd " w f") 'window-layout-flip-topdown) 154 | (evil-define-key 'normal 'global (kbd " w F") 'window-layout-flip-leftright) 155 | 156 | (evil-define-key 'normal 'global (kbd " q r") 'restart-emacs) 157 | (evil-define-key 'normal 'global (kbd " q q") 'save-buffers-kill-terminal) 158 | 159 | (evil-select-search-module 'evil-search-module 'isearch) 160 | (define-key evil-motion-state-map (kbd "") 'ignore) 161 | (define-key evil-motion-state-map (kbd "") 'ignore) 162 | (define-key evil-motion-state-map (kbd "") 'ignore) 163 | (define-key evil-motion-state-map (kbd "") 'ignore) 164 | 165 | (define-key evil-motion-state-map (kbd "C-+") #'(lambda () (interactive) (enlarge-window-horizontally 10))) 166 | (define-key evil-motion-state-map (kbd "C--") #'(lambda () (interactive) (shrink-window-horizontally 10))) 167 | (define-key evil-motion-state-map (kbd "C-M-+") #'(lambda () (interactive) (enlarge-window 3))) 168 | (define-key evil-motion-state-map (kbd "C-M--") #'(lambda () (interactive) (shrink-window 3))) 169 | 170 | (setq evil-normal-state-cursor '(box "DodgerBlue") 171 | evil-insert-state-cursor '(bar "DeepPink") 172 | evil-visual-state-cursor '(hollow "orchid")) 173 | ;; (evil-set-initial-state 'minibuffer-mode 'emacs) 174 | 175 | ;; (evil-define-key 'normal evil-ex-map "q" 'mk/safe-kill-buffer-and-window) 176 | (evil-mode 1)) 177 | 178 | (with-eval-after-load 'evil 179 | (dolist (state '(normal insert visual motion emacs)) 180 | (evil-define-key state 'global (kbd "s-M") nil) 181 | (evil-define-key state 'global (kbd "C-.") nil) 182 | (evil-define-key state 'global (kbd "C-k") nil))) 183 | 184 | (use-package evil-collection 185 | :after evil 186 | :demand t 187 | :config 188 | (evil-collection-init)) 189 | 190 | ;; (use-package evil-mc 191 | ;; :hook (evil-mode . global-evil-mc-mode) 192 | ;; :bind ( 193 | ;; ("C-M-e" . evil-mc-make-all-cursors) 194 | ;; ("C-M-n" . evil-mc-make-and-goto-next-match) 195 | ;; ("C-M-s" . evil-mc-skip-and-goto-next-match) 196 | ;; ("C-M-p" . evil-mc-make-and-goto-prev-match) 197 | ;; ("C-M-j" . evil-mc-make-cursor-move-next-line) 198 | ;; ("C-M-k" . evil-mc-make-cursor-move-prev-line)) 199 | ;; :custom 200 | ;; (evil-mc-mode-line-text-inverse-colors t) 201 | ;; (evil-mc-undo-cursors-on-keyboard-quit t) 202 | ;; (evil-mc-mode-line-text-cursor-color t) 203 | ;; :config 204 | ;; (evil-define-key 'visual evil-mc-key-map 205 | ;; "A" #'evil-mc-make-cursor-in-visual-selection-end 206 | ;; "I" #'evil-mc-make-cursor-in-visual-selection-beg)) 207 | 208 | (use-package evil-matchit 209 | :after evil-collection 210 | :config 211 | (global-evil-matchit-mode 1)) 212 | 213 | ;; (use-package evil-surround 214 | ;; :after evil 215 | ;; :commands global-evil-surround-mode 216 | ;; :custom 217 | ;; (evil-surround-pairs-alist 218 | ;; '((?\( . ("(" . ")")) 219 | ;; (?\[ . ("[" . "]")) 220 | ;; (?\{ . ("{" . "}")) 221 | 222 | ;; (?\) . ("(" . ")")) 223 | ;; (?\] . ("[" . "]")) 224 | ;; (?\} . ("{" . "}")) 225 | 226 | ;; (?< . ("<" . ">")) 227 | ;; (?> . ("<" . ">")))) 228 | ;; :hook (after-init . global-evil-surround-mode)) 229 | 230 | (use-package evil-commentary 231 | :ensure t 232 | :after (evil prog-mode) 233 | :init 234 | (evil-commentary-mode 1)) 235 | 236 | ;; (use-package evil-visualstar 237 | ;; :ensure t 238 | ;; :after evil 239 | ;; :hook (after-init . global-evil-visualstar-mode)) 240 | 241 | (use-package evil-snipe 242 | :ensure t 243 | :after evil 244 | :config 245 | (evil-snipe-mode +1) 246 | (evil-snipe-override-mode +1)) 247 | 248 | (use-package undo-fu 249 | :ensure t 250 | :defer t 251 | :custom 252 | (setopt undo-limit (* 13 160000)) 253 | (setopt undo-outer-limit (* 13 24000000)) 254 | (setopt undo-strong-limit (* 13 240000)) 255 | :config 256 | (setq undo-fu-allow-undo-in-region t)) 257 | 258 | (use-package undo-fu-session 259 | :hook (after-init . undo-fu-session-global-mode) 260 | :config 261 | (setq undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'") 262 | undo-fu-session-file-limit 10)) 263 | 264 | ;; (use-package hardtime 265 | ;; :ensure nil 266 | ;; :after evil 267 | ;; :config 268 | ;; (global-hardtime-mode 1)) 269 | 270 | (use-package pulsar 271 | :hook (after-init . pulsar-global-mode) 272 | :config 273 | (setq pulsar-pulse t 274 | pulsar-delay 0.035 275 | pulsar-iterations 12 276 | pulsar-face 'pulsar-cyan 277 | pulsar-highlight-face 'evil-ex-lazy-highlight 278 | pulsar-pulse-functions '( 279 | evil-yank 280 | evil-yank-line 281 | evil-delete 282 | evil-delete-line 283 | evil-jump-item 284 | evil-scroll-down 285 | evil-scroll-up 286 | evil-scroll-page-down 287 | evil-scroll-page-up 288 | evil-scroll-line-down 289 | evil-scroll-line-up 290 | evil-window-up 291 | evil-window-rotate-upwards 292 | evil-window-rotate-downwards 293 | evil-window-down 294 | evil-window-left 295 | evil-window-right 296 | evil-window-vsplit 297 | evil-window-split))) 298 | 299 | ;; (defun my/recenter-after-jump (&rest _) 300 | ;; "Centrera fönstret efter hoppkommandon i Evil." 301 | ;; (recenter)) 302 | 303 | ;; (dolist (fn '(evil-jump-backward 304 | ;; evil-jump-forward 305 | ;; evil-forward-section-begin 306 | ;; evil-backward-section-begin 307 | ;; evil-forward-sentence-begin 308 | ;; evil-backward-sentence-begin 309 | ;; evil-goto-definition)) 310 | ;; (advice-add fn :after #'my/recenter-after-jump)) 311 | 312 | ;;; Provide 313 | (provide 'mk-evil) 314 | ;;; mk-evil.el ends here. 315 | --------------------------------------------------------------------------------