-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7aa9c04
Showing
6 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
name: mclip | ||
on: push | ||
permissions: | ||
contents: write | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Build | ||
run: make build | ||
|
||
- name: Upload | ||
uses: actions/upload-artifact@v3 | ||
with: | ||
name: mclip | ||
path: build/mclip | ||
|
||
- name: Release | ||
uses: cycjimmy/semantic-release-action@v4 | ||
env: | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Prerequisites | ||
*.d | ||
|
||
# Object files | ||
*.o | ||
*.ko | ||
*.obj | ||
*.elf | ||
|
||
# Linker output | ||
*.ilk | ||
*.map | ||
*.exp | ||
|
||
# Precompiled Headers | ||
*.gch | ||
*.pch | ||
|
||
# Libraries | ||
*.lib | ||
*.a | ||
*.la | ||
*.lo | ||
|
||
# Shared objects (inc. Windows DLLs) | ||
*.dll | ||
*.so | ||
*.so.* | ||
*.dylib | ||
|
||
# Executables | ||
*.exe | ||
*.out | ||
*.app | ||
*.i*86 | ||
*.x86_64 | ||
*.hex | ||
|
||
# Debug files | ||
*.dSYM/ | ||
*.su | ||
*.idb | ||
*.pdb | ||
|
||
# Kernel Module Compile Results | ||
*.mod* | ||
*.cmd | ||
.tmp_versions/ | ||
modules.order | ||
Module.symvers | ||
Mkfile.old | ||
dkms.conf | ||
|
||
# Build dirs | ||
build/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
branches: | ||
- main | ||
plugins: | ||
- "@semantic-release/commit-analyzer" | ||
- "@semantic-release/release-notes-generator" | ||
- "@semantic-release/github" | ||
- "@semantic-release/changelog" | ||
tagFormat: ${version} | ||
dryRun: true | ||
ci: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
CC=gcc | ||
|
||
all: mclip | ||
|
||
clean: | ||
rm -rf build | ||
|
||
build: main.c | ||
mkdir -p build | ||
$(CC) -o build/mclip main.c | ||
|
||
install: build | ||
cp build/mclip /usr/bin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# :clipboard: mclip | ||
|
||
mclip (for "**M**emory **Clip**board") is a very simple Linux clipboard manager which stores its data inside a POSIX shared memory object. | ||
|
||
Today several clipboad tools exist but almost all of them require a specific dependency (X11, Wayland, Tmux, SSH, etc.). See for example the [Clipboard integration](https://neovim.io/doc/user/provider.html#provider-clipboard) page in the Neovim documentation. | ||
|
||
mclip is a tiny binary which only depends on low level Linux system functions like [`shm_open`](https://man7.org/linux/man-pages/man3/shm_open.3.html) and [`mmap`](https://man7.org/linux/man-pages/man2/mmap.2.html). So it should be usable in very basic environments. | ||
|
||
## Install | ||
|
||
## Usage | ||
|
||
This section explains how to use mclip in several tools. | ||
|
||
- [CLI](#cli) | ||
- [Neovim](#neovim) | ||
- [Zellij](#zellij) | ||
|
||
### CLI | ||
|
||
Display the help. | ||
|
||
```bash | ||
clip --help | ||
Usage: mclip [OPTION] | ||
|
||
Clipboard which stores its data inside shared memory. | ||
|
||
h-, --help read text from standard input and write it into the clipboard shared memory (default). | ||
i-, --in read text from standard input and write it into the clipboard shared memory (default). | ||
o-, --out print the content of the clipboard shared memory. | ||
``` | ||
|
||
To save text into the clipboard just enter it through stdin. | ||
|
||
```bash | ||
# Using a pipe | ||
$ echo "Hello world!" | mclip | ||
|
||
# Entering characters with the keyboard (press Ctrl+D to finish your input) | ||
$ mclip | ||
I can | ||
enter | ||
text | ||
on | ||
several | ||
lines | ||
<Ctrl+D> | ||
``` | ||
|
||
You can finally output the content of the clipboard. | ||
|
||
```bash | ||
$ mclip -o | ||
Hello world! | ||
``` | ||
|
||
### Neovim | ||
|
||
[Neovim](https://neovim.io) provides a [Clipboard integration](https://neovim.io/doc/user/provider.html#provider-clipboard) which allows to provide any clipboard tool. | ||
|
||
You can configure mclip as the Neovim clipboard tool using the following Lua configuration object. | ||
|
||
```lua | ||
vim.g.clipboard = { | ||
name = "mclip", | ||
copy = { | ||
["+"] = "mclip", | ||
["*"] = "mclip", | ||
}, | ||
paste = { | ||
["+"] = "mclip -o", | ||
["*"] = "mclip -o", | ||
}, | ||
cache_enabled = 1, | ||
} | ||
``` | ||
|
||
## Zellij | ||
|
||
TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
#define _GNU_SOURCE | ||
|
||
#include <sys/mman.h> | ||
#include <sys/stat.h> | ||
#include <fcntl.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <getopt.h> | ||
|
||
static const char SHARED_MEMORY_NAME[] = "/mclip"; | ||
|
||
/** | ||
* Read text from stdin and write into the shared memory. | ||
*/ | ||
void in() { | ||
void *addr = NULL; | ||
int fd = 0; | ||
|
||
fd = shm_open(SHARED_MEMORY_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); | ||
|
||
if (fd == -1) { | ||
fprintf(stderr, "shm_open() failed\n"); | ||
exit(1); | ||
} | ||
|
||
char characters[2] = {0}; | ||
|
||
int offset = 0; | ||
int nb_read = 0; | ||
int total_nb_read = 0; | ||
|
||
while(fgets(characters, sizeof(characters), stdin) != NULL) { | ||
nb_read = strlen(characters); | ||
total_nb_read = total_nb_read + nb_read; | ||
|
||
// Truncate the file to reserve space in it | ||
if(ftruncate(fd, total_nb_read) == -1) { | ||
fprintf(stderr, "ftruncate() failed\n"); | ||
exit(1); | ||
} | ||
|
||
if (addr != NULL) | ||
addr = mremap(addr, offset, total_nb_read, MREMAP_MAYMOVE); | ||
else | ||
addr = mmap(NULL, total_nb_read, PROT_WRITE, MAP_SHARED, fd, 0); | ||
|
||
sprintf(addr + offset, "%s", characters); | ||
|
||
offset = total_nb_read; | ||
} | ||
|
||
munmap(addr, total_nb_read); | ||
memset(characters, 0, sizeof(characters)); | ||
|
||
return; | ||
} | ||
|
||
/** | ||
* Read text from the shared memory and write it to stdout. | ||
*/ | ||
void out() { | ||
struct stat st; | ||
int fd = 0; | ||
void *addr = NULL; | ||
|
||
fd = shm_open(SHARED_MEMORY_NAME, O_RDONLY, S_IRUSR | S_IWUSR); | ||
|
||
if (fd == -1) { | ||
fprintf(stderr, "shm_open() failed\n"); | ||
exit(1); | ||
} | ||
|
||
fstat(fd, &st); | ||
|
||
// The shared memory is empty when it has just been initialized the first time with 'shm_open()'. | ||
if (st.st_size != 0) { | ||
addr = mmap(NULL, 1024, PROT_READ, MAP_SHARED, fd, 0); | ||
|
||
if (addr == MAP_FAILED) { | ||
fprintf(stderr, "mmap() failed\n"); | ||
exit(1); | ||
} | ||
} | ||
|
||
printf("%s", (char*) addr); | ||
} | ||
|
||
/** | ||
* Display the help. | ||
*/ | ||
void help() { | ||
printf("Usage: mclip [OPTION]\n\n"); | ||
printf("Clipboard which stores its data inside shared memory.\n\n"); | ||
printf("\t h-, --help \t read text from standard input and write it into the clipboard shared memory (default).\n"); | ||
printf("\t i-, --in \t read text from standard input and write it into the clipboard shared memory (default).\n"); | ||
printf("\t o-, --out \t print the content of the clipboard shared memory.\n\n"); | ||
} | ||
|
||
/** | ||
* Main entry of the mclip program. | ||
* | ||
* @param argc Number of arguments. | ||
* @param argv Array of arguments. | ||
*/ | ||
int main(int argc, char *argv[]) | ||
{ | ||
int option_help = 0; | ||
int option_in = 0; | ||
int option_out = 0; | ||
|
||
int c; | ||
int option_index = 0; | ||
|
||
static struct option long_options[] = { | ||
{"help", no_argument, 0, 'h'}, | ||
{"in", no_argument, 0, 'i'}, | ||
{"out", no_argument, 0, 'o'}, | ||
{0, 0, 0, 0} | ||
}; | ||
|
||
while(1) { | ||
c = getopt_long(argc, argv, "hio", long_options, &option_index); | ||
|
||
// No more options to read | ||
if (c == -1) | ||
break; | ||
|
||
switch(c) { | ||
|
||
// --help | ||
case 'h': | ||
option_help = 1; | ||
break; | ||
|
||
// --in | ||
case 'i': | ||
option_in = 1; | ||
break; | ||
|
||
// --out | ||
case 'o': | ||
option_out = 1; | ||
break; | ||
|
||
// Error encountered (i.e. bad option specified) | ||
case '?': | ||
exit(1); | ||
} | ||
|
||
} | ||
|
||
if (option_help == 1 && (option_in == 1 || option_out == 1)) { | ||
fprintf(stderr, "The '--help' option cannot be provided with the '--in' or '--out' option!\n"); | ||
return 1; | ||
} else if (option_help == 0 && option_in == 1 && option_out == 1) { | ||
fprintf(stderr, "The '--in' and '--out' options cannot be specified together!\n"); | ||
return 1; | ||
} else if (optind < argc) { | ||
fprintf(stderr, "Unknown argument speficied '%s'!\n", argv[optind]); | ||
return 1; | ||
} else if (option_help == 1) { | ||
help(); | ||
return 0; | ||
} | ||
|
||
if (option_in == 1 || (option_in == 0 && option_out == 0)) { | ||
in(); | ||
} else if (option_out == 1) { | ||
out(); | ||
} else { | ||
fprintf(stderr, "Unknown program state!\n"); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} |