Add quit function to api, update README and example_config

This commit is contained in:
Seaotatop 2023-06-21 17:36:51 -05:00
parent c46159c77a
commit 8c054e17ba
8 changed files with 121 additions and 131 deletions

View file

@ -77,7 +77,7 @@ It is *highly* recommended to use the [Lua language server](https://github.com/L
Install the [Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) plugin, then go into its settings and add the absolute(?) path to the [`api/lua`](api/lua) directory to Workspace: Library. Install the [Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) plugin, then go into its settings and add the absolute(?) path to the [`api/lua`](api/lua) directory to Workspace: Library.
#### For Neovim: #### For Neovim:
Pass Pass this table into your Lua language server settings:
```lua ```lua
Lua = { Lua = {
workspace = { workspace = {
@ -87,28 +87,18 @@ Lua = {
} }
} }
``` ```
into your Lua language server settings.
Doc website soon:tm: Doc website soon:tm:
## Controls ## Controls
The following controls are currently hardcoded: The following controls are currently hardcoded:
- `Esc`: Stop Pinnacle
- `Ctrl + Left Mouse`: Move a window - `Ctrl + Left Mouse`: Move a window
- `Ctrl + Right Mouse`: Resize a window - `Ctrl + Right Mouse`: Resize a window
The following controls are set in the [`example_config`](api/lua/example_config.lua): You can find the rest of the controls in the [`example_config`](api/lua/example_config.lua).
- `Ctrl + Alt + C`: Close the currently focused window
- `Ctrl + Alt + Space`: Toggle "floating" for the currently focused window
- `Ctrl + Return`: Open Alacritty
- `Ctrl + 1`: Open Kitty
- `Ctrl + 2`: Open Foot
- `Ctrl + 3`: Open Nautilus
"Floating" is in quotes because while windows do currently tile themselves, tiled ones can still be moved just like a floating window. Toggling to and from floating will retile all tiled windows.
The only layout currently is a master stack with the master on the left side.
## A Small Note ## A Small Note
This is currently just a summer project I'm working on, but I hope that I can work on it enough that it becomes somewhat usable! If development slows down during the rest of the year, it's because :star:university:star:. This is currently just a summer project I'm working on, but I hope that I can work on it enough that it becomes somewhat usable! If development slows down during the rest of the year, it's because :star:university:star:.
Also the only layout is kinda wonk right now if you close all but one window

View file

@ -1,10 +1,16 @@
require("pinnacle").setup(function(pinnacle) require("pinnacle").setup(function(pinnacle)
local input = pinnacle.input local input = pinnacle.input --Key and mouse binds
local client = pinnacle.client local client = pinnacle.client --Window management
local keys = pinnacle.keys local process = pinnacle.process -- Process spawning
local process = pinnacle.process
input.keybind({ "Alt", "Ctrl" }, keys.c, client.close_window) -- Every key supported by xkbcommon.
-- Support for just putting in a string of a key is intended.
local keys = input.keys
-- Keybinds ----------------------------------------------------------------------
input.keybind({ "Ctrl", "Alt" }, keys.c, client.close_window)
-- NOTE: In tiled mode you can still move stuff around as if it's floating. Actual tiling is TODO
input.keybind({ "Ctrl", "Alt" }, keys.space, client.toggle_floating) input.keybind({ "Ctrl", "Alt" }, keys.space, client.toggle_floating)
input.keybind({ "Ctrl" }, keys.Return, function() input.keybind({ "Ctrl" }, keys.Return, function()

View file

@ -1,4 +1,6 @@
local M = {} local M = {
keys = require("keys"),
}
---Set a keybind. If called on an already existing keybind, it gets replaced. ---Set a keybind. If called on an already existing keybind, it gets replaced.
---@param key Keys The key for the keybind. NOTE: uppercase and lowercase characters are considered different. ---@param key Keys The key for the keybind. NOTE: uppercase and lowercase characters are considered different.

View file

@ -43,10 +43,14 @@ end
local pinnacle = { local pinnacle = {
input = require("input"), input = require("input"),
client = require("client"), client = require("client"),
keys = require("keys"),
process = require("process"), process = require("process"),
} }
---Quit Pinnacle.
function pinnacle.quit()
SendMsg("Quit")
end
---Configure Pinnacle. You should put mostly eveything into the config_func to avoid invalid state. ---Configure Pinnacle. You should put mostly eveything into the config_func to avoid invalid state.
---The function takes one argument: the Pinnacle table, which is how you'll access all of the available config options. ---The function takes one argument: the Pinnacle table, which is how you'll access all of the available config options.
---@param config_func fun(pinnacle: Pinnacle) ---@param config_func fun(pinnacle: Pinnacle)

View file

@ -66,7 +66,6 @@ impl PinnacleSocketSource {
} }
} }
#[must_use]
pub fn send_to_client( pub fn send_to_client(
stream: &mut UnixStream, stream: &mut UnixStream,
msg: &OutgoingMsg, msg: &OutgoingMsg,

View file

@ -41,6 +41,10 @@ pub enum Msg {
#[serde(default)] #[serde(default)]
callback_id: Option<CallbackId>, callback_id: Option<CallbackId>,
}, },
// Pinnacle management
/// Quit the compositor.
Quit,
} }
#[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)] #[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]

View file

@ -228,17 +228,6 @@ impl<B: Backend> State<B> {
{ {
return FilterResult::Intercept(*callback_id); return FilterResult::Intercept(*callback_id);
} }
match keysym.modified_sym() {
keysyms::KEY_L => return FilterResult::Intercept(100),
keysyms::KEY_K => return FilterResult::Intercept(200),
keysyms::KEY_J => return FilterResult::Intercept(300),
keysyms::KEY_H => return FilterResult::Intercept(400),
keysyms::KEY_Escape => {
state.loop_signal.stop();
return FilterResult::Intercept(0);
}
_ => {}
}
} }
if keysym.modified_sym() == keysyms::KEY_Control_L { if keysym.modified_sym() == keysyms::KEY_Control_L {
@ -259,34 +248,19 @@ impl<B: Backend> State<B> {
self.move_mode = move_mode; self.move_mode = move_mode;
let program = match action { if let Some(callback_id) = action {
Some(100) => "alacritty", if let Some(stream) = self.api_state.stream.as_ref() {
Some(200) => "nautilus", if let Err(err) = crate::api::send_to_client(
Some(300) => "kitty", &mut stream.lock().unwrap(),
Some(400) => "foot", &OutgoingMsg::CallCallback {
Some(callback_id) => { callback_id: CallbackId(callback_id),
if let Some(stream) = self.api_state.stream.as_mut() { args: None,
if let Err(err) = crate::api::send_to_client( },
&mut self.api_state.stream.as_ref().unwrap().lock().unwrap(), ) {
&OutgoingMsg::CallCallback { // TODO: print error
callback_id: CallbackId(callback_id),
args: None,
},
) {
// TODO: print error
}
} }
return;
} }
None => return, }
};
tracing::info!("Spawning {}", program);
std::process::Command::new(program)
.env("WAYLAND_DISPLAY", self.socket_name.clone())
.spawn()
.unwrap();
} }
} }

View file

@ -118,6 +118,7 @@ impl<B: Backend> State<B> {
let (tx_channel, rx_channel) = calloop::channel::channel::<Msg>(); let (tx_channel, rx_channel) = calloop::channel::channel::<Msg>();
loop_handle.insert_source(rx_channel, |msg, _, data| match msg { loop_handle.insert_source(rx_channel, |msg, _, data| match msg {
Event::Msg(msg) => { Event::Msg(msg) => {
// TODO: move this into its own function
match msg { match msg {
Msg::SetKeybind { Msg::SetKeybind {
key, key,
@ -162,6 +163,8 @@ impl<B: Backend> State<B> {
.stdin(if callback_id.is_some() { .stdin(if callback_id.is_some() {
Stdio::piped() Stdio::piped()
} else { } else {
// piping to null because foot won't open without a callback_id
// otherwise
Stdio::null() Stdio::null()
}) })
.stdout(if callback_id.is_some() { .stdout(if callback_id.is_some() {
@ -180,81 +183,84 @@ impl<B: Backend> State<B> {
// TODO: find a way to make this hellish code look better, deal with unwraps // TODO: find a way to make this hellish code look better, deal with unwraps
if let Some(callback_id) = callback_id { if let Some(callback_id) = callback_id {
let stdout = child.stdout.take().unwrap(); let stdout = child.stdout.take();
let stderr = child.stderr.take().unwrap(); let stderr = child.stderr.take();
let stream = data.state.api_state.stream.as_ref().unwrap().clone(); let stream_out = data.state.api_state.stream.as_ref().unwrap().clone();
// data.state let stream_err = stream_out.clone();
// .api_state let stream_exit = stream_out.clone();
// .stream
// .replace(stream.try_clone().unwrap()); if let Some(stdout) = stdout {
let stream2 = stream.clone(); std::thread::spawn(move || {
let stream3 = stream.clone(); // TODO: maybe find a way to make this async?
std::thread::spawn(move || { let mut reader = BufReader::new(stdout);
// TODO: maybe make this not a thread? loop {
let mut reader = BufReader::new(stdout); let mut buf = String::new();
loop { match reader.read_line(&mut buf) {
let mut buf = String::new(); Ok(0) => break, // stream closed
match reader.read_line(&mut buf) { Ok(_) => {
Ok(0) => break, // EOF let mut stream = stream_out.lock().unwrap();
Ok(_) => { crate::api::send_to_client(
let mut stream = stream.lock().unwrap(); &mut stream,
crate::api::send_to_client( &OutgoingMsg::CallCallback {
&mut stream, callback_id,
&OutgoingMsg::CallCallback { args: Some(Args::Spawn {
callback_id, stdout: Some(
args: Some(Args::Spawn { buf.trim_end_matches('\n')
stdout: Some( .to_string(),
buf.trim_end_matches('\n').to_string(), ),
), stderr: None,
stderr: None, exit_code: None,
exit_code: None, exit_msg: None,
exit_msg: None, }),
}), },
}, )
) .unwrap();
.unwrap(); }
} Err(err) => {
Err(err) => { tracing::error!("child read err: {err}");
tracing::error!("child read err: {err}"); break;
break; }
} }
} }
} });
}); }
std::thread::spawn(move || { if let Some(stderr) = stderr {
let mut reader = BufReader::new(stderr); std::thread::spawn(move || {
loop { let mut reader = BufReader::new(stderr);
let mut buf = String::new(); loop {
match reader.read_line(&mut buf) { let mut buf = String::new();
Ok(0) => break, // EOF match reader.read_line(&mut buf) {
Ok(_) => { Ok(0) => break, // stream closed
let mut stream = stream2.lock().unwrap(); Ok(_) => {
crate::api::send_to_client( let mut stream = stream_err.lock().unwrap();
&mut stream, crate::api::send_to_client(
&OutgoingMsg::CallCallback { &mut stream,
callback_id, &OutgoingMsg::CallCallback {
args: Some(Args::Spawn { callback_id,
stdout: None, args: Some(Args::Spawn {
stderr: Some( stdout: None,
buf.trim_end_matches('\n').to_string(), stderr: Some(
), buf.trim_end_matches('\n')
exit_code: None, .to_string(),
exit_msg: None, ),
}), exit_code: None,
}, exit_msg: None,
) }),
.unwrap(); },
} )
Err(err) => { .unwrap();
tracing::error!("child read err: {err}"); }
break; Err(err) => {
tracing::error!("child read err: {err}");
break;
}
} }
} }
} });
}); }
std::thread::spawn(move || match child.wait() { std::thread::spawn(move || match child.wait() {
Ok(exit_status) => { Ok(exit_status) => {
let mut stream = stream3.lock().unwrap(); let mut stream = stream_exit.lock().unwrap();
crate::api::send_to_client( crate::api::send_to_client(
&mut stream, &mut stream,
&OutgoingMsg::CallCallback { &OutgoingMsg::CallCallback {
@ -275,9 +281,14 @@ impl<B: Backend> State<B> {
}); });
} }
} }
Msg::SpawnShell {
// TODO: add the rest shell,
_ => (), command,
callback_id,
} => todo!(),
Msg::Quit => {
data.state.loop_signal.stop();
}
}; };
} }
Event::Closed => todo!(), Event::Closed => todo!(),