\input texinfo
@comment %**start of header
@documentencoding UTF-8
@setfilename rec-mode.info
@settitle rec-mode for Emacs
@set UPDATED 19 June 2022
@set EDITION 1.8.90
@set VERSION 1.8.90
@set RECMODEVERSION 1.9.0
@afourpaper
@comment %**end of header

@c Macros used in this file.

@macro ie
@i{i.e.@:}
@end macro

@macro reccmd{key,command}
@item \key\
@itemx M-x \command\
@kindex \key\
@findex \command\
@c
@end macro

@c Merge variable and concept indexes
@synindex cp vr

@copying
This manual is for rec-mode @value{RECMODEVERSION} for Emacs, which is part of the GNU
recutils suite. This rec-mode manual has last been updated @value{UPDATED}.

Copyright @copyright{} 2012-2022 Free Software Foundation, Inc.

@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled ``GNU Free
Documentation License''.
@end quotation
@end copying

@dircategory Emacs
@direntry
* Rec Mode: (rec-mode). Emacs mode for editing recfiles.
@end direntry

@titlepage
@title rec-mode: an Emacs mode for editing recfiles
@subtitle for version @value{VERSION}, @value{UPDATED}
@author by Jose E. Marchesi
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@contents

@ifnottex
@node Top
@top rec-mode: an Emacs mode for editing recfiles

This manual documents version @value{RECMODEVERSION} of rec-mode.

@insertcopying
@end ifnottex

@menu
* Introduction::                Getting started
* Navigation mode::             User-friendly interface for browing recfiles
* Edition modes::               Edit recfiles in rec-format
* Summary mode::                List records in a table.
* Selecting records::           Run queries on the current buffer.
* Cross referencing::           Cross reference records.
* Configuration::               Adapting rec-mode to your needs
* Command Index::               Command and Function Index
* Key Index::                   Key (Character) Index
* Variable and Concept Index::  Variable and Concept Index
* GNU Free Documentation License::  Distribution terms for this document

@detailmenu
 --- The Detailed Node Listing ---

Introduction

* Installation::                How to install rec-mode
* Activation::                  How to activate rec-mode for certain buffers
* Feedback::                    Bug reports, ideas, patches etc.

Navigation mode

* Record navigation::           Moving through records
* Field navigation::            Moving through fields in a record
* Field folding::               Hiding and showing the values of fields
* Field edition::               Changing the values of fields
* Searches::                    Finding records fulfilling some criteria
* Statistics::                  Counting records
* Data integrity::              Verifying the integrity of the recfile

Selecting records

* Buffer from selection::       Copy the selection into a new recfile buffer.
* Selection mode::              Navigate the current buffer based on a search.


Cross referencing

* Cross-referencing records using foreign keys:: Jump to records using foreign keys
* Cross referencing by selection:: Navigate between records using selection expressions

Configuration

* Finding the recutils::        Specifying the location of the recutils.
* Records appearance::          Setting the way records are displayed

@end detailmenu
@end menu

@node Introduction
@chapter Introduction

rec-mode is a mode for browsing and editing recfiles, which are text
files containing data structured in fields and records.  It is part of
the GNU recutils@footnote{@url{http://www.gnu.org/software/recutils}}
suite.


Recfiles are text-based databases which are easy to read and write
manually using a text editor.  At the same time they feature enough
structure so they can be read, edited and processed automatically by
programs.

@menu
* Installation::                How to install rec-mode
* Activation::                  How to activate rec-mode for certain buffers
* Feedback::                    Bug reports, ideas, patches etc.
@end menu

@node Installation
@section Installation

rec-mode is implemented in a self-contained elisp file called
@file{rec-mode.el}.  It can be obtained in several ways:

@itemize @minus
@item From @url{https://elpa.gnu.org/packages/rec-mode.html, GNU ELPA}
using the built-in Emacs package manager. 
@item As part of the source tree cloned from the development git
repository of rec-mode.  @file{rec-mode.el} can be found in the root directory of
the recutils sources tree.
@item As a single file downloaded form some other location in
internet.
@item It may be already installed as part of a binary package in some
distribution.
@end itemize

@noindent In the second case you need to tell Emacs where to locate the
@file{rec-mode.el} file and to load it.  Add the following to your
@file{.emacs} file.

@lisp
(add-to-list 'load-path "~/path/to/recmode/")
(require 'rec-mode)
@end lisp

@noindent If @file{rec-mode.el} was installed as part of a binary
package in a distribution then you usually don't have to touch the
@code{load-path} variable.  Depending on the specific case you may
have to @code{require} the package.

@node Activation
@section Activation
@cindex activation

rec-mode should automatically activate when opening @file{.rec} files.
To make sure files with extension @file{.rec} use rec-mode, add the
@noindent rec-mode buffers need font-lock to be turned on - this is
the default in Emacs@footnote{If you don't use font-lock globally,
turn it on in the rec buffer with @code{(add-hook 'rec-mode-hook
'turn-on-font-lock)}}.

If the file doesn't end in @file{.rec}, make the first line of a
recfile look like this:

@example
# -*- mode: rec -*-
@end example

@noindent which will select rec-mode for this buffer no matter what
the file's name is.

@node Feedback
@section Feedback
@cindex feedback
@cindex bug reports
@cindex maintainer
@cindex author

If you find problems with rec-mode, or if you have questions, remarks,
or ideas about it, please mail to the recutils mailing list
@email{bug-recutils@@gnu.org}.  If you are not a member of the mailing
list, your mail will be passed to the list after a moderator has
approved it@footnote{Please consider subscribing to the mailing list,
in order to minimize the work the mailing list moderators have to do.
The subscription can be done online at
@url{http://lists.gnu.org/mailman/listinfo/bug-recutils}.}.

@node Navigation mode
@chapter Navigation mode
@cindex navigation mode
@cindex modes, navigation

When a recfile is visited in Emacs and rec-mode is activated, the
contents of the file are examined and parsed in order to determine if
it is a valid recfile and, in that case, to extract information like
the kind of records stored in the file.

If the file does not contain valid rec data then the buffer is put in
@code{fundamental-mode} and a description of the syntax error, along
its location, is notified in the echo area.

If the file contains valid rec data, the mode sets itself in what is
known as ``navigation mode''.  In this mode the buffer is made
read-only and it is narrowed to the first record present in the file.
Also, the presentation of the record contents is slightly changed in
order to improve the visualization of the data: continuation line
marks are replaced by indentation, big fields are folded, etc.  The
modeline is changed in order to reflect the type of the records being
navigated.

At this point the user can navigate through the records and fields
contained in the file, and edit the contents of the fields and the
structure of the records, by using the commands described in the
following subsections.

@menu
* Record navigation::           Moving through records
* Field navigation::            Moving through fields in a record
* Field folding::               Hiding and showing the values of fields
* Field edition::               Changing the values of fields
* Searches::                    Finding records fulfilling some criteria
* Statistics::                  Counting records
* Data integrity::              Verifying the integrity of the recfile
@end menu

@node Record navigation
@section Record navigation
@cindex motion, between records
@cindex jumping, to records
@cindex record navigation

The following commands jump to other records in the buffer.

@table @kbd
@reccmd{n,rec-cmd-goto-next-rec}
Display the next record of the same type in the buffer.
@*`C-u N n' will move next N times.
@reccmd{p,rec-cmd-goto-previous-rec}
Display the previous record of the same type in the buffer.
@*`C-u N p' will move backwards N times.
@reccmd{d, rec-cmd-show-descriptor}
Display the record descriptor applicable to the current record.  If
the current record is anonymous, @ie{} there is not record
descriptor. then this command does nothing.
@reccmd{b, rec-cmd-jump-back}
Display the record previously displayed in the buffer.
@reccmd{C-c C-t, rec-find-type}
Prompt the user for one of the record types present in the recfile and
display the first record of the selected type.
@end table

@node Field navigation
@section Field navigation

The following commands iterate through the fields in a record, and to
get information about some of the properties of the fields.

@table @kbd
@reccmd{TAB, rec-cmd-goto-next-field}
Move the cursor to the beginning of the name of the next field in the
current record.  If the cursor is currently located at the last field
of the record then move it to the beginning of the first field.

@reccmd{t, rec-cmd-show-type}
Show information about the type of the field under the cursor, if it
is defined.
@end table

@node Field folding
@section Field folding
@cindex folding

Fields in recfiles can contain data of any size, and sometimes it is
difficult to have an overview of the contents of the record.  The
following commands fold and unfold the value of the field under the
cursor.

@table @kbd
@reccmd{SPC, rec-cmd-toggle-field-visibility}
Toggle the visibility of the field under the cursor.  When a field is
folded then three dots are displayed in the buffer instead of the
value of the field.

It is possible to automatically fold any field whose value exceeds a
certain limit which can be configured by the user. @xref{Records
appearance}.
@end table

@node Field edition
@section Field edition
@cindex editing fields
@cindex edition, fields

The following commands change the value of the field under the cursor.

@table @kbd
@reccmd{e, rec-cmd-edit-field}
Edit the value of the field under the cursor.  The specific action
depends on the type of the field in the corresponding record
descriptor:
@itemize @minus
@item For @b{date} fields a calendar buffer is opened in another window
and the focus is moved there.  The user can then select a date by
moving the cursor there and press @kbd{RET} in order to set that date
as the value for the field.  Alternatively the user can press @kbd{t}
in order to set the field to ``now'', or @kbd{q} to cancel the
operation.  In the later case the value of the field is left
untouched.
@item For @b{enumerated} and @b{bool} fields a fast-select buffer is opened in
another window, showing a list of labeled options.  The labels are
single digits and letters.  The user can then select ony of the
options by pressing the corresponding label, or cancel the operation
by pressing @kbd{RET}.  In the later case the value of the field is
left untouched.
@item For any other kind of fields an edition buffer is opened in
another window, showing the current contents of the field.  The user
can then edit the buffer as desired.  When she is done, the user can
then press @kbd{C-c C-c} in order to set the new value of the field,
or just kill the buffer to cancel the operation.
@end itemize
@reccmd{m, rec-cmd-trim-field-value}
Trim the value of the field under the cursor, removing any sequence of
leading and trailing blank characters.
@end table

@node Searches
@section Searches

The following commands jump to the first record in the buffer
satisfying some criteria.

@table @kbd
@reccmd{s q, rec-cmd-jump-to-fast}
Display the first record having a field whose value matches a given
fixed pattern.  This is equivalent of using the command line option
@option{-q} of @command{recsel}.  If a prefix argument is specified
then the search is case-insensitive.
@reccmd{s s, rec-cmd-jump-to-sex}
Display the first record in the buffer satisfying a given selection
expression.  This is equivalent of using the command line option
@option{-e} of @command{recsel}.  If a prefix argument is specified
then the search is case-insensitive.
@end table

@node Statistics
@section Statistics
@cindex counting

The following commands allow to count records in the current buffer
based on some provided criteria.

@table @kbd
@reccmd{I, rec-cmd-show-info}
Show the number of records in the buffer categorized by type.
@reccmd{#, rec-cmd-count}
Count the number of records in the buffer having the same type as the
current record.  With a numeric prefix N, ask for a selection
expression and count the number of records in the buffer satisfying
the expression.

Note that rec-mode tries to guess a reasonable default for the
selection expression, depending on the type of the field and its
value.  If the user press @kbd{RET} then the provided default
selection expression is used.
@reccmd{%, rec-cmd-statistics}
If the field under the cursor contains an enumerated value, show the
percentages of records in the current record set having fields with
each of the possible values of the enumerated type.
@end table

@node Data integrity
@section Data integrity
@cindex fixing records

The integrity of the rec data stored in the file can be checked using
the following commands.

@table @kbd
@reccmd{c, rec-cmd-compile}
Compile the buffer with @command{recfix} and open a compilation window
showing the result of the command.  In case some error or warning is
reported, the user can jump to the location triggering the error by
pressing @kbd{RET} in the compilation window.
@end table

@node Edition modes
@chapter Edition modes
@cindex edition modes
@cindex modes, edition

The navigation mode described in a previous chapter is mainly intended
for browsing recdata and doing changes at the record level: editing
the contents of a field, adding or removing fields, etc.  In order to
perform broader changes, such as adding/deleting record descriptors,
records or comment blocks, the user must enter into one of the
``edition modes''.

There are three edition modes, covering different areas of the
recfile: record, record type and buffer.  When an edition mode is
entered the buffer is set in read/write mode, it is narrowed to the
desired area and any embellishment used in navigation mode is
removed@footnote{Exceptuating font-lock}.  As a general rule, the
commands available in navigation mode are also available in the
edition mode prefixed with @kbd{C-c} and with a control sequence
@kbd{C-}.  Thus, @kbd{n}, which in record navigation mode jumps to the
next record, becomes @kbd{C-c C-n} in the record edition modes.  The
exceptions to this are the bindings @kbd{c}
(@command{rec-cmd-compile}) which becomes @kbd{C-c C-k} and @kbd{h}
(@command{rec-cmd-show-summary}) which becomes @kbd{C-c M-h}. 

The following commands are used to enter into one of the available
edition modes from the navigation mode.

@table @kbd
@reccmd{R, rec-edit-record}
Edit the record being navigated.
@reccmd{T, rec-edit-type}
Edit the record set being navigated.
@reccmd{B, rec-edit-buffer}
Edit the buffer.
@end table

@noindent After doing modifications in the buffer, the user can go
back to navigation mode by using the following command.

@table @kbd
@reccmd{C-c C-c, rec-finish-editing}
Finish the current edition and return to navigation mode.  If a
syntactic error was introduced in the edition activity then the error
is reported in the echo area and navigation mode is not entered.
@end table

@node Summary mode
@chapter Summary mode
@cindex summary
@cindex modes, summary

Besides the standard viewing modes of buffers, there is also a third
option called @dfn{summary mode}.  Summary mode is a tabulated list of
the record in which each record is a row in the table.  The columns in
the table are determined by user input, or alternatively, by special
keys in the current file.

@table @kbd
@reccmd{h, rec-cmd-show-summary}
Creates a summary buffer from the current type being viewed in the
recfile. The columns are based on user input (prompted), or if the
record has either a @code{%summary} or @code{%key} in its descriptor,
those fields are used.
@end table

The input for the summary query is a @dfn{field expression}, a
comma-separated list of column names.  Thus, if your recfile looks
like the following:

@example
Name: Ada Lovelace
Age: 36

Name: Peter the Great
Age: 53

Name: Matusalem
Age: 969
@end example

Then calling @kbd{rec-cmd-show-summary} and entering @code{Name,Age}
would create a table of all records with those columns.  If your
record descriptor contains a @code{%summary} like below:

@example
%summary: Age,Name
@end example

@noindent then this is used as the field expression instead.
Similarly, if no @code{%summary} field is defined and a @code{%key}
field exists, then that field is used.

Calling this command enters @dfn{record summary mode}, which a a major
mode derived from @dfn{tabulated list mode} (@pxref{Tabulated List
mode,,,elisp}). In this mode, the following bindings are available:

@table @kbd
@reccmd{n, rec-summary-cmd-next}
Go to the next record in the summary.
@end table

@noindent Navigation inside the summary buffer maintains the position
of the associated recfile buffer, and vice versa.  The currently
active record in the recfile is shown highlighted in the buffer.  As a
result, the summary can be thought of as a useful ``overview''
overview for any recfile buffer.

@node Selecting records
@chapter Selecting records

Sometimes it is useful to operate or inspect only a subset of all the
records on the file.  To this end, rec-mode provides several ways of
using the searching facilities of recutils.

Selection can be done using two mechanisms:

@itemize @bullet
@item
@b{selection expressions}, which are expressions that can be applied
to a record. These offer a powerful query language for
records. @xref{Selection Expressions,,,recutils,GNU Recutils manual}.

@item
@b{fast string searches}, which match records whose field values match
a string.
@end itemize

For instance, you can create a new buffer out of the current buffer,
so that only the records that match your search are copied.  This way
you can create new recfiles out of existing ones based on selections.

To help navigate the buffer based on a search, you can create a new
navigation mode where the commands for moving between records only
move to those matching a search.  This is known as selection mode.

@menu
* Buffer from selection::       Copy the selection into a new recfile buffer.
* Selection mode::              Navigate the current buffer based on a search.

@end menu

@node Buffer from selection
@section Buffer from selection
@cindex selection, buffer

Creating new recfiles based on selections can be done by creating a
wholly new buffer using the @dfn{buffer from selection} commands in
rec-mode.

@table @kbd
@reccmd{x s, rec-cmd-new-buffer-from-sex}
Creates a new buffer from a @dfn{selection expression}. @xref{Selection
Expressions,,,recutils,GNU Recutils Manual}.  Prompts the user for a
selection expression and then displays a new buffer containing records
that match the expression. 
@reccmd{x q, rec-cmd-new-buffer-from-fast-string}
Creates a new buffer from a @dfn{fast string search}.  Prompts the user
for a @i{string} and then displays a new buffer which contains all
records whose any field contains this string.
@end table

In both of these commands, if the recfile has a @dfn{record descriptor},
it is copied as well.

@node Selection mode
@section Selection mode
@cindex selection mode
@cindex modes, selection

In both navigation mode and the assorted edition modes,
@code{rec-cmd-goto-next-rec} and @code{rec-cmd-goto-prev-rec} navigate
to the next and previous record, respectively.  On large files,
finding a particular record using these commands only can be quite
tedious.  To this end, using selections, it is possible to jump to or
restrict navigation to records matching selections.

@noindent Restricting the navigation commands, typically
bound to @kbd{n} and @kbd{C-c C-n} (@i{mutatis mutandis} for backward
movement), to records that match the current selection, can be done
using what is called @i{record selection mode}.

Record selection mode is a buffer-local minor mode in which the
commands for next and previous records as described above do not
behave the usual way: they navigate records that only match
the currently active selection.

When selection mode is entered, any associated summary buffer
automatically updates its contents to match that of the current
selection.  Once selection mode is turned off, the summary buffer
reverts back to the previous selection.

Record selection mode can be entered by the following commands:

@table @kbd
@reccmd{/ s, rec-cmd-navigate-current-type-by-sex}
Prompts the user for a selection expression, runs a query on the
current buffer and the current type, and then enters record selection
mode.
@reccmd{/ q, rec-cmd-navigate-current-type-by-fast-string}
Same as above, but with a fast string search.
@end table

@noindent In record selection mode, besides the standard navigation bindings,
the following additional bindings are defined:

@table @kbd

@reccmd{/ /, rec-cmd-exit-selection}
Exits record selection mode and restores the normal navigation keybindings.
@end table

@node Cross referencing
@chapter Cross referencing
@cindex cross referencing
@cindex xref

Besides navigation, edition and selection, rec-mode provides another
powerful feature for recfiles, known as @dfn{cross referencing}. In
short, cross referencing is an Emacs term for listing various kinds of
search results for certain keywords an identifiers. For records, this
could mean the following:

@enumerate
Finding the referred record of a foreign key.  If a field is a key
referring to another record, you can jump to that record.
@item
Finding the @i{referents} of a record if it is a foreign key. 
@item
Finding records that match a certain selection expression or fast
string search.
@end enumerate

@noindent Emacs provides a unified interface for this called Xref, see
@xref{Xref,,,emacs,GNU Emacs Manual}.  rec-mode
implements a custom xref backend for the purpose of easier navigating
between records.

Regardless of functionality, if there are more than one search result,
Xref searches present their results in a special @code{XREF} buffer.
It is an ordered list of results, similar to compilation mode
(@pxref{Compilation Mode,,,emacs,GNU Emacs Manual}). Xref makes it
easy to navigate between search results, as it binds the
@code{next-error} functionality, letting you navigate the results even
if you are @i{outside} the rec mode buffer.

@menu
* Cross-referencing records using foreign keys::
* Cross referencing by selection::
@end menu

@node Cross-referencing records using foreign keys
@section Cross-referencing records using foreign keys
@cindex cross referencing, foreign keys

When a record field is a reference to another record, it is possible
to use navigate from the referring field to that record. Consider the
following record:

@example
%rec: Book
%type: Published int
%type: Author rec Author

Title: Cat's Cradle
Published: 1963
Author: KurtVonnegut

Title: Breakfast of Champions
Published: 1973
Author: KurtVonnegut

Title: The Left Hand of Darkness
Published: 1969
Author: UrsulaKLeGuin

%rec: Author
%key: Id

Id: UrsulaKLeGuin
Name: Ursula K. Le Guin

Id: KurtVonnegut
Name: Kurt Vonnegut, Jr.

@end example

@subsection Navigating to referred records
@cindex cross-referencing, goto-definition

Navigating to @code{Author} field of the @code{Book} records and
hitting @kbd{M-.} (@code{xref-goto-definition}) will jump the editor
to the corresponding @code{Author} record.  The requirement is that
the current field is a valid foreign key, i.e. the field is a record
reference and the referred record exists in the current buffer.

@subsection Finding record references
@cindex cross-referencing, backreferences

On the other hand, in the above example, navigating anywhere on an
@code{Author} record, it is possible to list all the records referring
@emph{that} record using @kbd{M-?} (@code{xref-find-references}).
This works on any field of the record, since we foreign keys @emph{to}
the record work on the record level.

@subsection Commands for cross-referencing
@cindex cross-referencing, keybindings

@table @kbd
@reccmd{M-., xref-goto-definition}

Jump to the record referenced by this field, if possible. Use
@kbd{M-.} and @kbd{C-M-,} to jump between the results.

@reccmd{M-?, xref-find-references}

List all the records that reference this record.  The record
referenced must have a @code{%key} in its descriptor for this to work,
and to get any results the referring records must have properly used
foreign keys. 

@end table

For more keybindings, @xref{Looking Up Identifiers,,,emacs,Gnu Emacs
Manual}. For more info about foreign keys in recutils, @xref{Foreign Keys,,,recutils,Recutils Manual}.

@node Cross referencing by selection
@section Cross referencing by selection
@cindex cross referencing, selection

Cross referencing @i{by selection} lets you perform a query and then
list the results using the Xref buffer.  Rec mode provides two such
commands:

@table @kbd
@reccmd{X s, rec-cmd-xref-sex}
Query the current recfile using a selection expression and the current
type and then list the results using Xref.  Each results shows a small
snippet of the matched record making it easier to identify which
records matched the search.
@reccmd{X q, rec-cmd-xref-fast-string}
Like above, but using a fast string.  Instead of previewing the first
three fields of a record, it shows each field where there was a match.
@end table

@node Configuration
@chapter Configuration

rec-mode can be configured using the customization facilities of
Emacs. 

@menu
* Finding the recutils::        Specifying the location of the recutils.
* Records appearance::          Setting the way records are displayed
@end menu

@node Finding the recutils
@section Finding the recutils

@code{rec-mode} makes use of the several utilities which are part of
the recutils.  The following variables tell the mode where to find the
utilities.  The default values of these variables must work if the
recutils are installed system-wide in the system.

@defvar rec-recsel
Name of the @code{recsel} utility from the GNU recutil.
@end defvar

@defvar rec-recinf
Name of the @command{recinf} utility from the GNU recutils.
@end defvar

@defvar rec-recfix
Name of the @command{recfix} utility from the GNU recutils.
@end defvar

@node Records appearance
@section Records appearance

The appearance of the records in navigation mode can be customised by
tweaking the value of the following variables.

@defvar rec-max-lines-in-fields
Values in fiels having more than the specified number of lines will be
hidden by default in navigation mode.  When hidden, an ellipsis is
shown instead of the value of the field.  Default is @code{15}.
@end defvar

@node Command Index
@unnumbered Command and Function Index
@printindex fn

@node Key Index
@unnumbered Key (Character) Index
@printindex ky

@node Variable and Concept Index
@unnumbered Variable and Concept Index
@printindex vr

@node GNU Free Documentation License
@appendix GNU Free Documentation License

@include fdl.texi

@bye
