GUI::Editors
GUI::Editors
Table of Contents
NAME
GUI::Editors
AUTHOR
Francis Grizzly Smit ([email protected])
VERSION
0.1.0
TITLE
GUI::Editors
SUBTITLE
A Raku module for managing the users GUI Editor preferences in a variety of programs.
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.
@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;
}
grammar Editors & action class EditorsActions
grammar Editors 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* $$ }
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> || <path> <editor-name> }
regex comment { <-[\n]>* }
regex path { <lead-in> <path-segments>? }
regex lead-in { [ '/' | '~' | '~/' ] }
regex path-segments { <path-segment> [ '/' <path-segment> ]* '/' }
token path-segment { [ <with-space-in-it> || <with-other-stuff> ] }
token with-space-in-it { \w+ [ ' ' \w+ ]* }
token with-other-stuff { <start-other-stuff> <tail-other-stuff>* }
token start-other-stuff { \w+ }
token tail-other-stuff { <other-stuff>+ <tails-tail>? }
token tails-tail { \w+ }
token other-stuff { [ '-' || '+' || ':' || '@' || '=' || ',' || '&' || '%' || '.' ] }
token editor-name { <with-other-stuff> }
}
class EditorsActions is export {
...
...
...
method TOP($made) {
my @top = $made<line>Ā».made;
$made.make: @top;
}
} # class EditorsActions #
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 export {
regex TOP { ^ \h* 'editor' \h* ':'? '=' \h* <editor> \h* [ '#' <comment> \h* ]? $ }
regex editor { <editor-name> || <path> <editor-name> }
regex comment { <-[\n]>* }
regex path { <lead-in> <path-segments>? }
regex lead-in { [ '/' | '~' | '~/' ] }
regex path-segments { <path-segment> [ '/' <path-segment> ]* '/' }
token path-segment { [ <with-space-in-it> || <with-other-stuff> ] }
token with-space-in-it { \w+ [ ' ' \w+ ]* }
token with-other-stuff { <start-other-stuff> <tail-other-stuff>* }
token start-other-stuff { \w+ }
token tail-other-stuff { <other-stuff>+ <tails-tail>? }
token tails-tail { \w+ }
token other-stuff { [ '-' || '+' || ':' || '@' || '=' || ',' || '&' || '%' || '.' ] }
token editor-name { <with-other-stuff> }
}
class EditorLineActions is export {
#token other-stuff { [ '-' || '+' || ':' || '@' || '=' || ',' || '%' || '.' ] }
method other-stuff($/) {
my $other-stuff = ~$/;
make $other-stuff;
}
...
...
...
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 #
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 #
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;
}
@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;
}
@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;
}
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 [email protected]: { $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];
}
$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;
}
}
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(Bool:D $colour is copy, Bool:D $syntax --> Bool) is export
list-editors-file(ā¦)
List all GUI Editors in the configuration file.
sub list-editors-file(Bool:D $colour is copy, Bool:D $syntax --> Bool) is export
editors-stats(ā¦)
Show the values of some editors parameters.
sub editors-stats(Bool:D $colour is copy, Bool:D $syntax --> Bool) is export
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.
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 B<<.
will become Ā·
> and :
will become .
, this is to avoid problems with the special meaning of :
on windows.
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(Bool:D $colour is copy, Bool:D $syntax --> True) is export
backups-menu-restore(ā¦)
Presents a menu so you can choose which backup to restore from.
sub backups-menu-restore(Bool:D $colour, Bool:D $syntax,
Str:D $message = "" --> Bool:D) is export
Where:
$colour
ifTrue
represents the menu in colours.$syntax
ifTrue
represents the menu in colours.for now $syntax just does the same as
colour
, but in future it will lead to a more complex formatting.uses the
Gzz::Text::Utils::menu(ā¦)
, which uses theGzz::Text::Utils::dropdown(ā¦)
function for colour and syntax.
edit-files(ā¦)
Edit arbitrary files using chosen editor.
sub edit-files(Str:D @files --> Bool:D) is export