wizard: actually write the output config
This commit is contained in:
parent
9101f4cce2
commit
43ec3ddbaf
|
@ -78,6 +78,7 @@ Mod3 { yylval.number = (1 << 5); return MODIFIER; }
|
||||||
Mod4 { yylval.number = (1 << 6); return MODIFIER; }
|
Mod4 { yylval.number = (1 << 6); return MODIFIER; }
|
||||||
Mod5 { yylval.number = (1 << 7); return MODIFIER; }
|
Mod5 { yylval.number = (1 << 7); return MODIFIER; }
|
||||||
Mode_switch { yylval.number = (1 << 8); return MODIFIER; }
|
Mode_switch { yylval.number = (1 << 8); return MODIFIER; }
|
||||||
|
$mod { yylval.number = (1 << 9); return TOKMODVAR; }
|
||||||
control { return TOKCONTROL; }
|
control { return TOKCONTROL; }
|
||||||
ctrl { return TOKCONTROL; }
|
ctrl { return TOKCONTROL; }
|
||||||
shift { return TOKSHIFT; }
|
shift { return TOKSHIFT; }
|
||||||
|
|
|
@ -89,6 +89,10 @@ static char *modifier_to_string(int modifiers) {
|
||||||
return strdup("Mod1");
|
return strdup("Mod1");
|
||||||
else if (modifiers == ((1 << 3) | (1 << 0)))
|
else if (modifiers == ((1 << 3) | (1 << 0)))
|
||||||
return strdup("Mod1+shift");
|
return strdup("Mod1+shift");
|
||||||
|
else if (modifiers == (1 << 9))
|
||||||
|
return strdup("$mod");
|
||||||
|
else if (modifiers == ((1 << 9) | (1 << 0)))
|
||||||
|
return strdup("$mod+shift");
|
||||||
else return strdup("UNKNOWN");
|
else return strdup("UNKNOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +109,7 @@ static char *modifier_to_string(int modifiers) {
|
||||||
%token <number>NUMBER "<number>"
|
%token <number>NUMBER "<number>"
|
||||||
%token <string>STR "<string>"
|
%token <string>STR "<string>"
|
||||||
%token TOKBINDCODE
|
%token TOKBINDCODE
|
||||||
|
%token TOKMODVAR "$mod"
|
||||||
%token MODIFIER "<modifier>"
|
%token MODIFIER "<modifier>"
|
||||||
%token TOKCONTROL "control"
|
%token TOKCONTROL "control"
|
||||||
%token TOKSHIFT "shift"
|
%token TOKSHIFT "shift"
|
||||||
|
@ -148,6 +153,7 @@ binding_modifiers:
|
||||||
|
|
||||||
binding_modifier:
|
binding_modifier:
|
||||||
MODIFIER { $<number>$ = $<number>1; }
|
MODIFIER { $<number>$ = $<number>1; }
|
||||||
|
| TOKMODVAR { $<number>$ = $<number>1; }
|
||||||
| TOKCONTROL { $<number>$ = (1 << 2); }
|
| TOKCONTROL { $<number>$ = (1 << 2); }
|
||||||
| TOKSHIFT { $<number>$ = (1 << 0); }
|
| TOKSHIFT { $<number>$ = (1 << 0); }
|
||||||
;
|
;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* vim:ts=8:expandtab
|
||||||
|
*
|
||||||
|
* i3 - an improved dynamic tiling window manager
|
||||||
|
*
|
||||||
|
* © 2009 Michael Stapelberg and contributors
|
||||||
|
*
|
||||||
|
* See file LICENSE for license information.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formats a message (payload) of the given size and type and sends it to i3 via
|
||||||
|
* the given socket file descriptor.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ipc_send_message(int sockfd, uint32_t message_size,
|
||||||
|
uint32_t message_type, uint8_t *payload) {
|
||||||
|
int buffer_size = strlen("i3-ipc") + sizeof(uint32_t) + sizeof(uint32_t) + message_size;
|
||||||
|
char msg[buffer_size];
|
||||||
|
char *walk = msg;
|
||||||
|
|
||||||
|
strcpy(walk, "i3-ipc");
|
||||||
|
walk += strlen("i3-ipc");
|
||||||
|
memcpy(walk, &message_size, sizeof(uint32_t));
|
||||||
|
walk += sizeof(uint32_t);
|
||||||
|
memcpy(walk, &message_type, sizeof(uint32_t));
|
||||||
|
walk += sizeof(uint32_t);
|
||||||
|
memcpy(walk, payload, message_size);
|
||||||
|
|
||||||
|
int sent_bytes = 0;
|
||||||
|
int bytes_to_go = buffer_size;
|
||||||
|
while (sent_bytes < bytes_to_go) {
|
||||||
|
int n = write(sockfd, msg + sent_bytes, bytes_to_go);
|
||||||
|
if (n == -1)
|
||||||
|
err(EXIT_FAILURE, "write() failed");
|
||||||
|
|
||||||
|
sent_bytes += n;
|
||||||
|
bytes_to_go -= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connects to the i3 IPC socket and returns the file descriptor for the
|
||||||
|
* socket. die()s if anything goes wrong.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int connect_ipc(char *socket_path) {
|
||||||
|
int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||||
|
if (sockfd == -1)
|
||||||
|
err(EXIT_FAILURE, "Could not create socket");
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
|
addr.sun_family = AF_LOCAL;
|
||||||
|
strcpy(addr.sun_path, socket_path);
|
||||||
|
if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
|
||||||
|
err(EXIT_FAILURE, "Could not connect to i3");
|
||||||
|
|
||||||
|
return sockfd;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef _IPC_H
|
||||||
|
#define _IPC_H
|
||||||
|
|
||||||
|
void ipc_send_message(int sockfd, uint32_t message_size,
|
||||||
|
uint32_t message_type, uint8_t *payload);
|
||||||
|
|
||||||
|
int connect_ipc(char *socket_path);
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,6 +18,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#include "xcb.h"
|
#include "xcb.h"
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
|
enum { STEP_WELCOME, STEP_GENERATE } current_step = STEP_WELCOME;
|
||||||
enum { MOD_ALT, MOD_SUPER } modifier = MOD_SUPER;
|
enum { MOD_ALT, MOD_SUPER } modifier = MOD_SUPER;
|
||||||
|
@ -52,7 +54,6 @@ static xcb_connection_t *conn;
|
||||||
static uint32_t font_id;
|
static uint32_t font_id;
|
||||||
static uint32_t font_bold_id;
|
static uint32_t font_bold_id;
|
||||||
static char *socket_path;
|
static char *socket_path;
|
||||||
static int sockfd;
|
|
||||||
static int font_height;
|
static int font_height;
|
||||||
static int font_bold_height;
|
static int font_bold_height;
|
||||||
static xcb_window_t win;
|
static xcb_window_t win;
|
||||||
|
@ -62,6 +63,7 @@ static xcb_key_symbols_t *symbols;
|
||||||
xcb_window_t root;
|
xcb_window_t root;
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
|
|
||||||
|
char *rewrite_binding(const char *bindingline);
|
||||||
static void finish();
|
static void finish();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -205,36 +207,82 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates the config file and tells i3 to reload.
|
||||||
|
*
|
||||||
|
*/
|
||||||
static void finish() {
|
static void finish() {
|
||||||
printf("finishing the wizard\n");
|
printf("creating \"%s\"...\n", config_path);
|
||||||
|
|
||||||
#if 0
|
if (!(dpy = XOpenDisplay(NULL)))
|
||||||
dpy = XOpenDisplay(NULL);
|
errx(1, "Could not connect to X11");
|
||||||
|
|
||||||
FILE *kc_config = fopen("../i3.config.kc", "r");
|
FILE *kc_config = fopen("../i3.config.kc", "r");
|
||||||
|
if (kc_config == NULL)
|
||||||
|
err(1, "Could not open input file \"%s\"", "../i3.config.kc");
|
||||||
|
|
||||||
|
FILE *ks_config = fopen(config_path, "w");
|
||||||
|
if (ks_config == NULL)
|
||||||
|
err(1, "Could not open output config file \"%s\"", config_path);
|
||||||
|
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
ssize_t read;
|
ssize_t read;
|
||||||
|
bool head_of_file = true;
|
||||||
|
|
||||||
|
/* write a header about auto-generation to the output file */
|
||||||
|
fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config);
|
||||||
|
fputs("# It will not be overwritten, so edit it as you like.\n", ks_config);
|
||||||
|
fputs("#\n", ks_config);
|
||||||
|
fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config);
|
||||||
|
fputs("# this file and re-run i3-config-wizard(1).\n", ks_config);
|
||||||
|
fputs("#\n", ks_config);
|
||||||
|
fputs("# See http://i3wm.org/docs/userguide.html\n", ks_config);
|
||||||
|
|
||||||
while ((read = getline(&line, &len, kc_config)) != -1) {
|
while ((read = getline(&line, &len, kc_config)) != -1) {
|
||||||
/* See if that line is interesting by skipping leading whitespaces,
|
/* skip the warning block at the beginning of the input file */
|
||||||
* then checking for 'bindcode' */
|
if (head_of_file &&
|
||||||
|
strncmp("# WARNING", line, strlen("# WARNING")) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
head_of_file = false;
|
||||||
|
|
||||||
|
/* Skip leading whitespace */
|
||||||
char *walk = line;
|
char *walk = line;
|
||||||
while (isspace(*walk) && walk < (line + len))
|
while (isspace(*walk) && walk < (line + len))
|
||||||
walk++;
|
walk++;
|
||||||
if (strncmp(walk, "bindcode", strlen("bindcode")) != 0)
|
|
||||||
continue;
|
|
||||||
char *result = rewrite_binding(walk);
|
|
||||||
printf("in: %s", walk);
|
|
||||||
printf("out: %s", result);
|
|
||||||
free(result);
|
|
||||||
|
|
||||||
|
/* Set the modifier the user chose */
|
||||||
|
if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) {
|
||||||
|
if (modifier == MOD_ALT)
|
||||||
|
fputs("set $mod Mod1\n", ks_config);
|
||||||
|
else fputs("set $mod Mod4\n", ks_config);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for 'bindcode'. If it’s not a bindcode line, we
|
||||||
|
* just copy it to the output file */
|
||||||
|
if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) {
|
||||||
|
fputs(line, ks_config);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
char *result = rewrite_binding(walk);
|
||||||
|
fputs(result, ks_config);
|
||||||
|
free(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sync to do our best in order to have the file really stored on disk */
|
||||||
|
fflush(ks_config);
|
||||||
|
fsync(fileno(ks_config));
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
fclose(kc_config);
|
fclose(kc_config);
|
||||||
|
fclose(ks_config);
|
||||||
|
|
||||||
exit(0);
|
/* tell i3 to reload the config file */
|
||||||
#endif
|
int sockfd = connect_ipc(socket_path);
|
||||||
|
ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload");
|
||||||
|
close(sockfd);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue