Commits

Herbert Breunung  committed 7db8906

building up basic structure

  • Participants
  • Parent commits 31b399e
  • Branches sp3

Comments (0)

Files changed (24)

File lib/Kephra/API.pm

+use v5.12;
+use warnings;
+
+package Kephra::API;
+
+use Kephra::API::KeyMap;
+
+1;

File lib/Kephra/API/Command.pm

Empty file added.

File lib/Kephra/API/DocStash.pm

Empty file added.

File lib/Kephra/API/Event.pm

Empty file added.

File lib/Kephra/API/GuiBuilder.pm

Empty file added.

File lib/Kephra/API/KeyMap.pm

 
 sub register_keys {
 	my ($keys, $map) = @_;
-	return Kephra::Log::warning("got no hashref") unless ref $keys eq ref {};
+	#return Kephra::Log::warning("got no hashref") unless ref $keys eq ref {};
 	$map = $main_map unless defined $map;
 	for my $cmd (keys %$keys) {
 		$definition{$map}{ $cmd } = $keys->{$cmd};
 		my $code = keycode_from_definition( $keys->{$cmd} );
 		unless (exists $code{$map}{ $code }) { $code{$map}{ $code } = $cmd }
 		else {
-			Kephra::Log::warning("$cmd tried to register the already taken keycode $code");
+			#Kephra::Log::warning("$cmd tried to register the already taken keycode $code");
 		}
 	}
 }
 
 sub keycode_is_registered {
 	my ($code, $map) = @_;
-	Kephra::Log::warning('got no key code') unless $code;
+	#Kephra::Log::warning('got no key code') unless $code;
 	$map = $main_map unless defined $map;
 	return 1 if defined $code{$map}{$code} and $code{$map}{$code}
 }
 
 sub cmd_from_keycode {
 	my ($code, $map) = @_;
-	Kephra::Log::warning('got no key code') unless $code;
+	#Kephra::Log::warning('got no key code') unless $code;
 	$map = $main_map unless defined $map;
 	$code{$map}{$code};
 }
 sub keycode_from_definition {
 	my $def = shift;
 	$def =~ tr/ 	//d;
-	Kephra::Log::warning('got no key definition') unless $def;
+	#Kephra::Log::warning('got no key definition') unless $def;
 
 	my @key = split '\+', $def;           # only + can combine key in definition
 	my $code = length($key[-1]) == 1 ? ord uc $key[-1] : $key_value{ $key[-1] };
-	Kephra::Log::warning('don\'t know this key '.$key[-1]) unless $code;
+	#Kephra::Log::warning('don\'t know this key '.$key[-1]) unless $code;
 
 	$code += $mod_key_value{ shift(@key) } while @key > 1;
-	Kephra::Log::warning("got unknown key definition $def") unless $code;
+	#Kephra::Log::warning("got unknown key definition $def") unless $code;
 	return $code;
 }
 
 sub keycode_from_event {
 	my $event = shift;
-	Kephra::Log::warning ("got no event, but $event") unless ref $event and $event->isa('Wx::Event');
+	#Kephra::Log::warning ("got no event, but $event") unless ref $event and $event->isa('Wx::Event');
 	my $code = $event->GetKeyCode;
 	$code += $mod_key_value{'shift'} if $event->ShiftDown;
 	$code += $mod_key_value{'ctrl'} if $event->ControlDown;
 
 sub react_on_event {
 	my ($event, $map) = @_;
-	Kephra::Log::warning ("got no event, but $event") unless ref $event and $event->isa('Wx::Event');
+	#Kephra::Log::warning ("got no event, but $event") unless ref $event and $event->isa('Wx::Event');
 	$map = $main_map unless defined $map;
 	my $key = keycode_from_event($event);
-	Kephra::API::log("pressed key $key inside the ".(caller)[0]);
+	#Kephra::API::log("pressed key $key inside the ".(caller)[0]);
 	if (keycode_is_registered($key)){
 			my $cmd = cmd_from_code($key);
-			Kephra::API::log("run command: $cmd");
-			Kephra::API::Command::run( $cmd );
+			#Kephra::API::log("run command: $cmd");
+			#Kephra::API::Command::run( $cmd );
 	}
 	else {$event->Skip}
 }

File lib/Kephra/API/Macro.pm

Empty file added.

File lib/Kephra/API/Plugin.pm

Empty file added.

File lib/Kephra/API/Sandrum.pm

Empty file added.

File lib/Kephra/App.pm

 
 package Kephra::App;
 use base qw(Wx::App);
-use Kephra::App::Editor;
+use Kephra::API;
+use Kephra::App::Window;
 
 sub OnInit {
 	my $app   = shift;
-	my $frame = Wx::Frame->new( undef, &Wx::wxDEFAULT, 'Kephra SP3');
-	my $ed = Kephra::App::Editor->new($frame, -1);
-	Wx::Window::SetFocus( $ed );
+	my $frame = Kephra::App::Window->new($Kephra::NAME.' SP3 '.$Kephra::VERSION);
 
 	$frame->Show(1);
 	$app->SetTopWindow($frame);
 	1;
 }
 
+sub close_save {
+	#Kephra::File::close_all();
+	close_raw();
+}
+
+sub close_raw  {
+	#my $win = Kephra::API::main_window()->destroy();
+}
+
+sub OnExit {
+	my $app = shift;
+	Wx::wxTheClipboard->Flush;
+	1;
+}
+
 1;

File lib/Kephra/App/Window.pm

+use v5.12;
+use warnings;
+use Wx;
+
+package Kephra::App::Window;
+use base qw(Wx::Frame);
+use Kephra::App::Editor;
+our $_ref;
+my $title_end = "$Kephra::NAME $Kephra::VERSION";
+
+
+sub new {
+	my( $class, $title ) = @_;
+	my( $self ) = $_ref = $class->SUPER::new (  undef, -1, $title, [-1,-1], [800,600] );
+	$self->SetIcon( Wx::GetWxPerlIcon() );
+	my $ed = Kephra::App::Editor->new($self, -1);
+
+	Wx::Window::SetFocus( $ed );
+	#Kephra::App::Focus::set($ed);
+
+	return $self;
+}
+
+sub close   { $_ref->Close() }
+sub destroy { $_ref->Destroy() }
+
+sub get_title { $_ref->GetTitle( )       }
+sub set_title { $_ref->SetTitle( $_[1] ) }
+sub refresh_title {
+	my $self = shift;
+	my $doc = Kephra::API::document();
+	return $self->set_title( $title_end ) unless defined $doc and $doc;
+
+	my $title = $doc->title;
+	$title .= ' ('.$doc->file_path.')' if $doc->file_path;
+	$self->set_title( $title . " - $title_end" );
+}
+
+sub toggle_fullscreen {
+	my ($self) = @_;
+	$self->{fullscreen} ^= 1;
+	$self->ShowFullScreen ( 
+		$self->{fullscreen}, 
+		&Wx::wxFULLSCREEN_NOCAPTION | &Wx::wxFULLSCREEN_NOBORDER
+	);
+}
+
+1;

File lib/Kephra/Config.pm

Empty file added.

File lib/Kephra/Document.pm

Empty file added.

File lib/Kephra/Edit.pm

Empty file added.

File lib/Kephra/File.pm

Empty file added.

File lib/Kephra/File/Local.pm

+use v5.12;
+use warnings;
+use Encode;
+use Encode::Guess;
+use Kephra::API;
+use Kephra::File;
+
+package Kephra::File::Local;
+
+
+sub read {
+	my $doc = shift;
+	my $file = Kephra::File::normalize_path( shift ) || $doc->file_path;
+	return Kephra::Log::warning("can't load nonexising file") unless $file and -e $file;
+	return Kephra::Log::warning("can't read $file") unless -r $file;
+	my $ed = $doc->editor->{ Kephra::API::docbar() };
+	CORE::open my $FH, '<', $file;
+	binmode($FH);
+	my $content = do { local $/; <$FH> };
+	if ($content) {
+
+		my @guesses = qw/utf-8 iso8859-1 latin1/;
+		my $guess = Encode::Guess::guess_encoding( $content, @guesses );
+		if ( ref($guess) and ref($guess) =~ m/^Encode::/ ) {
+			$doc->encoding( $guess->name );
+		} elsif ( $guess =~ m/utf8/ ) {
+			$doc->encoding( 'utf-8' );
+		} elsif ( $guess =~ m/or/ ) {
+			my @suggest_encodings = split /\sor\s/, "$guess";
+			$doc->encoding( $suggest_encodings[0] );
+		} else { $doc->encoding( 'utf-8' ) }
+		$content = Encode::decode( $doc->encoding,  $content );
+		#say $doc->encoding; 
+
+		$ed->SetText( $content );
+		$ed->SetSavePoint;
+	}
+}
+
+sub write {
+	my $doc = shift;
+	my $file = Kephra::File::normalize_path( shift ) || $doc->file_path;
+	return Kephra::Log::warning("need a file path") unless $file;
+	return Kephra::Log::warning("can't overwrite $file") if -e $file and not -w $file;
+	$doc->file_path($file) unless defined $doc->file_path and $doc->file_path eq $file;
+	my $ed = $doc->editor->{ Kephra::API::docbar() };
+	CORE::open my $FH, '> :raw :encoding('.$doc->encoding.')', $file;
+	print $FH $ed->GetText;
+	$ed->SetSavePoint;
+}
+
+
+1;

File lib/Kephra/Help.pm

Empty file added.

File lib/Kephra/Internals.pod

+=head1 API
+
+=head2 Kephra::API
+
+The module Kephra::API is the best starting point to understand the inner workings.
+It's one design goal and purpose of this file, because it naturally gives an
+overview of the most important functions and values and there origin. From here
+you can step to the other major interfaces that are included there with C<use>
+in the first lines.
+
+But more vitally it decouples many cross module calls and allows to change things
+under the hood during smaller release cycles. As long as the first version number
+(see L<Versioning>) does not change, nothing will be renamed or removed from the API.
+
+
+=head1 NAMESPACES
+
+If you want to leave the recommended ways as proposed by the API and call
+functions or data directly (or even better you want to help to develope Kephra) ...
+here is an overview to the Kephra namespace organisation.
+
+Please note that the shorter the name is (shorter namespace chain),
+the more internal and general purpose the module is owning that name.
+For instance Kephra::File::Local serves as specialized subtask of Kephra::File.
+
+
+* Kephra
+
+contains just the init process:
+setting dirs, loading libs, finding configs, start worker fork
+
+* Kephra::API
+
+interface to important internal functions all modules and plugins should use
+
+The modules in the Kephra::API::* namespace are services for a more sophisticated
+communication between the modules who do the real work.
+
+Kephra::API::Command
+
+Also sort of API but more complex. Contains every call the user is able to make.
+Needed to protocol each call for monitoring, macros and other introspection
+based functions. Also helps to make simple menu and toolbar definitions.
+They just need to be a list of CommandIDs.
+
+Kephra::API::KeyMap
+
+handles the mapping from key kommbo to the command it triggeres for any 
+App::Dialog and App::Part
+
+Kephra::API::Event
+
+
+* Kephra::App
+
+module that handles boot and shutdown sequence
+namespace of all the Wx-GUI-related stuff, all visible parts
+Kephra::App::* contains the more lower level stuff and 
+Kephra::App::*::* the higher level components
+
+* Kephra::App::Dialog
+
+all dialogs are called from here
+
+* Kephra::App::Part
+
+namespace of the great visual sections of the app
+
+=head2 Kephra::App::Focus
+
+keeps track in which App::Part the Focus wanders to make save way back if needed
+
+=over 4
+
+* Kephra::App::Panel
+
+wrapper around Wx::Panel + Wx::BoxSizer, helps not to deal with with sizers
+is a stepping stone to the GCL
+
+* Kephra::App::Window
+
+main frame/window and main layout of the app
+holds all the Kephra::App::Part s and Bars
+
+* Kephra::Config
+
+Interface to most not document related internally held data.
+We have a much broader understanding of configuration.
+Even Icons and localisation belong to it.
+Its all data which puts the app in the state it is.
+
+* Kephra::Document
+
+document properties, syntax modes
+
+* Kephra::Edit
+
+text processing
+
+* Kephra::Plugin
+
+plugin namespace
+Kephra::API::Plugin is the base class for all plugins
+
+=back
+
+=head1 Glossary
+
+=head2 App
+
+everything visible and GUI (Wx) related
+
+=head2 App::Part
+
+visual area dedicated for one purpose, editor is the most prominent,
+but ther are also FileBrowser, IOUnit and more
+
+=head2 Editor
+
+one widget for editing text
+
+=head2 Edit
+
+namespace for the actual editing operations
+
+=head2 Panel
+
+area to place widget on, can be under anything, even under each editor
+a Kephra::App::Panel is a helper class that manages its sizer
+(visibility and ordering of elements)
+
+=head1 Document
+
+=cut
+
+__END__
+
+our @needed_at_first = qw/App API/;
+our @starttime_loaded_modules = qw/
+	App App::Util API Config Config::Default Config::File
+	Document DocumentStash CommandList Edit EventTable 
+	File KeyMap PluginRegistrar SanddrumInterpreter Works/;
+our @runtime_loaded_namespaces =
+	qw/App::Dialog Config::Default/;
+
+our @command_modules = 
+	qw/App App::Panel::Editor App::Panel::FileBrowser App::Panel::IOUnit
+	App::Panel::OrgPad App::Panel::ProjectManager App::Panel::SratchSheet
+	App::Panel::TextLab App::Panel::TreeLib
+	CommandList Config 
+	Edit File EventTable KeyMap PluginRegistrar SanddrumInterpreter/;
+our @oop_interfaces = 
+	qw/App::Editor App::Panel App::Splitter App::SidePanelController 
+	   App::Bar::Document Document/;

File lib/Kephra/Log.pm

Empty file added.

File lib/Kephra/Philosophy.pod

+=head1 Kephra Philosophy
+
+=head2  Why Perl
+
+=over 4
+
+=item * flexible, human friendly syntax
+
+=item * has very good native Regex support
+
+=item * mature technology
+
+=item * CPAN
+
+=back
+
+=head2  What Part Of Perl We Use Or Avoid
+
+=head2  Principles
+
+=over 4
+
+=item * full intospection
+
+=item * parts serve metapurposes and work together
+
+=back
+
+=head2  Interdependency Of Core Modules
+
+=head2  Modules vs Objects
+
+=head2  Boot Stages
+
+Just using the fact that when modules are loded (after the fork)
+there main code (outside the sub) is run. At this time we create the
+basic command list and the definition which module gets which part of
+the global config (actual loading happens later).
+
+=head2  Worker Fork
+
+=cut

File lib/Kephra/Plugin/Demo.pm

+use strict;
+use warnings;
+
+package Kephra::Plugin::Tutorial;
+
+
+1;

File lib/Kephra/StyleGuide.pod

+=head1 Kephra Coding Style
+
+=head2 Technical Details
+
+    bracketing     = K & R
+    indention size = 4
+    use of tabs    = yes
+
+
+=head2 Organisation
+
+1 module - 1 namespace
+
+=head2 Naming
+
+We try to reuse same names for similar purposes,
+especially when its the same purpose through several modules,
+or the same data part through different structures.
+
+We also try to lean toward natural Perl names (eg 'sub' 'coderef', 'push').
+
+
+=head3 module/class Names
+
+titlecase / camelcase       ~~ LikeThis
+
+
+=head3 sub/method Names
+
+lowercase words separated by _ ~~ like_this
+
+routines only to be called inside a module start with one _
+avoid to call these from outside by all means
+
+create not make when we generate something
+
+=head3 Variable Names
+
+lowercase words separated by _ ~~ like_this
+We say active, no more current or recent.
+
+$self  reference of the class itself
+
+$ed    in most cases the active editor pane
+       (was renamed from $ep to prevent simple copy and paste of old code)
+
+$file  full file path, unless oyur specific like file_name, file_path etc.
+
+=head3 Command Names
+
+words separated by -
+
+=head3 Event Names
+
+words separated by .
+
+=head3 Key Definitions
+
+keys separated by +

File lib/Kephra/Versioning.pod

+=head1 Kephra Versioning Schema
+
+=head2 Goals
+
+=over 2
+
+=item * simple (as linear as possible - as a watch)
+
+=item * measures development status not time
+
+=item * no extras (Alpha, Beta, Release Candidate, Patchlevel)
+
+=back
+
+=head2 General Pattern
+
+  Revision . Stable . Testing . Development
+
+Trailing zeros can be omited - 0.5 is the same as 0.5.0.0
+
+=head3 Development
+
+Development number is changed after every important commit.
+Normally after every day of development.
+
+Development releases come with no warranty whatsoever.
+
+=head3 Testing
+
+Testing number is raised if a new feature of importance has to attract
+the attention of the testers.
+
+Testing releases come with all known bugs disabled (if possible).
+Interfaces glitches may occur.
+
+=head3 Stable
+
+Stable number goes up if several greater new features are in
+and all known bugs are out.
+If there are still bugs,
+they have to be disabled with the feature there are sitting on.
+
+Stable releases should have a polished interface and no bugs.
+If one appears in 0.3 it will be fixed ASAP with 0.3.0.1 a.s.o.
+
+During a time window before releasing a stable version,
+all new features will go into a new branch, which will become 0.3.1.
+The next testing should be released soon after the stable is out.
+
+=head3 Revision
+
+Has the word vision in it. When I got my initial vision we are at 1.0.
+If I have a new one after that or we change a fundamental technology
+there is gonna be a 2.0.
+
+Or in case we just want to break backward compatibility of the Kephra::API,
+it is a signal to all Plugin authors, they have to adapt.
+
+=head2 What Changed?
+
+We dropped the special patchlevel number.
+The version 0.3 Patchlevel 5 is now 0.3.0.5.

File lib/Kephra/Worker.pm

Empty file added.