CERN-ROOT-mode User Manual
Table of Contents
1. Introduction
This is the user-manual for the CERN-ROOT-mode package, the source code of which can be found at https://github.com/jaypmorgan/cern-root-mode. In this manual, I detail how to install, use, customise, and help develop CERN-ROOT-mode.
CERN-ROOT-mode is an Emacs major-mode for interacting with ROOT (https://root.cern/). Specifically, this package provides the facilities to run the ROOT command line interface/REPL.
1.1. What is ROOT?
ROOT enables statistically sound scientific analyses and visualization of large amounts of data: today, more than 1 exabyte (1,000,000,000 gigabyte) are stored in ROOT files. The Higgs was found with ROOT!
1.2. What is CERN-ROOT-mode?
CERN-ROOT-mode is a major-mode in Emacs that provides the functionality to easily interact with the ROOT REPL. In this, we have provided various functions such as: creating a new REPL, sending lines/function definitions/evaluating files in this REPL. In addition to working with C++ files. This functionality is extended to org-mode. In this way, we may create C++ source code blocks and evaluate their contents, once again, using the ROOT REPL.
Figure 1: A brief example of what we want CERN-ROOT-mode to do: that is evaluate C++ statements in the ROOT REPL, quickly and easily.
2. Installation
2.1. Installing with package.el
CERN-ROOT-mode is available on Melpa, so if you use package.el
, and assuming that
you've added Melpa to the list of package archives (as shown below), then you can
run (package-install 'cern-root-mode)
.
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) ;; Comment/uncomment this line to enable MELPA Stable if desired. See `package-archive-priorities` ;; and `package-pinned-packages`. Most users will not need or want to do this. ;;(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t) (package-initialize)
(package-install 'cern-root-mode)
2.2. Manual installation
First you will need to clone the repository from Github:
git clone https://github.com/jaypmorgan/cern-root-mode ~/.emacs.d/cern-root-mode
After, in Emacs, you can load the package. First we're adding this cloned directory
to the load-path. This will ensure that when we call (load "root")
, Emacs will be
able to find a root.el
. After, we call (require 'cern-root-mode)
which will allow us to
begin using the package straight away.
(add-to-list 'load-path "~/.emacs.d/cern-root-mode/") (load "root") (require 'cern-root-mode)
If you want to configure some of the variables, these can be done using setq
. One
variable that you might want to customise is the cern-root-filepath
. This variable is the
path (absolute or relative) to the ROOT REPL executable.
(setq cern-root-filepath "/path/to/root" cern-root-terminal-backend 'vterm)
You may also want to configure some key-bindings to the commonly used functions. I would suggest that these key-bindings are only created within the C++ keymap.
(define-key 'c++-mode-map (kbd "C-c C-c") 'cern-root-eval-defun-maybe) (define-key 'c++-mode-map (kbd "C-c C-b") 'cern-root-eval-buffer) (define-key 'c++-mode-map (kbd "C-c C-l") 'cern-root-eval-file)
In summary we would have the following configuration:
(add-to-list 'load-path "~/.emacs.d/cern-root-mode/") (load "root") (require 'cern-root-mode) (setq cern-root-filepath "/path/to/root" cern-root-terminal-backend 'vterm) (define-key 'c++-mode-map (kbd "C-c C-c") 'cern-root-eval-defun-maybe) (define-key 'c++-mode-map (kbd "C-c C-b") 'cern-root-eval-buffer) (define-key 'c++-mode-map (kbd "C-c C-l") 'cern-root-eval-file)
2.3. Using use-package
and straight.el
Here is one example of installing/configuring the package with straight.el
:
(use-package cern-root-mode :bind (:map c++-mode-map (("C-c C-c" . cern-root-eval-defun) ("C-c C-b" . cern-root-eval-buffer) ("C-c C-l" . cern-root-eval-file) ("C-c C-r" . cern-root-eval-region))) :straight (cern-root-mode :type git :host github :repo "jaypmorgan/cern-root-mode") :config (setq cern-root-filepath "/path/to/root"))
3. Using cern-root-mode
When in a C++ major-mode buffer, enter the command (using M-x
): cern-root-run
. This will
start a new instance of the ROOT REPL in the same window.
If you want to create a new window for the ROOT REPL, instead of using cern-root-run,
enter the command: =cern-root-run-other-window
. This will first split the window sensibly,
then create a new ROOT REPL in the other window.
3.1. Using ROOT in Org-mode
CERN-ROOT-mode provides the functionality to execute C++ source code blocks using the ROOT REPL instead of the default C++ executable. This can make the process of writing C++ in org-mode more fluid (for an example, see fig:org-mode-test).
Figure 2: Evaluating C++ source code blocks within Org-mode documents using ROOT!
To write C++ code blocks that then are executed using ROOT, specify
root
as the language in the begin_src
header. For example:
#+begin_src root // write your code here. #+end_src
Upon executing this code block (such as with C-c C-c
), this code
will be executed in the ROOT REPL instead.
Code can be written and re-used over multiple code blocks with the use
of the :session
argument (with an optional name). By providing this
argument, a ROOT REPL instance will be created that can be used within
the context of many source blocks. For example, let's create another
code block with this session argument:
#+begin_src cern-root :session *my-root-session* void test() { // print something printf("This is something"); } #+end_src
When we first run this code block, CERN-ROOT-mode will create a new
instance of the ROOT REPL in the buffer named *my-root-session*
(you
can switch to this buffer if you want to interact directly outside of
the code blocks!). This means that, by specifying the same argument to
a different code block, we can call this test
function.
#+begin_src cern-root :session *my-root-session* test(); // call the test function #+end_src
This gets us a long way to achieving the same functionality as root --notebook
, but
in Emacs.
3.1.1. Creating Figures
Figures can be created by saving the plot before hand, and printing out the filename of the newly saved plot. Let's explain this by way of an example. If we have a function that creates a plot and saves it a file:
#+begin_src cern-root :session *root* const char* macro3(){ const char* filename{"/tmp/polar-plot.png"}; auto c = new TCanvas("myCanvas","myCanvas",600,600); double rmin = 0.; double rmax = TMath::Pi()*6.; const int npoints = 1000; double r[npoints]; double theta[npoints]; for (int ipt = 0; ipt < npoints; ipt++) { theta[ipt] = ipt*(rmax-rmin)/npoints+rmin; r[ipt] = TMath::Sin(theta[ipt]); } auto grP1 = new TGraphPolar(npoints,theta,r); grP1->SetTitle("A Fan"); grP1->SetLineWidth(3); grP1->SetLineColor(2); grP1->Draw("L"); gPad->Update(); grP1->GetPolargram()->SetToRadian(); c->SaveAs(filename); return filename; } #+end_src
We can then execute this function (which will save the plot), and then we just need to print out the name of the saved file. In addition, we need to specify that our results is a file:
#+begin_src cern-root :session *root* :results output file const char* filename = macro3(); printf("%s", filename); #+end_src
4. Customisation
There are only a few variables provided by the package:
- cern-root-filepath – (string, default
"root"
) this is the absolute/relative path to the root executable. This could be left as the default "root" value if ROOT is available on your $PATH. - cern-root-command-options – (string, default
""
) these are the command line options used when starting ROOT. By default there are no options. - cern-root-prompt-regex – (string, default
"^\\[[0-9;^k]+m?"
) this is the regular expression used to find the input prompt of the ROOT REPL. If there is a customised prompt, this will need to be updated to suit the customisation. - cern-root-buffer-name – (string, default
"*ROOT*"
) what to call the ROOT repl buffer when it starts. This could be left as the default*ROOT*
, but its there for you to modify as you please. - cern-root-terminal-backend – (symbol, default
'terminal
) the terminal emulator to run the ROOT instance in. There are only two current defined [=vterm=,inferior=]. By default, the terminal backend is set to =inferior
. Though, there is still some issues in getting the auto-complete to work correctly. If you really need auto-complete, I would recommend switching the backend to'vterm
(requires you've already installed vterm).
5. Developing CERN-ROOT-mode
5.1. Variable index
Variable cern-root-filepath (Default: ) Path to the ROOT executable.
Variable cern-root-command-options (Default: ) Command line options for running ROOT.
Variable cern-root-prompt-regex (Default: ) Regular expression to find prompt location in ROOT-repl.
Variable cern-root-terminal-backend (Default: ) Type of terminal to use when running ROOT.
Variable cern-root-buffer-name (Default: ) Name of the newly create buffer for ROOT.
5.2. Function index
Function cern-root-run nil Run an inferior instance of ROOT.
Function cern-root-run-other-window nil Run an inferior instance of ROOT in an different window.
Function cern-root-switch-to-repl nil Switch to the ROOT REPL.
Function cern-root-eval-region (beg end) Evaluate a region from BEG to END in ROOT.
Function cern-root-eval-line nil Evaluate this line in ROOT.
Function cern-root-eval-string (string) Send and evaluate a STRING in the ROOT REPL.
Function cern-root-eval-defun nil Evaluate a function in ROOT.
Function cern-root-eval-buffer nil Evaluate the buffer in ROOT.
Function cern-root-eval-file (filename) Evaluate FILENAME in ROOT.
Function cern-root-change-working-directory (dir) Change the working directory of ROOT to DIR.
Function cern-root-list-input-history nil List the history of previously entered statements.
Function cern-root--remembering-position (&rest body) Execute BODY and return to exact position in buffer and window.
Function cern-root--pluck-item (el lst) Return the value of EL in the plist LST.
Function cern-root--make-earmuff (name) Give a NAME earmuffs, i.e. some-name -> *some-name*.
Function cern-root--make-no-earmuff (name) Remove earmuffs from a NAME if it has them, *some-name* -> some-name.
Function cern-root--set-env-vars nil Set the environment variable for current directory. Setup the environment variables so that no colours or bold fonts will be used in the REPL. This prevents comint from creating duplicated input in trying to render the ascii colour codes. Function returns t if the variables have been set, else nil. This return value is very useful for deciding if the variables should be unset, as we will want not want to remove the user’s existing rcfiles.
5.3. Testing
To test the functionality of the package, some unit tests have been
stored in the tests/
directory. To run these unit tests, you can
either evaluate the specific buffer in Emacs and run ert
(see
https://www.gnu.org/software/emacs/manual/html_node/ert/Running-Tests-Interactively.html
for more information), or you can them all from the command line
using:
emacs -batch \ -l ert \ -l cern-root-mode.el \ -l tests/test-cern-root-mode.el \ -f ert-run-tests-batch-and-exit
5.4. Contributions
All contributions should be directed to https://github.com/jaypmorgan/cern-root-mode where you can submit issues and pull-requests.