2020-09-06 11:32:08 +02:00
;; tinmop: an humble gemini and pleroma client
2020-05-08 15:45:43 +02:00
;; Copyright (C) 2020 cage
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program.
;; If not, see [[http://www.gnu.org/licenses/][http://www.gnu.org/licenses/]].
( in-package :main )
2020-09-06 14:42:16 +02:00
( defparameter *time* 0.0 )
( defparameter *ticks* 0 )
2020-05-08 15:45:43 +02:00
( define-constant +dt+ ( / 1 +fps+ ) :test #' = )
( defun incf-dt ( )
2020-09-06 14:42:16 +02:00
( incf *time* +dt+ ) )
( defun incf-ticks ( )
( incf *ticks* ) )
2020-05-08 15:45:43 +02:00
( defun setup-bindings ( )
" This is where an UI event is bound to a function the event nil is
2021-01-13 17:28:23 +01:00
the event that is fired when no input from user ( key pressed mouse
2020-05-08 15:45:43 +02:00
etc. ) happened "
( windows:with-croatoan-window ( croatoan-window specials:*main-window* )
( bind croatoan-window
:resize
( lambda ( w event )
( declare ( ignore w event ) )
( windows:refresh-config-all )
( windows:draw-all ) ) )
( bind croatoan-window
t
( lambda ( w event )
( declare ( ignore w ) )
( incf-dt )
( handler-bind ( ( conditions:command-not-found
( lambda ( e )
( invoke-restart 'command-window:print-error e ) ) ) )
( command-window:manage-event event ) ) ) )
;; this is the main thread
( bind croatoan-window
nil
( lambda ( w e )
( declare ( ignore w e ) )
( incf-dt )
2020-09-06 14:42:16 +02:00
( incf-ticks )
2020-12-31 11:38:37 +01:00
( scheduled-events:run-scheduled-events *ticks* )
2020-12-31 11:36:34 +01:00
( when ( not ( program-events:stop-event-dispatching-p ) )
( program-events:dispatch-program-events ) )
2020-05-08 15:45:43 +02:00
( windows:calculate-all +dt+ ) ) ) ) )
( defun init-i18n ( )
"Initialize i18n machinery"
( handler-bind ( ( error
( lambda ( e )
( declare ( ignore e ) )
( invoke-restart 'cl-i18n:return-empty-translation-table ) ) ) )
( setf cl-i18n:*translation-file-root* +catalog-dir+ )
( cl-i18n:load-language +text-domain+ :locale ( cl-i18n:find-locale ) ) ) )
( defun init-db ( )
"Initialize the database"
( db-utils:with-ready-database ( :connect t )
( db:purge-history ) ) )
( defun change-folder ( )
"Change folder, used in requests of a command line switch"
( let ( ( refresh-event ( make-instance 'program-events:refresh-thread-windows-event
:new-folder command-line:*start-folder* ) )
( folder-exists-p ( db:folder-exists-p command-line:*start-folder* ) ) )
2020-05-30 09:53:12 +02:00
( if folder-exists-p
( program-events:push-event refresh-event )
( ui:error-message ( format nil
( _ "Folder ~s does not exists" )
command-line:*start-folder* ) ) ) ) )
2020-05-08 15:45:43 +02:00
( defun change-timeline ( )
"Change timeline, used in requests of a command line switch"
( let* ( ( refresh-event ( make-instance 'program-events:refresh-thread-windows-event
:new-timeline command-line:*start-timeline* ) ) )
( program-events:push-event refresh-event ) ) )
2020-05-18 19:16:52 +02:00
( defun reset-timeline-pagination ( )
( ui:reset-timeline-pagination ) )
2020-06-27 22:43:13 +02:00
( defun load-gemini-url ( url )
2020-06-28 12:36:59 +02:00
( let* ( ( event ( make-instance 'program-events:gemini-request-event
2020-06-27 22:43:13 +02:00
:url url ) ) )
2020-06-28 12:36:59 +02:00
( program-events:push-event event ) ) )
2020-06-27 22:43:13 +02:00
2020-05-16 13:45:07 +02:00
( defun load-configuration-files ( )
2021-01-13 17:28:23 +01:00
( handler-case
( swconf:load-config-file swconf:+shared-conf-filename+ )
( error ( e )
( format *error-output* "~a~%" e )
( os-utils:exit-program 1 ) ) )
( handler-bind ( ( error
#' ( lambda ( e )
( format *error-output*
( _ "Non fatal error~%~a~%Tinmop will add an empty file for you. This file will be enough to use the program as a gemini client but to connect to pleroma the file must be properly filled.~%Consult the manpage ~a(1) for more details" )
e
+program-name+ )
( invoke-restart 'res:create-empty-in-home ) ) ) )
( swconf:load-config-file swconf:+conf-filename+ ) ) )
2020-05-16 13:45:07 +02:00
2020-05-08 15:45:43 +02:00
( defun init ( )
"Initialize the program"
2021-01-13 17:28:23 +01:00
;; (res:init)
;; (load-configuration-files)
;; (init-db)
2020-07-08 18:34:48 +02:00
( gemini-client:init-default-gemini-theme )
2020-05-08 15:45:43 +02:00
( db-utils:with-ready-database ( :connect nil )
2020-12-29 19:14:18 +01:00
( complete:initialize-complete-username-cache )
2020-05-08 15:45:43 +02:00
( modules:load-module +starting-init-file+ )
;; init main window for first...
( main-window:init )
( keybindings-window:init )
( command-window:init )
( thread-window:init )
;; the size of message and tag window depends from the sizes of
;; thread-window and command window, so the first two must be
;; initialized after the latter
( message-window:init )
( tags-window:init )
( conversations-window:init )
( setup-bindings )
;; ... and init-keyboard-mapping-for last
( keybindings:init-keyboard-mapping )
( ui:focus-to-thread-window )
;; now init the client
( client:init )
( client:authorize )
2020-06-23 15:51:43 +02:00
( if command-line:*gemini-url*
2020-06-27 22:43:13 +02:00
( load-gemini-url command-line:*gemini-url* )
2020-06-23 15:51:43 +02:00
( progn
2020-12-31 15:35:12 +01:00
( when command-line:*module-file*
( modules:load-module command-line:*module-file* ) )
2020-06-23 15:51:43 +02:00
( let ( ( program-events:*process-events-immediately* t ) )
( when command-line:*start-timeline*
( change-timeline ) )
( when command-line:*start-folder*
( change-folder ) ) )
( when command-line:*reset-timeline-pagination*
( reset-timeline-pagination ) )
( when command-line:*update-timeline*
( ui:update-current-timeline ) )
( when command-line:*check-follow-requests*
( ui:start-follow-request-processing ) ) ) ) ) )
2020-05-08 15:45:43 +02:00
( defun run ( )
( windows:with-croatoan-window ( croatoan-window specials:*main-window* )
( setf ( frame-rate croatoan-window ) +fps+ )
( db-utils:with-ready-database ( :connect nil )
( unwind-protect
( progn
( hooks:run-hooks 'hooks:*before-main-loop* )
( run-event-loop croatoan-window ) )
( end-screen ) ) ) ) )
( defun load-script-file ( )
2020-09-05 17:02:00 +02:00
"Load (execute) a lisp file used in requests of a command line switch"
2020-05-08 15:45:43 +02:00
( setf program-events:*process-events-immediately* t )
2020-05-16 13:45:07 +02:00
( load-configuration-files )
2020-05-08 15:45:43 +02:00
( init-db )
( db-utils:with-ready-database ( :connect nil )
( client:init )
( client:authorize )
( load command-line:*script-file* :verbose nil :print nil ) ) )
( defun main ( )
"The entry point function of the program"
( init-i18n )
2021-01-13 17:28:23 +01:00
( res:init )
( load-configuration-files )
( init-db )
2020-05-08 15:45:43 +02:00
( command-line:manage-opts )
( if command-line:*script-file*
( load-script-file )
( let ( ( croatoan::*debugger-hook* #' ( lambda ( c h )
( declare ( ignore h ) )
( end-screen )
( print c ) ) ) )
( init )
( run ) ) ) )