Skip to content

Commit

Permalink
Merge pull request #6 from nberth/superbol-mode
Browse files Browse the repository at this point in the history
Draft version of basic superbol-mode for GNU/Emacs
  • Loading branch information
nberth authored Sep 25, 2023
2 parents f4d5b99 + 1206449 commit 0a05abe
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 26 deletions.
6 changes: 3 additions & 3 deletions .drom
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version:0.9.0

# hash of toml configuration files
# used for generation of all files
ce91e02d93482e19b68ff8b123bea8a3:.
8288a3cd2b32b2fada49d59ebfc4d900:.
# end context for .

# begin context for .github/workflows/workflow.yml
Expand All @@ -15,7 +15,7 @@ fc10b0887fb072e04e5bcbdd5a0c6668:.github/workflows/workflow.yml

# begin context for .gitignore
# file .gitignore
90b1808274a081597c6ff82400928561:.gitignore
0727863b8e681aec0cc8d969f8cfb747:.gitignore
# end context for .gitignore

# begin context for CHANGES.md
Expand All @@ -30,7 +30,7 @@ d00f73c835ae4a1589d55ebda4ab381b:CHANGES.md

# begin context for Makefile
# file Makefile
86f0208a874473207a92c1e552fa9cb5:Makefile
8c1798510e3d14cdfd80b0ebd931773b:Makefile
# end context for Makefile

# begin context for README.md
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ ATTIC
!.vscode/launch.json
*.vsix
*.opam.locked
/emacs/lsp-superbol-customs.el


16 changes: 16 additions & 0 deletions Makefile.header
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# -*- Makefile -*-
PROJECT=superbol_vscode_platform
SRCDIR=src/vscode/superbol-vscode-platform

# Emacs lsp-mode source directory (https://github.com/emacs-lsp/lsp-mode):
# (could be a submodule)
LSP_MODE_SRCDIR ?= ../lsp-mode

.PHONY: compile
compile: build
cp -f _build/default/src/vscode/vscode-package-json/main.exe vscode-package-json
Expand Down Expand Up @@ -33,3 +38,14 @@ opam-cross:
drom dep --cross osx
drom dep --cross windows

# emacs-lsp:
emacs/lsp-superbol-customs.el: $(LSP_MODE_SRCDIR) package.json
emacs --batch > "$@" \
--load "$(LSP_MODE_SRCDIR)/scripts/lsp-generate-settings.el" \
--eval "(dolist (l (lsp-generate-settings \"package.json\")) (print l))" \
&& echo "Generated $@" 1>&2 \
|| rm -f "$@"

# 8.0.1
# --eval "(princ (lsp-generate-settings \"package.json\" 'lsp-superbol))" \
# --eval '(princ "\n")' \
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# Superbol VSCode Platform for COBOL
# Superbol Studio OSS: A New Platform for COBOL

## Features

* LSP (superbol) with following capabilities:
* LSP (`superbol-free`) with following capabilities:
* Syntax diagnostics
* Go to definitions
* Find references
* Peek on copybook (Superbol PR #211)
* Semantic highlighting (Superbol PR #212)
* Peek on copybook and source text replacements
* Semantic highlighting
* File and range indentation

## Install
* VSCode extension

* GNU/Emacs mode

## VSCode Extension

### From binary and VSIX

Expand Down Expand Up @@ -65,6 +69,10 @@ In the `superbol` field past the path to the `superbol` executable.

You can check the documentation on using the extension on [this page](https://ocamlpro.github.io/superbol-vscode-platform/sphinx).

## GNU/Emacs mode

You can check the documentation on using the Superbol LSP with GNU/Emacs on [this page](https://ocamlpro.github.io/superbol-vscode-platform/sphinx/emacs.html).

## Resources

* Website: https://ocamlpro.github.io/superbol-vscode-platform
Expand Down
1 change: 1 addition & 0 deletions drom.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ ATTIC
!.vscode/launch.json
*.vsix
*.opam.locked
/emacs/lsp-superbol-customs.el
"""
github-workflow-before-build = """
Expand Down
42 changes: 42 additions & 0 deletions emacs/eglot-superbol.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
;;; lsp-superbol.el --- Eglot LSP client for Superbol COBOL -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2023 OCamlPro SAS
;;
;; All rights reserved.
;; This source code is licensed under the MIT license found in the
;; LICENSE.md file in the root directory of this source tree.

;;; Commentary:

;; Eglot LSP client for Superbol COBOL

;;; Code:

(unless (fboundp 'eglot)
(load "eglot-autoloads"))

(require 'eglot)
(require 'superbol-mode)

(defun eglot-superbol--start ()
"Superbol LSP startup function for Eglot"

;; Actually start the LSP server
(eglot-ensure)

;; Turn on fontification (even if minimal)
(funcall font-lock-fontify-buffer-function))

(add-to-list 'eglot-server-programs '(superbol-mode . ("superbol-free" "lsp")))
(add-to-list 'eglot-server-programs '(cobol-mode . ("superbol-free" "lsp")))

;; Autostart the LSP when entering superbol-mode
(add-hook 'superbol-mode-hook #'eglot-superbol--start)

;; Also load on cobol-mode
(with-eval-after-load 'cobol-mode
(add-hook 'cobol-mode-hook #'eglot-superbol--start))

(provide 'eglot-superbol)

;;; eglot-superbol.el ends here
82 changes: 82 additions & 0 deletions emacs/lsp-superbol.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
;;; lsp-superbol.el --- lsp-mode LSP client for Superbol COBOL -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2023 OCamlPro SAS
;;
;; All rights reserved.
;; This source code is licensed under the MIT license found in the
;; LICENSE.md file in the root directory of this source tree.

;;; Commentary:

;; lsp-mode.el LSP client for Superbol COBOL

;;; Code:

(unless (fboundp 'lsp-mode)
(load "lsp-mode-autoloads"))

(require 'lsp-mode)
(require 'superbol-mode)

;; ---

(defgroup lsp-superbol nil
"Settings for the Superbol Language Server for COBOL (lsp-mode)."
:group 'lsp-mode
:link '(url-link "https://github.com/OCamlPro/superbol-vscode-extension")
:package-version '(lsp-mode . "8.0.1"))

(load (expand-file-name "lsp-superbol-customs.el"
(file-name-directory load-file-name)))

;; ---

(defun lsp-superbol--server-command ()
"Startup command for the Superbol LSP language server."
;; (list (lsp-package-path 'superbol-language-server) "lsp"))
(list (expand-file-name "superbol-free" lsp-superbol-path) "lsp"))

;; (lsp-dependency 'superbol-language-server
;; `(:system ,(executable-find (lsp-package-path 'superbol-language-server))))
;; '(:system "superbol-language-server"))

(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection #'lsp-superbol--server-command)
:priority 0
:activation-fn (lsp-activate-on "superbol" "cobol" "COBOL")
:server-id 'superbol-ls
))

;; ---

;; (with-eval-after-load 'superbol-mode
(add-to-list 'lsp-language-id-configuration '(superbol-mode . "cobol"))
(add-to-list 'lsp-language-id-configuration '(cobol-mode . "cobol"))

(defun lsp-superbol--start ()
"Superbol LSP startup function for lsp-mode"

;; Enable semantic tokens
(set (make-local-variable 'lsp-semantic-tokens-enable) t)

;; Actually start the LSP server
(lsp)

;; Turn on fontification
(funcall font-lock-fontify-buffer-function))

;; Autostart the LSP when entering superbol-mode
(add-hook 'superbol-mode-hook #'lsp-superbol--start)

;; Also load on cobol-mode
(with-eval-after-load 'cobol-mode
(add-hook 'cobol-mode-hook #'lsp-superbol--start))

;; ---

(lsp-consistency-check lsp-superbol)

(provide 'lsp-superbol)

;;; lsp-superbol.el ends here
40 changes: 40 additions & 0 deletions emacs/superbol-mode.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
;;; superbol-mode.el --- Superbol COBOL major mode -*- lexical-binding: t; -*-
;;
;; Copyright (c) 2023 OCamlPro SAS
;;
;; All rights reserved.
;; This source code is licensed under the MIT license found in the
;; LICENSE.md file in the root directory of this source tree.

;;; Commentary:

;; Major mode for editing COBOL files using Superbol as a LSP server

;;; Code:

;; CHECKME: Force association right here?
(defun superbol-mode-enable-for-default-extensions ()
"Automatically associate `superbol-mode` with a few common COBOL file
extensions."
(dolist (regex '("\\.[cC][oO][bB]\\'"
"\\.[cC][bB][lL]\\'"
"\\.[cC][pP][yY]\\'"))
(add-to-list 'auto-mode-alist `(,regex . superbol-mode))))

;;;###autoload
(define-derived-mode superbol-mode prog-mode
"Superbol"
"SUPERBOL mode is a major mode for handling COBOL files. It is mostly intended
to be backed by an LSP."
;; XXX: could actually derive from cobol-mode, if available.

;; Straight from cobol-mode
(set (make-local-variable 'comment-start-skip)
"\\(^.\\{6\\}\\*\\|\\*>\\)\\s-* *")
(set (make-local-variable 'comment-start) "*>")
(set (make-local-variable 'comment-end) ""))

;; ---

(provide 'superbol-mode)
;;; superbol-mode.el ends here
95 changes: 92 additions & 3 deletions sphinx/emacs.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Emacs modes
===========
GNU/Emacs modes
===============

We document two means that are available for editing COBOL files using
GNU/Emacs. One makes use of a modified version of
:code:`cobol-mode.el` that can be found on ELPA. The other is a new
mode, :code:`superbol-mode`, that simply makes use of the LSP to
provide a powerful COBOL IDE.

Standard file :code:`cobol-mode.el`
-----------------------------------
Expand Down Expand Up @@ -30,7 +36,7 @@ change this option using :code:`M-x customize`, save and then restart emacs.
Features
~~~~~~~~

The :code:`cobol-mode.el` provides a following features:
The :code:`cobol-mode.el` provides the following features:

* colorization
* indentation
Expand All @@ -46,3 +52,86 @@ Customization
We advise to also use the :code:`auto-complete` mode also. This mode
will propose completions while typing keywords (use TAB or RET to
complete).

Superbol-mode
-------------

The new Superbol mode provides an IDE that makes use of the Superbol
LSP to provide advanced navigation and editing facilities for COBOL
projects. It can be used in combination with any of the two main LSP
clients that exist within the GNU/Emacs ecosystem to interact with LSP
servers: `lsp-mode` and `eglot`.

Superbol-mode with `lsp-mode`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`lsp-mode`_ appears to be the most prominent at the moment. This
client benefits from a large user-base, but is also considered
"bloated" by some.

The main advantages for using it in our context is its support for
`semantic tokens`_, that provide a way for LSPs to issue information
about the semantics of symbols from the source code. Compared to
traditional regexp-based highlighting, semantic tokens-based
highlighting can drastically improve code readability of various
source code elements based on their syntactic location;

.. _lsp-mode: https://github.com/emacs-lsp/lsp-mode
.. _semantic tokens:
https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide


Superbol-mode with `eglot`
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Another possibility is to use `eglot`_, that is sometimes considered
easier to configure and more lightweight than `lsp-mode` (which
notably makes it more reactive to user inputs). Being more recent, it
lacks some of the features of `lsp-mode`, among which is the support
for semantic tokens [#eglot-semtok-issue]_. However, additionally
enabling the aforementioned `cobol-mode.el` provides reasonable syntax
highlighting.

.. _eglot: https://elpa.gnu.org/packages/eglot.html

Setup
~~~~~

Let us first define an environment variable that indicates where the
``superbol-free`` executable can be found. Additionally, define a
variable that points to the root of the source directory for the
extension:

.. code-block:: shell
export SUPERBOL_DIR="<directory where superbol-free can be found>";
export SUPERBOL_VSCODE_PLATFORM_DIR="$PWD";
After this, the following command launches a GNU/Emacs instance with
an `lsp-mode`-based client configured for COBOL files:

.. code-block:: shell
emacs -L "$SUPERBOL_VSCODE_PLATFORM_DIR/emacs" \
--load lsp-superbol \
--eval "(custom-set-variables '(lsp-superbol-path \"$SUPERBOL_DIR\"))" \
--funcall superbol-mode-enable-for-default-extensions
To use `eglot`, type the following instead:

.. code-block:: shell
emacs -L "$SUPERBOL_VSCODE_PLATFORM_DIR/emacs" \
--load eglot-superbol \
--eval "(add-to-list 'exec-path \"$SUPERBOL_DIR\")" \
--funcall superbol-mode-enable-for-default-extensions
Further configuration for auto-indentation:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`lsp-mode` provides a ``lsp-format-region`` function that may be used
to use the LSP-provided intentation. When using `eglot`, the same
functionality is provided by ``eglot-format``.

.. [#eglot-semtok-issue] Note there is a pending issue on this point
at https://github.com/joaotavora/eglot/issues/615 .
Loading

0 comments on commit 0a05abe

Please sign in to comment.