From f3ddf235b5d0c1263aa42472e98d62aaba157aae Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 15 Dec 2021 06:16:22 -0800 Subject: [PATCH] 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 --- init.example.el | 1 + modules/lang/fortran/README.org | 76 ++++++++++++++++++++++++++++++++ modules/lang/fortran/autoload.el | 54 +++++++++++++++++++++++ modules/lang/fortran/config.el | 57 ++++++++++++++++++++++++ modules/lang/fortran/doctor.el | 18 ++++++++ 5 files changed, 206 insertions(+) create mode 100644 modules/lang/fortran/README.org create mode 100644 modules/lang/fortran/autoload.el create mode 100644 modules/lang/fortran/config.el create mode 100644 modules/lang/fortran/doctor.el diff --git a/init.example.el b/init.example.el index dc4e6ea9a..7e0ae3122 100644 --- a/init.example.el +++ b/init.example.el @@ -129,6 +129,7 @@ ;;ess ; emacs speaks statistics ;;factor ;;faust ; dsp, but you get to keep your soul + ;;fortran ; in FORTRAN, GOD is REAL (unless declared INTEGER) ;;fsharp ; ML stands for Microsoft's Language ;;fstar ; (dependent) types and (monadic) effects and Z3 ;;gdscript ; the language you waited for diff --git a/modules/lang/fortran/README.org b/modules/lang/fortran/README.org new file mode 100644 index 000000000..6e3989f3f --- /dev/null +++ b/modules/lang/fortran/README.org @@ -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. diff --git a/modules/lang/fortran/autoload.el b/modules/lang/fortran/autoload.el new file mode 100644 index 000000000..8216c28fc --- /dev/null +++ b/modules/lang/fortran/autoload.el @@ -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*") diff --git a/modules/lang/fortran/config.el b/modules/lang/fortran/config.el new file mode 100644 index 000000000..129f0a17f --- /dev/null +++ b/modules/lang/fortran/config.el @@ -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)) diff --git a/modules/lang/fortran/doctor.el b/modules/lang/fortran/doctor.el new file mode 100644 index 000000000..0d2de77e9 --- /dev/null +++ b/modules/lang/fortran/doctor.el @@ -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.")))