feat(NSPasteboard): uses backend when not ssh and on MacOS
This commit is contained in:
parent
565174c4b8
commit
9a377fa209
3 changed files with 68 additions and 7 deletions
|
|
@ -1,5 +1,10 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub const OSC52 = @import("Clip/OSC52.zig");
|
pub const OSC52 = @import("Clip/OSC52.zig");
|
||||||
// pub const PBCopy = if (@import("builtin").os.tag == .macos) @import("Clip/OSC52.zig") else null;
|
// Ideally we would make else be `@compileError` but that
|
||||||
|
// messes up with the interface checking
|
||||||
|
pub const NSPasteboard = if (builtin.target.os.tag == .macos) @import("Clip/NSPasteboard.zig") else void;
|
||||||
|
|
||||||
// I am not sure if this is super idiomatic Zig or if this is bad practice, but
|
// I am not sure if this is super idiomatic Zig or if this is bad practice, but
|
||||||
// by ensuring that all Clip backends implement the same methods, we are able
|
// by ensuring that all Clip backends implement the same methods, we are able
|
||||||
|
|
@ -16,8 +21,6 @@ fn assertFn(comptime T: type, comptime name: []const u8, comptime Sig: type) voi
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
_ = @import("Clip/NSPasteBoard.zig");
|
|
||||||
|
|
||||||
inline for (@typeInfo(@This()).@"struct".decls) |decl| {
|
inline for (@typeInfo(@This()).@"struct".decls) |decl| {
|
||||||
// Only grab types of structs
|
// Only grab types of structs
|
||||||
const T = @field(@This(), decl.name);
|
const T = @field(@This(), decl.name);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,44 @@
|
||||||
|
/// NSPasteBoard Clipboard backend
|
||||||
|
/// Fulfills `Clip` interface
|
||||||
|
pub const NSPasteboard = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
extern fn sendPB(text: [*:0]const u8) void;
|
extern fn sendPB(text: [*:0]const u8) void;
|
||||||
extern fn initPB() void;
|
extern fn initPB() void;
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
io: std.Io,
|
||||||
|
|
||||||
|
buffer: std.ArrayList(u8),
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator, io: std.Io, buf_size: usize) !NSPasteboard {
|
||||||
|
return .{
|
||||||
|
.alloc = alloc,
|
||||||
|
.io = io,
|
||||||
|
.buffer = try std.ArrayList(u8).initCapacity(alloc, buf_size),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free(self: *NSPasteboard) void {
|
||||||
|
self.buffer.clearAndFree(self.alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeCopyBuffer(self: *NSPasteboard, buf: []const u8) anyerror!void {
|
||||||
|
try self.buffer.appendSlice(self.alloc, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writePasteboard(self: *NSPasteboard) anyerror!void {
|
||||||
|
// Null Terminate string for C function Call
|
||||||
|
if (self.buffer.items[self.buffer.items.len - 1] == '\n') {
|
||||||
|
self.buffer.items[self.buffer.items.len - 1] = '\x00';
|
||||||
|
} else {
|
||||||
|
try self.buffer.append(self.alloc, '\x00');
|
||||||
|
}
|
||||||
|
initPB();
|
||||||
|
sendPB(@ptrCast(self.buffer.items.ptr));
|
||||||
|
}
|
||||||
|
|
||||||
test "objc bridge" {
|
test "objc bridge" {
|
||||||
initPB();
|
initPB();
|
||||||
sendPB("test_string");
|
sendPB("test_string");
|
||||||
|
|
@ -15,4 +51,3 @@ test "objc bridge" {
|
||||||
|
|
||||||
try std.testing.expectEqualStrings("test_string", std.mem.trim(u8, result.stdout, "\n"));
|
try std.testing.expectEqualStrings("test_string", std.mem.trim(u8, result.stdout, "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
27
src/main.zig
27
src/main.zig
|
|
@ -1,4 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const os = builtin.target.os.tag;
|
||||||
const File = std.Io.File;
|
const File = std.Io.File;
|
||||||
const Clip = @import("Clip.zig");
|
const Clip = @import("Clip.zig");
|
||||||
|
|
||||||
|
|
@ -13,10 +16,30 @@ pub fn main(init: std.process.Init) !void {
|
||||||
|
|
||||||
// We want to avoid doing as many allocations as possible so having raw
|
// We want to avoid doing as many allocations as possible so having raw
|
||||||
// pages with it being larger should be totally fine
|
// pages with it being larger should be totally fine
|
||||||
var clip = try Clip.OSC52.init(std.heap.page_allocator, init.io, std.heap.pageSize());
|
const alloc = std.heap.page_allocator;
|
||||||
defer clip.free();
|
const size = std.heap.pageSize();
|
||||||
|
|
||||||
|
const is_ssh = init.environ_map.get("SSH_CONNECTION") != null or
|
||||||
|
init.environ_map.get("SSH_CLIENT") != null or
|
||||||
|
init.environ_map.get("SSH_TTY") != null;
|
||||||
|
|
||||||
|
// This can be cleaned up
|
||||||
|
if (is_ssh) {
|
||||||
|
var clip = try Clip.OSC52.init(alloc, io, size);
|
||||||
|
defer clip.free();
|
||||||
try run(io, &clip);
|
try run(io, &clip);
|
||||||
|
} else {
|
||||||
|
if (comptime os == .macos) {
|
||||||
|
var clip = try Clip.NSPasteboard.init(alloc, io, size);
|
||||||
|
defer clip.free();
|
||||||
|
try run(io, &clip);
|
||||||
|
} else {
|
||||||
|
// No Linux Clipboards yet
|
||||||
|
var clip = try Clip.OSC52.init(alloc, io, size);
|
||||||
|
defer clip.free();
|
||||||
|
try run(io, &clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(io: std.Io, clip: anytype) !void {
|
pub fn run(io: std.Io, clip: anytype) !void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue