11//! Handle requests from neovim and manage dev workflow
2- use anyhow:: { bail, Context , Result } ;
32mod requests;
43pub mod state;
54
@@ -8,55 +7,71 @@ pub use requests::*;
87#[ cfg( feature = "daemon" ) ]
98pub use state:: DaemonState ;
109
10+ #[ cfg( feature = "lua" ) ]
11+ use crate :: util:: mlua:: LuaExtension ;
12+
13+ #[ cfg( feature = "lua" ) ]
14+ use mlua:: prelude:: * ;
15+
16+ #[ cfg( feature = "daemon" ) ]
17+ use anyhow:: Result ;
18+
1119pub const DAEMON_SOCKET_PATH : & str = "/tmp/xcodebase-daemon.socket" ;
1220pub const DAEMON_BINARY : & str =
1321 "/Users/tami5/repos/neovim/xcodebase.nvim/target/debug/xcodebase-daemon" ;
1422
1523/// Representation of daemon
16- pub struct Daemon {
17- #[ cfg( feature = "daemon" ) ]
18- pub state : std:: sync:: Arc < tokio:: sync:: Mutex < state:: DaemonStateData > > ,
19- #[ cfg( feature = "daemon" ) ]
20- pub listener : tokio:: net:: UnixListener ,
24+ pub struct Daemon ;
25+
26+ /// Requirement for daemon actions
27+ #[ cfg( feature = "daemon" ) ]
28+ #[ async_trait:: async_trait]
29+ pub trait DaemonRequestHandler < T > {
30+ async fn handle ( & self , state : DaemonState ) -> Result < ( ) > ;
31+ fn parse ( args : Vec < & str > ) -> Result < T > ;
2132}
2233
23- impl Daemon {
24- #[ cfg( feature = "daemon" ) ]
25- pub fn new ( ) -> Self {
26- Self {
27- state : Default :: default ( ) ,
28- listener : tokio:: net:: UnixListener :: bind ( DAEMON_SOCKET_PATH ) . unwrap ( ) ,
29- }
30- }
34+ /// Representations of all the supported daemon requests
35+ #[ derive( Debug ) ]
36+ pub enum DaemonRequest {
37+ Build ( Build ) ,
38+ Run ( Run ) ,
39+ RenameFile ( RenameFile ) ,
40+ Register ( Register ) ,
41+ Drop ( Drop ) ,
42+ }
3143
32- /// Spawn new instance of the server via running binaray is a child process
33- pub fn spawn ( ) -> Result < ( ) > {
34- std:: process:: Command :: new ( DAEMON_BINARY )
35- . spawn ( )
36- . context ( "Unable to start background instance using daemon binaray" )
37- . map ( |_| ( ) )
44+ #[ cfg( feature = "daemon" ) ]
45+ impl DaemonRequest {
46+ /// Handle daemon request
47+ pub async fn handle ( & self , state : DaemonState ) -> Result < ( ) > {
48+ match self {
49+ DaemonRequest :: Build ( c) => c. handle ( state) . await ,
50+ DaemonRequest :: Run ( c) => c. handle ( state) . await ,
51+ DaemonRequest :: RenameFile ( c) => c. handle ( state) . await ,
52+ DaemonRequest :: Register ( c) => c. handle ( state) . await ,
53+ DaemonRequest :: Drop ( c) => c. handle ( state) . await ,
54+ }
3855 }
3956
40- /// Pass args to running daemon
41- pub fn execute ( args : & [ & str ] ) -> Result < ( ) > {
42- use std:: io:: Write ;
43- match std:: os:: unix:: net:: UnixStream :: connect ( DAEMON_SOCKET_PATH ) {
44- Ok ( mut stream) => {
45- stream. write_all ( args. join ( " " ) . as_str ( ) . as_ref ( ) ) ?;
46- stream. flush ( ) . context ( "Fail to flush stream!" )
47- }
48- Err ( e) => bail ! ( "Fail to execute {:#?}: {e}" , args) ,
49- }
57+ /// Parse [`super::Daemon`] request from string
58+ pub fn parse ( str : & str ) -> Result < Self > {
59+ let mut args = str. split ( " " ) . collect :: < Vec < & str > > ( ) ;
60+ Ok ( match args. remove ( 0 ) {
61+ Build :: KEY => Self :: Build ( Build :: parse ( args) ?) ,
62+ Run :: KEY => Self :: Run ( Run :: parse ( args) ?) ,
63+ RenameFile :: KEY => Self :: RenameFile ( RenameFile :: parse ( args) ?) ,
64+ Register :: KEY => Self :: Register ( Register :: parse ( args) ?) ,
65+ Drop :: KEY => Self :: Drop ( Drop :: parse ( args) ?) ,
66+ cmd => anyhow:: bail!( "Unknown command messsage: {cmd}" ) ,
67+ } )
5068 }
5169}
5270
53- #[ cfg( feature = "lua" ) ]
54- use crate :: util:: mlua:: LuaExtension ;
55-
5671#[ cfg( feature = "lua" ) ]
5772impl Daemon {
5873 /// Representation of daemon table in lua
59- pub fn lua ( lua : & mlua:: Lua ) -> mlua :: Result < mlua :: Table > {
74+ pub fn lua ( lua : & mlua:: Lua ) -> LuaResult < LuaTable > {
6075 let table = lua. create_table ( ) ?;
6176 table. set ( "is_running" , lua. create_function ( Self :: is_running) ?) ?;
6277 table. set ( "ensure" , lua. create_function ( Self :: ensure) ?) ?;
@@ -66,22 +81,37 @@ impl Daemon {
6681 }
6782
6883 /// Check if Daemon is running
69- pub fn is_running ( _: & mlua:: Lua , _: ( ) ) -> mlua :: Result < bool > {
84+ pub fn is_running ( _: & mlua:: Lua , _: ( ) ) -> LuaResult < bool > {
7085 match std:: os:: unix:: net:: UnixStream :: connect ( DAEMON_SOCKET_PATH ) {
7186 Ok ( stream) => Ok ( stream. shutdown ( std:: net:: Shutdown :: Both ) . ok ( ) . is_some ( ) ) ,
7287 Err ( _) => Ok ( false ) ,
7388 }
7489 }
7590
7691 /// Ensure that daemon is currently running in background
77- pub fn ensure ( lua : & mlua:: Lua , _: ( ) ) -> mlua :: Result < bool > {
92+ pub fn ensure ( lua : & mlua:: Lua , _: ( ) ) -> LuaResult < bool > {
7893 if Self :: is_running ( lua, ( ) ) . unwrap ( ) {
7994 Ok ( false )
80- } else if Self :: spawn ( ) . is_ok ( ) {
95+ } else if std :: process :: Command :: new ( DAEMON_BINARY ) . spawn ( ) . is_ok ( ) {
8196 lua. info ( "Spawned Background Server" ) ?;
8297 Ok ( true )
8398 } else {
8499 panic ! ( "Unable to spawn background server" ) ;
85100 }
86101 }
102+
103+ /// Pass args to running daemon
104+ pub fn execute ( args : & [ & str ] ) -> LuaResult < ( ) > {
105+ use std:: io:: Write ;
106+ match std:: os:: unix:: net:: UnixStream :: connect ( DAEMON_SOCKET_PATH ) {
107+ Ok ( mut stream) => {
108+ stream. write_all ( args. join ( " " ) . as_str ( ) . as_ref ( ) ) ?;
109+ stream. flush ( ) . map_err ( mlua:: Error :: external)
110+ }
111+ Err ( e) => Err ( mlua:: Error :: external ( format ! (
112+ "Fail to execute {:#?}: {e}" ,
113+ args
114+ ) ) ) ,
115+ }
116+ }
87117}
0 commit comments