Integrating `coqidetop` inside Kakoune

Overview

This plugin aims at providing a functional and usable coqidetop wrapper for use with Kakoune.

demo screenshot

For a list of things left to do, see the end of this README.


P.S.: coqoune is the same kind of project, and was started way before this one. However, in my experience, Coqoune has been a bit buggy at some times (for example crashing on Coq errors), and the overall integration with highlighters doesn't work that well. I wanted to maintain a fork on my own, but most of the extension is written in some weird non-POSIX shell, which I'm not that familiar with at all.

I chose to write the “backend” in Rust, mainly to discover, and because I felt like it was more suited for this than Haskell.

Dependencies

  • coqidetop (should come with a Coq installation by default)
  • socat
  • Python 3.8+

Installation

The recommended way to install this plugin is through plug.kak:

plug "mesabloo/coqide.kak" do %{
  cargo build --release --locked
  cargo install --force --path . --root ~/.local
} config %{
  # configure this plugin here
}

Public API

  • coqide-start starts the daemon in the current buffer. Note that multiple daemons defined in multiple buffers account for multiple sessions. The state is also bufferized, meaning that you cannot control one daemon from another buffer than the one it was started for.
  • coqide-stop stops the daemon started in the current buffer.
  • coqide-dump-log starts a new buffer with the logs until this point. It is not automatically refreshed when new logs appear. In order to do this, you need to close the log buffer with delete-buffer! and relaunch coqide-dump-log.
  • coqide-next identifies and processes the next Coq statement.
  • coqide-previous removes the last processed Coq statement from the processed state.
  • coqide-query prompts for a query to send directly to the coqidetop process and sends it without affecting the current state.
  • coqide-move-to tries to process Coq statements until the main cursor.

Additional functionality:

  • This plugin will aso automatically backtrack to the cursor when an insertion is detected before the end of the processed range.

Documentation

This plugin comes with several default options, but some of them can be altered:

  • coqide_command is the command used to launch the daemon (which is written in Rust). Sometimes, the executable is not in your PATH, so you may want to customize this option using set-option global coqide_command "<path to coqide-daemon>". The default value is coqide-daemon therefore assumes it is in your PATH.
  • Colors:
    • coqide_processed is the face used to highlight Coq code which has already been processed by the daemon. This can be customized as wanted using set-face, but comes with the default value default,black.
    • coqide_keyword is the face used to color keywords in both goal and result buffers. It defauls to the same face used to color keywords.
    • coqide_evar is used to highlight specific variables in the goal and result buffers. Defaults to variable when not specified.
    • coqide_type is the face which colors types in the goal and results buffers. Defaults to the face type if unchanged.
    • coqide_notation colors operators in both goal and result buffers. Defaults to operator if left unspecified.
    • coqide_variable is used to highlight variable names in the goal and result buffers. Defaults to variable if unchanged.
    • coqide_reference ??? Defaults to variable because I'm quite unsure what this is used for.
    • coqide_path ??? Defaults to module for some reason.

Things left to do and known bugs

The codebase is at some locations pretty ugly (e.g. when decoding XML nodes to Rust values). However, most of it should be at last a little bit documented.

Here are some erroneous or incomplete features:

  • Trying to go past an error multiple times will make state IDs inconsistent therefore leading to a coqidetop error.

  • Sending two next commands simultaneously (the second needs to be sent before the first one is processed) creates inconsistent state IDs. A workaround is simply to go back 2-3 states and retry processing.

    This might be easily fixable by locking everything after sending a call until a Processed response is received.

  • The “parser” used to detect the next statement does not take in account qualified identifiers.

  • ... and some other things that I did not see.

If you feel like it, feel free to improve this plugin by forking this repository and submitting your patches through pull requests. Just try not to implement many features in the same pull request.

Personal configuration

As I intend to use this plugin, here is how I configured it. It spawns two new kakoune clients containing the result and goal buffers and deletes them when they get discarded.

plug "coqide.kak" do %{
  cargo build --release --locked
  cargo install --force --path . --root ~/.local
} config %{
  declare-option -hidden str coqide_close_panels

  declare-user-mode coq
  map global coq c ": enter-user-mode -lock coq<ret>" \
    -docstring "stay in the Coq user mode"
  map global coq k ": coqide-previous<ret>" \
    -docstring "unprove the last statement"
  map global coq j ": coqide-next<ret>" \
    -docstring "prove the next statement"
  map global coq <ret> ": coqide-move-to<ret>" \
    -docstring "move tip to main cursor"
  map global coq l ": coqide-dump-log<ret>" \
    -docstring "dump logs"
  map global coq q ": coqide-query<ret>" \
    -docstring "send a query to coqtop"

  # Create two additional clients to show goals and results
  hook global BufCreate \*coqide-(.*)-(goal|result)\* %{
    evaluate-commands %sh{
      client_name="coq-${kak_hook_param_capture_1}-${kak_hook_param_capture_2}"
      regex_safe="$(sed 's/\*/\\*/g' <<< "$kak_hook_param_capture_0")"

      switch_to_buffer="
        buffer $kak_hook_param_capture_0
        rename-client $client_name

        try %{
          remove-highlighter buffer/line_numbers
          remove-highlighter buffer/matching
          remove-highlighter buffer/wrap_lines
          remove-highlighter buffer/show-whitespaces
        }
      "
      ${kak_opt_termcmd} "kak -c $kak_session -e '$switch_to_buffer'" &>/dev/null </dev/null &

      echo "hook -once global BufClose '$regex_safe' %{
        evaluate-commands -client '$client_name' 'quit!'
      }"
    }
  }


  hook global WinSetOption filetype=coq %{ 
    coqide-start

    # User mode to interact with CoqIDE only in Coq files
    map buffer user c ": enter-user-mode coq<ret>" \
      -docstring "enter the Coq user mode"

    # Better looking face
    set-face global coqide_processed default,black+id

    # Commands to execute when the buffer is closed.
    # These are declared here as a string in order to have the value of `%opt{coqide_pid}`
    # (which is an internal option)
    set-option buffer coqide_close_panels "
      evaluate-commands -client coq-%opt{coqide_pid}-goal 'quit!'
      evaluate-commands -client coq-%opt{coqide_pid}-result 'quit!'
      remove-hooks coqide-%opt{coqide_pid}
    "

    # Remove the side panels when closing the buffer
    hook global -group "coqide-%opt{coqide_pid}" BufClose "%val{buffile}" %{ try %opt{coqide_close_panels} }
    hook global -group "coqide-%opt{coqide_pid}" ClientClose .* %{ try %opt{coqide_close_panels} }
  }
}
You might also like...
Helix - A kakoune / neovim inspired editor, written in Rust
Helix - A kakoune / neovim inspired editor, written in Rust

A kakoune / neovim inspired editor, written in Rust. The editing model is very heavily based on kakoune; during development I found myself agree

tree-sitter meets Kakoune

kak-tree-sitter This is a binary server that interfaces tree-sitter with kakoune. Features Install Usage Design Credits Features Semantic highlighting

tree-sitter server for kakoune

tree-sitter.kak Warning This currently just a proof-of-concept, and isn't stable yet. A Tree-sitter server that keeps parsed ASTs in memory. This is u

A simple hinting Rust binary to be used in the Kakoune editor
A simple hinting Rust binary to be used in the Kakoune editor

Hop: hinting brought to Kakoune selections Table of content: Install Configuration Kakoune options hop-kak options Usage Workflow examples Default key

 rusty-donut - ASCII raymarching inside a terminal
rusty-donut - ASCII raymarching inside a terminal

ASCII raymarching inside a terminal

Detect if code is running inside a virtual machine (x86 and x86-64 only).

inside-vm Detect if code is running inside a virtual machine. Only works on x86 and x86-64. How does it work Measure average cpu cycles when calling c

A template to build smart contracts in Rust to run inside a Cosmos SDK module on all chains that enable it.

CosmWasm Starter Pack This is a template to build smart contracts in Rust to run inside a Cosmos SDK module on all chains that enable it. To understan

Smart Contract built in Rust to run inside Cosmos SDK module on all chains that enable it

CoinSwap is a Smart Contract that is built on the terra blockchain and can be used to swap cryptocurrencies such as LUNA, UST, TerraUSD, Anchor, Mirror Protocol, LUNI and other CW20 tokens. The Project also contains a smart contract which works as a analysis tool for the gas fees on the Terra Blockchain.

Works out if this is running from inside a shell, and if so, which one.

pshell pshell answers the question "Is my application running in a shell, and if so, which one". Example: you are installing something and want to mak

L2 validity rollup combined with blind signatures over elliptic curves inside zkSNARK, to provide offchain anonymous voting with onchain binding execution on Ethereum

blind-ovote Blind-OVOTE is a L2 voting solution which combines the validity rollup ideas with blind signatures over elliptic curves inside zkSNARK, to

Check if the process is running inside Windows Subsystem for Linux (Bash on Windows)

is-wsl Check if the process is running inside Windows Subsystem for Linux (Bash on Windows) Inspired by sindresorhus/is-wsl and made for Rust lang. Ca

Shared execution environment for constructing 3D virtual spaces from the inside.

Hearth Hearth is a shared, always-on execution environment for constructing 3D virtual spaces from the inside. Come join our Discord server! The Histo

An implementation of the classic arcade game Whac-A-Hole inside Discord, made in 12 hours, with no experience in Rust.

Whac-A-Hole A blazingly fast implementation of the classic arcade game What-A-Hole inside Discord, made in 12 hours, with no experience in Rust ( 🚀 ?

A simple extension for `bevy-editor-pls` to support tilemap editing right inside the bevy app.

What is this This is a simple tilemap editor plugin, that hooks right into bevy_editor_pls to work with bevy_ecs_tilemap. It works completely within i

A tool to format codeblocks inside markdown and org documents.
A tool to format codeblocks inside markdown and org documents.

cbfmt (codeblock format) A tool to format codeblocks inside markdown, org, and restructuredtext documents. It iterates over all codeblocks, and format

A tool for bulk downloading and exporting the account data inside Solana snapshots.

Memento Memento is a tool used to load and save accounts from old Solana snapshots in Google Cloud Storage. Why should I use Memento? No fighting sola

Calling Quantlib C++ functionalities inside Rust using CxxBridge.

Quantlib on Rust An example of calling Quantlib C++ functionalities inside Rust using CxxBridge. Usage Clone the repository with --recurse-submodules:

Show HTML content
Show HTML content "inside" your egui rendered application

hframe Show HTML content "inside" your egui rendered application. "hframe" stands for "HTML Frame". Note: hframe only works when the application is co

Owner
Mesabloo
Shameless self-promo: https://github.com/zilch-lang
Mesabloo
tree-sitter server for kakoune

tree-sitter.kak Warning This currently just a proof-of-concept, and isn't stable yet. A Tree-sitter server that keeps parsed ASTs in memory. This is u

Enrico Borba 8 May 4, 2023
Detect if code is running inside a virtual machine (x86 and x86-64 only).

inside-vm Detect if code is running inside a virtual machine. Only works on x86 and x86-64. How does it work Measure average cpu cycles when calling c

null 34 Oct 3, 2022
Calling Quantlib C++ functionalities inside Rust using CxxBridge.

Quantlib on Rust An example of calling Quantlib C++ functionalities inside Rust using CxxBridge. Usage Clone the repository with --recurse-submodules:

Marco Inacio 3 Feb 21, 2024
A prototype project integrating jni rust into Kotlin and using protobuf to make them work together

KotlinRustProto a prototype project integrating jni rust into Kotlin and using protobuf to make them work together How to start add a RPC call in Droi

woo 11 Sep 5, 2022
Client for integrating private analytics in fast and reliable libraries and apps using Rust and WebAssembly

TelemetryDeck Client Client for integrating private analytics in fast and reliable libraries and apps using Rust and WebAssembly The library provides

Konstantin 2 Apr 20, 2022
Utilities for integrating Datadog with opentelemetry + tracing in rust

Non-official datadog tracing and log correlation for Rust services. This crate contains the necessary glue to bridge the gap between OpenTelemetry, tr

willbank 5 Oct 31, 2023
Putting a brain behind `cat`🐈‍⬛ Integrating language models in the Unix commands ecosystem through text streams.

smartcat (sc) Puts a brain behind cat! CLI interface to bring language models in the Unix ecosystem and allow power users to make the most out of llms

Emilien Fugier 28 Dec 2, 2023
Rust library for integrating local LLMs (with llama.cpp) and external LLM APIs.

Table of Contents About The Project Getting Started Roadmap Contributing License Contact A rust interface for the OpenAI API and Llama.cpp ./server AP

Shelby Jenkins 4 Dec 18, 2023
Kakoune Language Server Protocol Client

Kakoune Language Server Protocol Client kak-lsp is a Language Server Protocol client for Kakoune implemented in Rust. Installation Note kak-lsp.toml d

null 495 Dec 17, 2022
Thin wrapper around starship.rs to format kakoune status line

kakship is just a thin wrapper around starship to format the status line of kakoune and is meant to be used with the included kakoune script kakship.kak.

Eric Burghard 15 Jun 7, 2022