9Port/Acme with LSP
Overview
Acme is an excellent editor. If you have to edit a complex C++ code base, using acme-lsp with ccls results in a big productivity boost. In this post I describe my Acme setup on Darwin with a focus on acme-lsp and ccls.
ACME LSP
To install acme-lsp
and acmefocused
please follow these instructions:
GO111MODULE=on go get github.com/fhs/acme-lsp/cmd/acme-lsp@latest
GO111MODULE=on go get github.com/fhs/acme-lsp/cmd/L@latest
GO111MODULE=on go get github.com/fhs/acme-lsp/cmd/acmefocused@latest
Follow the Hints and Tips outlined at the acme-lsp page to scripts like Ldef
, Lrefs
, Ltype
, etc., so that you can easily execute those commands with a single middle click.
ACMEFOCUSED with SKHD
While one can create scripts to be executed via a middle click, I prefer to use keyboard short-cuts for common tasks like auto completion, show definitions/references, etc. via skhd.
skhd is a hotkey daemon for macOS that focuses on responsiveness and performance. Hotkeys are defined in a text file through a simple DSL. skhd is able to hotload its configuration file, meaning that hotkeys can be edited and updated live while skhd is running.
; tail -n12 .config/skhd/skhdrc
# acme-lsp: complete
shift + cmd - f [
"acme" : L comp -e | 9p write acme/`{dial unix!`{namespace}/acmefocused}/errors
]
# acme-lsp: refs
shift + cmd - r [
"acme" : L refs | 9p write acme/`{dial unix!`{namespace}/acmefocused}/errors
]
# acme-lsp: defs
shift + cmd - d [
"acme" : L def | 9p write acme/`{dial unix!`{namespace}/acmefocused}/errors
]
Start ACME LSP via Launchd
Using launchd
to fire up acme-lsp
is what I decided is best for my use case.
Create a 9lab.org.acme-lsp.plist
file with the following contents:
; touch $HOME/Library/LaunchAgents/9lab.org.acme-lsp.plist
; E $HOME/Library/LaunchAgents/9lab.org.acme-lsp.plist
Replace $HOME
with the path to your home folder:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>9lab.org.acme-lsp</string>
<key>ProgramArguments</key>
<array>
<string>$HOME/bin/acme-lsp</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PLAN9</key>
<string>/usr/local/plan9</string>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/plan9/bin:$HOME/bin</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/usr/local/var/log/9lab/acme-lsp.out.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/9lab/acme-lsp.err.log</string>
</dict>
</plist>
Start ACME Focused via Launchd
Create a 9lab.org.acmefocused.plist
file with the following contents:
; touch $HOME/Library/LaunchAgents/9lab.org.acmefocused.plist
; E $HOME/Library/LaunchAgents/9lab.org.acmefocused.plist
Replace $HOME
with the path to your home folder:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<keyacmefocused>Label</key>
<string>9lab.org.acmefocused</string>
<key>ProgramArguments</key>
<array>
<string>$HOME/bin/acmefocused</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>PLAN9</key>
<string>/usr/local/plan9</string>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/plan9/bin</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/usr/local/var/log/9lab/acmefocused.out.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/9lab/acmefocused.err.log</string>
</dict>
</plist>
Launchd Helper Script
The following rc
helper script eases restart of acme-lsp
and acmefocused
:
; E $HOME/bin/lsp
; cat $HOME/bin/lsp
#!/usr/local/plan9/bin/rc
fn Help {
echo `{basename $0}^' [list|stop|start|restart|logclear]'
}
fn List {
launchctl list | grep '9lab.org.acme'
}
fn PropertyLists {
launchctl dumpstate | grep 'path = .*9lab.org.acme.*.plist$' | ssam 's/^.* = //g'
}
fn Restart {
for(p in `{PropertyLists}) {
launchctl unload -w $p
launchctl load -w $p
}
}
fn Stop {
for(p in `{PropertyLists}) {
launchctl unload -w $p
}
}
fn Start {
for(p in `{PropertyLists}) {
launchctl load -w $p
}
}
fn LogClear {
for(p in `{PropertyLists}) {
# Extract log files from .plist launch agent definition:
#
# <key>StandardOutPath</key>
# <string>/usr/local/var/log/9lab/acmefocused.out.log</string>
# <key>StandardErrorPath</key>
# <string>/usr/local/var/log/9lab/acmefocused.err.log</string>
#
logs=`{cat $p | grep '\.log' | awk -F '[<|>]' '{print $3}'}
for(l in $logs) {
echo 'Truncating log file ">'^$l^'"'
>$l
}
}
}
# -----------------------------------------------------------------
switch ($#*) {
case 0
Help
case *
switch ($1) {
case list
List
case start
Start
case stop
Stop
case restart
Restart
case logclear
LogClear
case *
Help
}
}
Now one can easily restart and list the status of acmefocused
and acme-lsp
:
; lsp restart
$HOME/Library/LaunchAgents/9lab.org.acmefocused.plist: Operation now in progress
$HOME/Library/LaunchAgents/9lab.org.acme-lsp.plist: Operation now in progress
; lsp list
3850 0 9lab.org.acme-lsp
3847 0 9lab.org.acmefocused
ACME LSP: C++ via CCLS
Build CCLS
Download pre-built LLVM binaries for Darwin using curl:
; cd $HOME
; mkdir -p lib/llvm
; cd lib/llvm
; curl https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-apple-darwin.tar.xz --silent --location --output clang+llvm-10.0.1-x86_64-apple-darwin.tar.xz
; open clang+llvm-10.0.1-x86_64-apple-darwin.tar.xz
Get get dependencies via Homebrew:
; brew install rapidjson
; mkdir -p $HOME/src/priv/git
; cd $HOME/src/priv/git
; git clone https://github.com/1g0rb0hm/ccls
; cd ccls
; git remote add upstream https://github.com/MaskRay/ccls
Build fork of ccls:
; cd $HOME/src/priv/git/ccls
; cmake -H. -BRelease -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$home/lib/llvm/clang+llvm-10.0.1-x86_64-apple-darwin/lib/cmake
; cmake --build Release
Add ccls to PATH
:
; cd $HOME/bin
; ln -s $HOME/src/priv/git/ccls/Release/ccls
Configure ACME LSP
Determine ACME LSP
configuration file location and edit it:
; acme-lsp -showconfig | head -1 | cut -f 2 -d : -
$HOME/Library/Application Support/acme-lsp/config.toml
; E '$HOME/Library/Application Support/acme-lsp/config.toml'
A configuration that works with Xcode
or CommandLineTools
depending on your needs (NOTE
ensure to set th path to your project workspace and replace $HOME
with the full path to your home folder):
HideDiagnostics = true
RPCTrace = false
WorkspaceDirectories = [
"$HOME/src/YOUR_C++_PROJECT"
]
[Servers]
[Servers.ccls]
Command = [
"ccls",
# "-log-file=/Users/igor/Library/Logs/ccls.log",
# "-v=4",
# clang.extraArgs from 'clang -v -fsyntax-only -x c++ /dev/null'
# clang.resourceDir from 'clang -print-resource-dir'
#
# -- Xcode
# ; sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
"--init={\"cache\":{\"directory\":\"$HOME/Library/Caches/ccls\"},\"highlight\":{\"enabled\":true},\"clang\":{\"extraArgs\":[\"-isystem\",\"/usr/local/include\",\"-isystem\",\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1\",\"-isystem\",\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include\",\"-isystem\",\"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include\",\"-isystem\",\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include\",\"-isystem\",\"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks\"],\"resourceDir\":\"$HOME/lib/llvm/clang+llvm-10.0.1-x86_64-apple-darwin\"},\"completion\":{\"detailedLabel\":false}}"
# -- CommandLineTools
# ; sudo xcode-select -s /Library/Developer/CommandLineTools
# "--init={\"cache\":{\"directory\":\"$HOME/Library/Caches/ccls\"},\"highlight\":{\"enabled\":true},\"clang\":{\"extraArgs\":[\"-isystem\",\"/usr/local/include\",\"-isystem\",\"/Library/Developer/CommandLineTools/usr/include/c++/v1\",\"-isystem\",\"/Library/Developer/CommandLineTools/usr/lib/clang/11.0.3/include\",\"-isystem\",\"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include\",\"-isystem\",\"/Library/Developer/CommandLineTools/usr/include\",\"-isystem\",\"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks\"],\"resourceDir\":\"$HOME/lib/llvm/clang+llvm-10.0.1-x86_64-apple-darwin\"},\"completion\":{\"detailedLabel\":false}}"
]
StderrFile = "ccls.stderr.log"
LogFile = "ccls.log"
[[FilenameHandlers]]
Pattern = '(\.h)|(\.c)|(\.cpp)|(\.cc)|(\.def)$'
ServerKey = "ccls"