GUI::Editors
Table of Contents
NAME
GUI::Editors
AUTHOR
Francis Grizzly Smit (grizzly@smit.id.au)
VERSION
0.1.12
TITLE
GUI::Editors
SUBTITLE
A Raku module for managing the users GUI Editor preferences in a variety of programs.
COPYRIGHT
LGPL V3.0+ LICENSE
Top of Document
Introduction
A Raku module for managing the users GUI Editor preferences in a variety of programs.
$editor-config
A constant which contains the location of the users editors file
# the home dir #
constant $home = %*ENV<HOME>.Str();
# config files
constant $editor-config is export = "$home/.local/share/gui-editors";
NB: the $home
is the value of the users HOME environment variable.
Top of Document
@config-files
An array containing the configuration files of the program, by default it is set to contain editors the editors configuration file the remainder should be added by init-gui-editors(...)
the initialization procedure for the module.
# The config files to test for #
my Str:D @config-files = qw{editors};
sub config-files( --> Array[Str:D]) is export {
return @config-files;
}
@guieditors
An array of known GUI editors.
my Str:D @guieditors;
sub guieditors( --> Array[Str:D]) is export {
return @guieditors;
}
Top of Document
grammar Editors & action class EditorsActions
grammar Editors is BasePaths is export {
regex TOP { [ <line> [ \v+ <line> ]* \v* ]? }
regex line { [ <white-space-line> || <override-gui_editor> || <config-line> || <editor-to-use> || <comment-line> ] }
regex white-space-line { ^^ \h* $$ }
regex override-gui_editor { ^^ \h* 'override' \h+ 'GUI_EDITOR' [ \h+ '#' <comment> ]? \h* $$ }
regex comment-line { ^^ \h* '#' <-[\v]>* $$ }
regex config-line { ^^ \h* 'guieditors' \h* '+'? '=' \h* <editor> \h* [ '#' <comment> \h* ]? $$ }
regex editor-to-use { ^^ \h* 'editor' \h* ':'? '=' \h* <editor> \h* [ '#' <comment> \h* ]? $$ }
regex editor { <editor-name> || <base-path> <editor-name> }
regex comment { <-[\n]>* }
token editor-name { <with-other-stuff> }
}
class EditorsActions does BasePathsActions is export {
method white-space-line($/) {
my %wspln = type => 'white-space-line', value => ~$/;
make %wspln;
}
method comment-line($/) {
my %comln = type => 'comment-line', value => ~$/;
make %comln;
}
#token editor-name { <with-other-stuff> }
method editor-name($/) {
my $edname = $/<with-other-stuff>.made;
make $edname;
}
method editor($/) {
my $ed-name;
if $/<base-path> {
$ed-name = $/<base-path>.made ~ $/<editor-name>.made;
} else {
$ed-name = $/<editor-name>.made;
}
make $ed-name;
}
method comment($/) {
my $comm = (~$/).trim;
make $comm;
}
method config-line($/) {
my %cfg-line = type => 'config-line', value => $/<editor>.made;
if $/<comment> {
my $com = $/<comment>.made;
%cfg-line«comment» = $com;
}
make %cfg-line;
}
method editor-to-use($/) {
my %editor-to-use = type => 'editor-to-use', value => $/<editor>.made;
if $/<comment> {
my $com = $/<comment>.made;
%editor-to-use«comment» = $com;
}
make %editor-to-use;
}
method override-gui_editor($/) {
my %override-gui_editor = type => 'override-gui_editor', :value;
if $/<comment> {
my $com = $/<comment>.made;
%override-gui_editor«comment» = $com;
}
make %override-gui_editor;
}
method line($/) {
my %ln;
if $/<white-space-line> {
%ln = $/<white-space-line>.made;
} elsif $/<comment-line> {
%ln = $/<comment-line>.made;
} elsif $/<config-line> {
%ln = $/<config-line>.made;
} elsif $/<editor-to-use> {
%ln = $/<editor-to-use>.made;
} elsif $/<override-gui_editor> {
%ln = $/<override-gui_editor>.made;
}
make %ln;
}
method TOP($made) {
my @top = $made<line>».made;
$made.make: @top;
}
} # class EditorsActions does BasePathsActions is export #
Top of Document
grammar EditorLine & class EditorLineActions
A grammar and associated action class to parse and recognise the editor := value # comment
lines in the editors file.
grammar EditorLine is BasePaths is export {
regex TOP { ^ \h* 'editor' \h* ':'? '=' \h* <editor> \h* [ '#' <comment> \h* ]? $ }
regex editor { <editor-name> || <base-path> <editor-name> }
regex comment { <-[\n]>* }
token editor-name { <with-other-stuff> }
}
class EditorLineActions does BasePathsActions is export {
#token editor-name { <with-other-stuff> }
method editor-name($/) {
my $edname = $/<with-other-stuff>.made;
make $edname;
}
method editor($/) {
my $ed-name;
if $/<base-path> {
$ed-name = $/<base-path>.made ~ '/' ~ $/<editor-name>.made;
} else {
$ed-name = $/<editor-name>.made;
}
make $ed-name;
}
method comment($/) {
my $comm = (~$/).trim;
make $comm;
}
method config-line($/) {
my %cfg-line = type => 'config-line', value => $/<editor>.made;
if $/<comment> {
my $com = $/<comment>.made;
%cfg-line«comment» = $com;
}
make %cfg-line;
}
method TOP($made) {
my %top = type => 'editor-to-use', value => $made<editor>.made;
if $made<comment> {
my $com = $made<comment>.made;
%top«comment» = $com;
}
$made.make: %top;
}
} # class EditorLineActions does BasePathsActions is export #
Top of Document
grammar OverrideGUIEditor & actions class OverrideGUIEditorActions
A grammar to parse/recognise the override GUI_EDITOR # comment
line.
grammar OverrideGUIEditor is export {
regex TOP { ^ \h* [ <commented> \h* ]? 'override' \h+ 'GUI_EDITOR' [ \h+ '#' <comment> ]? \h* $ }
regex comment { <-[\n]>* }
token commented { '#' }
}
class OverrideGUIEditorActions is export {
method comment($/) {
my $comment = (~$/).trim;
make $comment;
}
method commented($/) {
my $commented = (~$/).trim;
make $commented;
}
method TOP($made) {
my %top = type => 'override-gui_editor', :value;
if $made<commented> {
%top«value» = False;
}
if $made<comment> {
my $com = $made<comment>.made;
%top«comment» = $com;
}
$made.make: %top;
}
} # class OverrideGUIEditorActions #
Top of Document
Some useful variables
NB: All these variables are available outside of the module as a sub of the same name. That way I can give read only access to them.
$GUI_EDITOR
The value of the %*ENV«GUI_EDITOR»
environment variable or ''
if not set.
$VISUAL
The value of the %*ENV«VISUAL»
environment variable or ''
if not set.
$EDITOR
The value of the %*ENV«EDITOR»
environment variable or ''
if not set.
my Str:D $GUI_EDITOR = ((%*ENV<GUI_EDITOR>:exists) ?? ~%*ENV<GUI_EDITOR> !! '');
my Str:D $VISUAL = ((%*ENV<VISUAL>:exists) ?? ~%*ENV<VISUAL> !! '');
my Str:D $EDITOR = ((%*ENV<EDITOR>:exists) ?? ~%*ENV<EDITOR> !! '');
sub GUI_EDITOR( --> Str:D) is export {
return $GUI_EDITOR;
}
sub VISUAL( --> Str:D) is export {
return $VISUAL;
}
sub EDITOR( --> Str:D) is export {
return $EDITOR;
}
Top of Document
@GUIEDITORS
The Array of Hashes that the Editors
grammar and EditorsActions
generate from parsing the editors file.
@gui-editors
The Array of GUI Editors defined in the editors file.
@default-editors
The array of editors selected in the file should have only one element otherwise the file is miss configured.
my Hash @GUIEDITORS;
my Str:D @gui-editors;
my Str:D @default-editors;
sub GUIEDITORS( --> Array[Hash]) is export {
return @GUIEDITORS;
}
sub gui-editors( --> Array[Str:D]) is export {
return @gui-editors;
}
sub default-editors( --> Array[Str:D]) is export {
return @default-editors;
}
Top of Document
@override-gui_editor
An array of True values one for each of the times the override GUI_EDITOR
directive appears in the editors file, it is an error for it to appear more than once, (it's a zero or one rule).
$override-GUI_EDITOR
True if the override GUI_EDITOR
directive is present in the editors file. If True then the setting in the file overrides the %*ENV«GUI_EDITOR»
variable, otherwise %*ENV«GUI_EDITOR»
wins.
my Bool:D @override-gui_editor;
sub override-gui_editor( --> Array[Bool:D]) is export {
return @override-gui_editor;
}
my Bool:D $override-GUI_EDITOR = False;
sub override-GUI_EDITOR( --> Bool:D) is export {
return $override-GUI_EDITOR;
}
Top of Document
In init-gui-editors
sub init-gui-editors(Str:D @client-config-files, Str:D $client-config-path,
&gen-configs:(Str:D, Str:D --> Bool:D),
&check:(Str:D @cfg-files, Str:D $config --> Bool:D)
--> Bool:D) is export
...
...
...
@GUIEDITORS = Editors.parse(@editors-file.join("\x0A"), :enc('UTF-8'), :$actions).made;
@gui-editors = @GUIEDITORS.grep( -> %l { %l«type» eq 'config-line' } ).map: -> %ln { %ln«value»; };
@default-editors = @GUIEDITORS.grep( -> %l { %l«type» eq 'editor-to-use' } ).map: -> %ln { %ln«value»; };
if @default-editors > 1 {
$*ERR.say: "Error: file $editor-config/editors is miss configured more than one editor defined should be 0 or 1";
}
@override-gui_editor = @GUIEDITORS.grep( -> %l { %l«type» eq 'override-gui_editor' } ).map: -> %ln { %ln«value»; };
if @override-gui_editor > 1 {
my Int:D $elems = @override-gui_editor.elems;
$*ERR.say: qq[Make up your mind only one "override GUI_EDITOR" is required, you supplied $elems are you insane???];
$override-GUI_EDITOR = True;
} elsif @override-gui_editor == 1 {
$override-GUI_EDITOR = True;
}
if @gui-editors {
#@gui-editors.raku.say;
for @gui-editors -> $geditor {
if !@guieditors.grep: { $geditor } {
my Str $guieditor = $geditor;
$guieditor .=trim;
@guieditors.append($guieditor);
}
}
}
if $override-GUI_EDITOR && @default-editors {
$editor = @default-editors[@default-editors - 1];
}elsif %*ENV<GUI_EDITOR>:exists {
my Str $guieditor = ~%*ENV<GUI_EDITOR>;
if ! @guieditors.grep( { $_ eq $guieditor.IO.basename } ) {
@guieditors.prepend($guieditor.IO.basename);
}
} elsif $editor-guessed && @default-editors {
$editor = @default-editors[@default-editors - 1];
}
Top of Document
$editor
The editor the user has chosen.
# the editor to use #
my Str:D $editor = '';
sub editor( --> Str:D) is export {
return $editor;
}
edit-configs()
A function to open the users configuration files in their chosen editor.
sub edit-configs() returns Bool:D is export {
if $editor {
my $option = '';
my @args;
my $edbase = $editor.IO.basename;
if $edbase eq 'gvim' {
$option = '-p';
@args.append('-p');
}
for @config-files -> $file {
if $file eq 'editors' {
@args.append("$editor-config/$file");
} else {
@args.append("$client-config/$file");
}
}
my $proc = run($editor, |@args);
return $proc.exitcode == 0 || $proc.exitcode == -1;
} else {
$*ERR.say: "no editor found please set GUI_EDITOR, VISUAL or EDITOR to your preferred editor.";
$*ERR.say: "e.g. export GUI_EDITOR=/usr/bin/gvim";
$*ERR.say: "or set editor in the $editor-config/editors file this can be done with the set editor command.";
$*ERR.say: qq[NB: the editor will be set by first checking GUI_EDITOR then VISUAL then EDITOR and
finally editor in the config file so GUI_EDITOR will win over all.
Unless you supply the "override GUI_EDITOR" directive in the $editor-config/editors file
and also supplied the "editor := <editor>" directive];
return False;
}
}
Top of Document
Editor functions
list-editors(…)
List all known GUI Editors, flagging the selected editor with '*' note if none is flagged either $editor
is set to a non GUI Editor or $editor
is set to the empty string.
sub list-editors(Str:D $prefix,
Bool:D $colour,
Bool:D $syntax,
Int:D $page-length,
Regex:D $pattern --> Bool) is export
editors-stats(…)
Show the values of some editors parameters.
sub editors-stats(Str:D $prefix,
Bool:D $colour,
Bool:D $syntax,
Int:D $page-length,
Regex:D $pattern --> Bool) is export
Top of Document
BadEditor
BadEditor
is an Exception class for the GUI::Editors
module.
class BadEditor is Exception is export {
has Str:D $.msg = 'Error: bad editor specified';
method message( --> Str:D) {
$!msg;
}
}
set-editor(…)
A function to set the editor of choice.
sub set-editor(Str:D $editor, Str $comment = Str --> Bool:D) is export
NB: this will still be overridden by %*ENV«GUI_EDITOR»
unless you set override GUI_EDITOR.
add-gui-editor(…)
Add an editor to the list of known GUI Editors.
sub add-gui-editor(Str:D $editor, Str $comment = Str --> Bool:D) is export
NB: please make sure it really is a GUI Editor otherwise this module will not work correctly. You are completely free to set the chosen editor to what ever you like.
set-override-GUI_EDITOR(…)
Set or unset the override GUI_EDITOR flag.
sub set-override-GUI_EDITOR(Bool:D $value, Str $comment = Str --> Bool:D) is export
If set then the file always wins else %*ENV«GUI_EDITOR»
always wins if set.
Top of Document
backup-editors(…)
Backup the editors file.
sub backup-editors(Bool:D $use-windows-formatting --> Bool) is export
NB: if $use-windows-formatting is true or the program is running on windows then .
will become ·
and :
will become .
, this is to avoid problems with the special meaning of :
on windows.
Top of Document
restore-editors(…)
Restore the editors file from a backup.
sub restore-editors(IO::Path $restore-from --> Bool) is export
If $restore-from
is relative and not found from the current directory $editor-config/$restore-from
will be tried.
list-editors-backups(…)
List all the available backups in the $editor-config
.
sub list-editors-backups(Str:D $prefix,
Bool:D $colour is copy,
Bool:D $syntax,
Regex:D $pattern,
Int:D $page-length --> Bool:D) is export
Where
$prefix
a filter only files starting with this are included in the result.
$colour
colour the output.
$syntax
syntax highlight the results colour on steroids.
$pattern
a regex to filter the results by only files matching this will be included in the results.
$page-length
set the length of the pages before it repeats the header.
Top of Document
Presents a menu so you can choose which backup to restore from.
sub backups-menu-restore-editors(Bool:D $colour,
Bool:D $syntax,
Str:D $message = "" --> Bool:D) is export
Top of Document
edit-files(…)
Edit arbitrary files using chosen editor.
sub edit-files(Str:D @files --> Bool:D) is export
Where
@files
a list of files to open in the chosen GUI editor.
Top of Document