Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft version of basic superbol-mode for GNU/Emacs #6

Merged
merged 2 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading