module: add :lang fortran

* feat(fortran): account for f90 and fortran modes

* feat(fortran): initial keybindings

* feat(fortran): basic compilation

* feat(fortran): compilation popup

This customizes the name of the compilation buffer produced by the
`compile` function. We're keeping things simple; Emacs already knows how
to run compilation commands in a popup and parse the results, so let's
let it do its thing.

* feat(fortran): doctor checks

* docs(fortran): installation instructions

* feat(fortran): actual usage of fpm

* feat(fortran): configure compilation popups

* feat(fortran): improved raw gfortran usage

Although it's recommended to do everything through `fpm` to make life
easier.

* docs(fortran): backburner `+intel` for now

* feat(fortran): address PR suggestions
This commit is contained in:
Colin Woodbury 2021-12-15 06:16:22 -08:00 committed by GitHub
parent d43f260af6
commit f3ddf235b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 206 additions and 0 deletions

View file

@ -0,0 +1,76 @@
#+TITLE: lang/fortran
#+DATE: October 22, 2021
#+SINCE: v3.0.0 (#5676)
#+STARTUP: inlineimages nofold
* Table of Contents :TOC_3:noexport:
- [[#description][Description]]
- [[#maintainers][Maintainers]]
- [[#module-flags][Module Flags]]
- [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
- [[#arch-linux][Arch Linux]]
- [[#features][Features]]
- [[#configuration][Configuration]]
- [[#troubleshooting][Troubleshooting]]
* Description
This module enables a complete, modern development environment for the [[https://fortran-lang.org/][Fortran]]
language. Initially released in 1956 (a year before Lisp 1.0), Fortran is the
original high-performance computation language and is still widely used in
science and academia. Popular versions of the language include Fortran 77 and
Fortran 90, with further extensions in the 1995 and 2008 varieties. Today,
Fortran has joined the modern age with its own [[https://github.com/fortran-lang/fpm][package manager]], [[https://fortran-lang.org/packages/][package
registry]], and [[https://fortran-lang.discourse.group/][Discourse community]].
In particular, this module features:
+ Support for all major Fortran varieties.
+ Auto-formatting via =fprettier=.
+ Integration with the =fpm= package manager.
+ LSP support via [[https://github.com/hansec/fortran-language-server][fortran-language-server]].
#+begin_quote
After a career of writing Fortran on Mainframes and Windows machines, my
now-retired Dad is switching to Linux. Imagine my surprise when I learned that
off-the-shelf setups for Fortran on Linux basically don't exist! Well, until
now... Cheers Dad, hope this helps.
#+end_quote
** Maintainers
+ [[https://github.com/fosskers][@fosskers]] (Author)
** Module Flags
+ =+lsp= Activate =fortran-language-server= for Fortran projects.
** Plugins
* Prerequisites
For minimum functionality, this module requires =gfortran=. For most project
management tasks you will also need [[https://github.com/fortran-lang/fpm][fpm]], the Fortran Package Manager.
** Arch Linux
=gfortran= is available from the official repositories:
#+begin_example
sudo pacman -S gcc-fortran
#+end_example
Whereas =fpm= is available from the AUR and thus must be installed with an
AUR-compatible tool like [[https://github.com/fosskers/aura][Aura]]:
#+begin_example
sudo aura -A fortran-fpm
#+end_example
* Features
# An in-depth list of features, how to use them, and their dependencies.
* Configuration
# How to configure this module, including common problems and how to address them.
* Troubleshooting
# Common issues and their solution, or places to look for help.

View file

@ -0,0 +1,54 @@
;;; lang/fortran/autoload.el -*- lexical-binding: t; -*-
;; --- GFORTRAN --- ;;
;;;###autoload
(defun +fortran/gfortran-compile ()
"Compile the current buffer using gfortran."
(interactive)
(compile (format "gfortran %s %s"
(+fortran/fortran-std)
buffer-file-name)))
;;;###autoload
(defun +fortran/gfortran-run ()
"Run the current buffer using gfortran."
(interactive)
(delete-file "./a.out")
(+fortran/gfortran-compile)
(while (not (file-exists-p "./a.out"))
(sleep-for 1))
(compile "./a.out"))
(defun +fortran/fortran-std ()
"Which version of Fortran should we target?"
(cl-case major-mode
(fortran-mode "-std=legacy")
(t "")))
;; --- FPM --- ;;
;;;###autoload
(defun +fortran/fpm-build ()
"Build the current project using fpm."
(interactive)
(compile "fpm build"))
;;;###autoload
(defun +fortran/fpm-run ()
"Run the current project using fpm."
(interactive)
(compile "fpm run"))
;;;###autoload
(defun +fortran/fpm-test ()
"Test the current project using fpm."
(interactive)
(compile "fpm test"))
;; --- MISC. --- ;;
;;;###autoload
(defun +fortran/compilation-buffer-name (mode)
"The name of the buffer produced by `compile'."
(interactive)
"*fortran-compilation*")

View file

@ -0,0 +1,57 @@
;;; lang/fortran/config.el -*- lexical-binding: t; -*-
;;
;;; Packages
(use-package! f90
:defer t
:config
;; --- Compilation --- ;;
;; Used by `compile' (SPC c c)
(setq-hook! 'f90-mode-hook
compile-command "gfortran "
compilation-buffer-name-function #'+fortran/compilation-buffer-name)
(set-popup-rule! "^\\*fortran-compilation" :side 'right :size 0.5 :quit t)
;; --- LSP Configuration --- ;;
(when (featurep! +lsp)
(setq lsp-clients-fortls-args '("--enable_code_actions" "--hover_signature"))
(add-hook 'f90-mode-local-vars-hook #'lsp!))
;; --- Keybindings --- ;;
(map! :map f90-mode-map
:localleader
(:prefix ("f" . "fpm")
:desc "fpm build" "b" #'+fortran/fpm-build
:desc "fpm run" "r" #'+fortran/fpm-run
:desc "fpm test" "t" #'+fortran/fpm-test)
:desc "compile (gfortran)" "c" #'+fortran/gfortran-compile
:desc "run (gfortran)" "r" #'+fortran/gfortran-run))
(use-package! fortran
;; The `.for' extension is automatically recognized by Emacs and invokes
;; `fortran-mode', but not its capital variant `.FOR'. Many old files are
;; named the latter way, so we account for that manually here.
:mode ("\\.FOR$" . fortran-mode)
:config
;; Or else Flycheck will get very mad.
(setq flycheck-gfortran-language-standard "legacy")
;; --- Compilation --- ;;
;; Used by `compile' (SPC c c)
(setq-hook! 'fortran-mode-hook ; TODO These work for f90 but not for fortran.
compile-command "gfortran -std=legacy "
compilation-buffer-name-function #'+fortran/compilation-buffer-name)
(set-popup-rule! "^\\*fortran-compilation" :side 'right :size 0.5 :quit t)
;; --- LSP --- ;;
;; Strangely, the built-in flycheck support seems to give better hints than the LSP.
;; (when (featurep! +lsp)
;; (setq lsp-clients-fortls-args '("--enable_code_actions" "--hover_signature"))
;; (add-hook 'fortran-mode-local-vars-hook #'lsp!)))
;; --- Keybindings --- ;;
(map! :map fortran-mode-map
:localleader
:desc "compile (gfortran)" "c" #'+fortran/gfortran-compile
:desc "run (gfortran)" "r" #'+fortran/gfortran-run))

View file

@ -0,0 +1,18 @@
;; -*- lexical-binding: t; no-byte-compile: t; -*-
;;; lang/fortran/doctor.el
(assert! (or (not (featurep! +lsp))
(featurep! :tools lsp))
"This module requires (:tools lsp)")
(when (not (executable-find "gfortran"))
(warn! "Couldn't find gfortran - compilation will not work."))
(unless (executable-find "fpm")
(warn! "Couldn't find fpm - project building/testing will not work."))
(when (featurep! +lsp)
(unless (executable-find "fortls")
(warn! "Couldn't find fortls."))
(unless (executable-find "fprettify")
(warn! "Couldn't find fprettify.")))