Apply xresources, font2 (adds the ability to configure st via Xresources), solarized-both patches

This commit is contained in:
Sergey Silaev 2020-12-20 03:44:57 +03:00
parent fe24022e12
commit e7e76fc34d
5 changed files with 351 additions and 51 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
st
st.o
x.o
*.tar.gz

View file

@ -1,27 +1,29 @@
# st - simple terminal emulator for X
# Sergey's build of st - simple terminal emulator for X
This is my terminal which I use every day.
This is my terminal which I use every day and update from time to time.
+ Based on [st-0.8.4](https://st.suckless.org/)
+ Default font: [Droid Sans Mono Slashed for Powerline](https://github.com/powerline/fonts/tree/master/DroidSansMonoSlashed)
+ Default theme: [Solarized](https://ethanschoonover.com/solarized/)
+ Default theme: `Solarized Light` swap between light/dark with `F6`
+ Default font: `Monospace`
+ Default shell: `sh`
## Bindings
+ **Scrollback**: with `shift-↑/↓` or `shift-h/shift-j`
+ **Scrollback**: with `shift-↑/↓` or `ctrl+shift-h/ctrl+shift-j`
+ **Scrollback mouse**: `shift` while scrolling the mouse
+ **Change font size**:`ctrl+shift-↑/↓`
+ **Reset font size**: `ctrl+shifts-home` returns to default
+ **Copy/Paste text**: with `ctrl+shift-c`, `ctrl+shift+v` and `ctrl+shift-insert` or right mouse click
+ **Extract all visible URLs and present rofi/dmenu to select and open one**: ctrl+shift+U
+ **Copy/Paste text**: with `ctrl+shift-c`, `ctrl+shift+v`, `ctrl+shift-insert` and right mouse button2/button3 click
+ **Extract all visible URLs** and present rofi/dmenu to select and open one: `ctrl+shift+U`
## Requirements
+ `make` tool for building
+ `libXft` library for fonts drawing
+ `Xlib` header files for interacting with an X server
+ `libxft-bgra` libXft with BGRA glyph (color emoji) rendering & scaling pathes
+ `xurls` tool for extract urls from plain text
+ `Droid Sans Mono Slashed for Powerline` just default font, which you can change it in `config.h`
+ `ttf-joypixels` emoji as a Service (formerly EmojiOne)
## Patches
@ -30,6 +32,9 @@ This is my terminal which I use every day.
+ alpha
+ externalpipe
+ rightclickpaste
+ font2
+ xresources
+ solarized-both
## Simple installation
@ -38,3 +43,38 @@ git clone https://github.com/ssilaev/st
cd st
sudo make install
```
## Dynamic configuration thought Xresources
You can specify a font, color theme, alpha, and ximspot interval in .Xresources.
After applying new settings, need to update X server resources via xrdb utility `xrdb ~/.Xresources`.
Example:
```
st.alpha: 0.8
st.font: Droid Sans Mono Slashed for Powerline:pixelsize=16
st.shell: zsh
st.termname: st-256color
st.color0: #073642
st.color1: #dc322f
st.color2: #859900
st.color3: #b58900
st.color4: #268bd2
st.color5: #d33682
st.color6: #2aa198
st.color7: #eee8d5
st.color9: #cb4b16
st.color8: #fdf6e3
st.color10: #586e75
st.color11: #657b83
st.color12: #839496
st.color13: #6c71c4
st.color14: #93a1a1
st.color15: #fdf6e3
...
```
Full list of available variables you can check in `config.h`.

137
config.h
View file

@ -5,7 +5,11 @@
*
* font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html
*/
static char *font = "Droid Sans Mono Slashed for Powerline:pixelsize=16:antialias=true:autohint=true";
static char *font = "monospace:pixelsize=14:antialias=true:autohint=true";
/* Spare fonts */
static char *font2[] = {"JoyPixels:pixelsize=16:antialias=true:autohint=true"};
static int borderpx = 2;
/*
@ -16,7 +20,7 @@ static int borderpx = 2;
* 4: value of shell in /etc/passwd
* 5: value of shell in config.h
*/
static char *shell = "/bin/zsh";
static char *shell = "/bin/sh";
char *utmp = NULL;
/* scroll program: to enable use a string like "scroll" */
char *scroll = NULL;
@ -62,6 +66,13 @@ static double maxlatency = 33;
*/
static unsigned int blinktimeout = 800;
/*
* interval (in milliseconds) between each successive call to ximspot. This
* improves terminal performance while not reducing functionality to those
* whom need XIM support.
*/
int ximspot_update_interval = 1000;
/*
* thickness of underline and bar cursors
*/
@ -93,48 +104,69 @@ char *termname = "st-256color";
*/
unsigned int tabspaces = 8;
/* bg opacity */
float alpha = 0.8;
/* background opacity */
float alpha = 1.0;
/* Terminal colors (16 first used in escape sequence) */
static const char *colorname[] = {
/* 8 normal colors */
"black",
"red3",
"green3",
"yellow3",
"blue2",
"magenta3",
"cyan3",
"gray90",
/* 8 bright colors */
"gray50",
"red",
"green",
"yellow",
"#5c5cff",
"magenta",
"cyan",
"white",
/* solarized light */
"#eee8d5", /* 0: black */
"#dc322f", /* 1: red */
"#859900", /* 2: green */
"#b58900", /* 3: yellow */
"#268bd2", /* 4: blue */
"#d33682", /* 5: magenta */
"#2aa198", /* 6: cyan */
"#073642", /* 7: white */
"#fdf6e3", /* 8: brblack */
"#cb4b16", /* 9: brred */
"#93a1a1", /* 10: brgreen */
"#839496", /* 11: bryellow */
"#657b83", /* 12: brblue */
"#6c71c4", /* 13: brmagenta*/
"#586e75", /* 14: brcyan */
"#002b36", /* 15: brwhite */
};
[255] = 0,
/* Terminal colors for alternate (light) palette */
static const char *altcolorname[] = {
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
"#555555",
/* solarized dark */
"#073642", /* 0: black */
"#dc322f", /* 1: red */
"#859900", /* 2: green */
"#b58900", /* 3: yellow */
"#268bd2", /* 4: blue */
"#d33682", /* 5: magenta */
"#2aa198", /* 6: cyan */
"#eee8d5", /* 7: white */
"#002b36", /* 8: brblack */
"#cb4b16", /* 9: brred */
"#586e75", /* 10: brgreen */
"#657b83", /* 11: bryellow */
"#839496", /* 12: brblue */
"#6c71c4", /* 13: brmagenta*/
"#93a1a1", /* 14: brcyan */
"#fdf6e3", /* 15: brwhite */
};
/*
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
unsigned int defaultfg = 7;
unsigned int defaultbg = 0;
static unsigned int defaultcs = 256;
static unsigned int defaultrcs = 257;
unsigned int defaultfg = 12;
unsigned int defaultbg = 8;
static unsigned int defaultcs = 14;
static unsigned int defaultrcs = 15;
/*
* Colors used, when the specific fg == defaultfg. So in reverse mode this
* will reverse too. Another logic would only make the simple feature too
* complex.
*/
unsigned int defaultitalic = 7;
unsigned int defaultunderline = 7;
/*
* Default shape of cursor
* 2: Block ("")
@ -170,6 +202,44 @@ static unsigned int defaultattr = 11;
*/
static uint forcemousemod = ShiftMask;
/*
* Xresources preferences to load at startup
*/
ResourcePref resources[] = {
{ "font", STRING, &font },
{ "color0", STRING, &colorname[0] },
{ "color1", STRING, &colorname[1] },
{ "color2", STRING, &colorname[2] },
{ "color3", STRING, &colorname[3] },
{ "color4", STRING, &colorname[4] },
{ "color5", STRING, &colorname[5] },
{ "color6", STRING, &colorname[6] },
{ "color7", STRING, &colorname[7] },
{ "color8", STRING, &colorname[8] },
{ "color9", STRING, &colorname[9] },
{ "color10", STRING, &colorname[10] },
{ "color11", STRING, &colorname[11] },
{ "color12", STRING, &colorname[12] },
{ "color13", STRING, &colorname[13] },
{ "color14", STRING, &colorname[14] },
{ "color15", STRING, &colorname[15] },
{ "background", STRING, &colorname[256] },
{ "foreground", STRING, &colorname[257] },
{ "cursorColor", STRING, &colorname[258] },
{ "termname", STRING, &termname },
{ "shell", STRING, &shell },
{ "minlatency", INTEGER, &minlatency },
{ "maxlatency", INTEGER, &maxlatency },
{ "blinktimeout", INTEGER, &blinktimeout },
{ "bellvolume", INTEGER, &bellvolume },
{ "tabspaces", INTEGER, &tabspaces },
{ "borderpx", INTEGER, &borderpx },
{ "cwscale", FLOAT, &cwscale },
{ "chscale", FLOAT, &chscale },
{ "alpha", FLOAT, &alpha },
{ "ximspot_update_interval", INTEGER, &ximspot_update_interval },
};
static char *openurlcmd[] = { "/bin/zsh", "-c",
"xurls | rofi -dmenu -l 10 -columns 1 | xargs -r xdg-open",
"externalpipe", NULL };
@ -213,10 +283,11 @@ static Shortcut shortcuts[] = {
{ TERMMOD, XK_Insert, selpaste, {.i = 0} },
{ TERMMOD, XK_Num_Lock, numlock, {.i = 0} },
{ TERMMOD, XK_U, externalpipe, { .v = openurlcmd } },
{ TERMMOD, XK_K, kscrollup, {.i = -1} },
{ TERMMOD, XK_J, kscrolldown, {.i = -1} },
{ ShiftMask, XK_Up, kscrollup, {.i = -1} },
{ ShiftMask, XK_Down, kscrolldown, {.i = -1} },
{ ShiftMask, XK_K, kscrollup, {.i = -1} },
{ ShiftMask, XK_J, kscrolldown, {.i = -1} },
{ XK_ANY_MOD, XK_F6, swapcolors, {.i = 0} },
};
/*

1
st.h
View file

@ -130,6 +130,7 @@ extern wchar_t *worddelimiters;
extern int allowaltscreen;
extern int allowwindowops;
extern char *termname;
extern int usealtcolors;
extern unsigned int tabspaces;
extern unsigned int defaultfg;
extern unsigned int defaultbg;

207
x.c
View file

@ -14,6 +14,7 @@
#include <X11/keysym.h>
#include <X11/Xft/Xft.h>
#include <X11/XKBlib.h>
#include <X11/Xresource.h>
char *argv0;
#include "arg.h"
@ -45,6 +46,19 @@ typedef struct {
signed char appcursor; /* application cursor */
} Key;
/* Xresources preferences */
enum resource_type {
STRING = 0,
INTEGER = 1,
FLOAT = 2
};
typedef struct {
char *name;
enum resource_type type;
void *dst;
} ResourcePref;
/* X modifiers */
#define XK_ANY_MOD UINT_MAX
#define XK_NO_MOD 0
@ -55,6 +69,7 @@ static void clipcopy(const Arg *);
static void clippaste(const Arg *);
static void numlock(const Arg *);
static void selpaste(const Arg *);
static void swapcolors(const Arg *);
static void zoom(const Arg *);
static void zoomabs(const Arg *);
static void zoomreset(const Arg *);
@ -158,6 +173,8 @@ static void xhints(void);
static int xloadcolor(int, const char *, Color *);
static int xloadfont(Font *, FcPattern *);
static void xloadfonts(char *, double);
static int xloadsparefont(FcPattern *, int);
static void xloadsparefonts(void);
static void xunloadfont(Font *);
static void xunloadfonts(void);
static void xsetenv(void);
@ -256,6 +273,8 @@ static char *opt_title = NULL;
static int oldbutton = 3; /* button event on startup: 3 = release */
int usealtcolors = 0; /* 1 to use alternate palette */
void
clipcopy(const Arg *dummy)
{
@ -294,6 +313,14 @@ numlock(const Arg *dummy)
win.mode ^= MODE_NUMLOCK;
}
void
swapcolors(const Arg *dummy)
{
usealtcolors = !usealtcolors;
xloadcols();
redraw();
}
void
zoom(const Arg *arg)
{
@ -308,6 +335,7 @@ zoomabs(const Arg *arg)
{
xunloadfonts();
xloadfonts(usedfont, arg->f);
xloadsparefonts();
cresize(0, 0);
redraw();
xhints();
@ -703,7 +731,7 @@ brelease(XEvent *e)
if (mouseaction(e, 1))
return;
if (e->xbutton.button == Button3)
if (e->xbutton.button == Button3 | e->xbutton.button == Button2)
selpaste(NULL);
else if (e->xbutton.button == Button1)
mousesel(e, 1);
@ -762,6 +790,11 @@ sixd_to_16bit(int x)
return x == 0 ? 0 : 0x3737 + 0x2828 * x;
}
const char* getcolorname(int i)
{
return (usealtcolors) ? altcolorname[i] : colorname[i];
}
int
xloadcolor(int i, const char *name, Color *ncolor)
{
@ -780,7 +813,7 @@ xloadcolor(int i, const char *name, Color *ncolor)
return XftColorAllocValue(xw.dpy, xw.vis,
xw.cmap, &color, ncolor);
} else
name = colorname[i];
name = getcolorname(i);
}
return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
@ -803,8 +836,8 @@ xloadcols(void)
for (i = 0; i < dc.collen; i++)
if (!xloadcolor(i, NULL, &dc.col[i])) {
if (colorname[i])
die("could not allocate color '%s'\n", colorname[i]);
if (getcolorname(i))
die("could not allocate color '%s'\n", getcolorname(i));
else
die("could not allocate color %d\n", i);
}
@ -849,8 +882,8 @@ xclear(int x1, int y1, int x2, int y2)
void
xhints(void)
{
XClassHint class = {opt_name ? opt_name : termname,
opt_class ? opt_class : termname};
XClassHint class = {opt_name ? opt_name : "st",
opt_class ? opt_class : "St"};
XWMHints wm = {.flags = InputHint, .input = 1};
XSizeHints *sizeh;
@ -1040,6 +1073,101 @@ xloadfonts(char *fontstr, double fontsize)
FcPatternDestroy(pattern);
}
int
xloadsparefont(FcPattern *pattern, int flags)
{
FcPattern *match;
FcResult result;
match = FcFontMatch(NULL, pattern, &result);
if (!match) {
return 1;
}
if (!(frc[frclen].font = XftFontOpenPattern(xw.dpy, match))) {
FcPatternDestroy(match);
return 1;
}
frc[frclen].flags = flags;
/* Believe U+0000 glyph will present in each default font */
frc[frclen].unicodep = 0;
frclen++;
return 0;
}
void
xloadsparefonts(void)
{
FcPattern *pattern;
double sizeshift, fontval;
int fc;
char **fp;
if (frclen != 0)
die("can't embed spare fonts. cache isn't empty");
/* Calculate count of spare fonts */
fc = sizeof(font2) / sizeof(*font2);
if (fc == 0)
return;
/* Allocate memory for cache entries. */
if (frccap < 4 * fc) {
frccap += 4 * fc - frccap;
frc = xrealloc(frc, frccap * sizeof(Fontcache));
}
for (fp = font2; fp - font2 < fc; ++fp) {
if (**fp == '-')
pattern = XftXlfdParse(*fp, False, False);
else
pattern = FcNameParse((FcChar8 *)*fp);
if (!pattern)
die("can't open spare font %s\n", *fp);
if (defaultfontsize > 0) {
sizeshift = usedfontsize - defaultfontsize;
if (sizeshift != 0 &&
FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) ==
FcResultMatch) {
fontval += sizeshift;
FcPatternDel(pattern, FC_PIXEL_SIZE);
FcPatternDel(pattern, FC_SIZE);
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval);
}
}
FcPatternAddBool(pattern, FC_SCALABLE, 1);
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
XftDefaultSubstitute(xw.dpy, xw.scr, pattern);
if (xloadsparefont(pattern, FRC_NORMAL))
die("can't open spare font %s\n", *fp);
FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
if (xloadsparefont(pattern, FRC_ITALIC))
die("can't open spare font %s\n", *fp);
FcPatternDel(pattern, FC_WEIGHT);
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
if (xloadsparefont(pattern, FRC_ITALICBOLD))
die("can't open spare font %s\n", *fp);
FcPatternDel(pattern, FC_SLANT);
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
if (xloadsparefont(pattern, FRC_BOLD))
die("can't open spare font %s\n", *fp);
FcPatternDestroy(pattern);
}
}
void
xunloadfont(Font *f)
{
@ -1127,8 +1255,6 @@ xinit(int cols, int rows)
XWindowAttributes attr;
XVisualInfo vis;
if (!(xw.dpy = XOpenDisplay(NULL)))
die("can't open display\n");
xw.scr = XDefaultScreen(xw.dpy);
if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0)))) {
@ -1149,6 +1275,9 @@ xinit(int cols, int rows)
usedfont = (opt_font == NULL)? font : opt_font;
xloadfonts(usedfont, 0);
/* spare fonts */
xloadsparefonts();
/* colors */
xw.cmap = XCreateColormap(xw.dpy, parent, xw.vis, None);
xloadcols();
@ -1198,13 +1327,13 @@ xinit(int cols, int rows)
cursor = XCreateFontCursor(xw.dpy, mouseshape);
XDefineCursor(xw.dpy, xw.win, cursor);
if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
if (XParseColor(xw.dpy, xw.cmap, getcolorname(mousefg), &xmousefg) == 0) {
xmousefg.red = 0xffff;
xmousefg.green = 0xffff;
xmousefg.blue = 0xffff;
}
if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) {
if (XParseColor(xw.dpy, xw.cmap, getcolorname(mousebg), &xmousebg) == 0) {
xmousebg.red = 0x0000;
xmousebg.green = 0x0000;
xmousebg.blue = 0x0000;
@ -1993,6 +2122,59 @@ run(void)
}
}
int
resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
{
char **sdst = dst;
int *idst = dst;
float *fdst = dst;
char fullname[256];
char fullclass[256];
char *type;
XrmValue ret;
snprintf(fullname, sizeof(fullname), "%s.%s",
opt_name ? opt_name : "st", name);
snprintf(fullclass, sizeof(fullclass), "%s.%s",
opt_class ? opt_class : "St", name);
fullname[sizeof(fullname) - 1] = fullclass[sizeof(fullclass) - 1] = '\0';
XrmGetResource(db, fullname, fullclass, &type, &ret);
if (ret.addr == NULL || strncmp("String", type, 64))
return 1;
switch (rtype) {
case STRING:
*sdst = ret.addr;
break;
case INTEGER:
*idst = strtoul(ret.addr, NULL, 10);
break;
case FLOAT:
*fdst = strtof(ret.addr, NULL);
break;
}
return 0;
}
void
config_init(void)
{
char *resm;
XrmDatabase db;
ResourcePref *p;
XrmInitialize();
resm = XResourceManagerString(xw.dpy);
if (!resm)
return;
db = XrmGetStringDatabase(resm);
for (p = resources; p < resources + LEN(resources); p++)
resource_load(db, p->name, p->type, p->dst);
}
void
usage(void)
{
@ -2069,6 +2251,11 @@ run:
setlocale(LC_CTYPE, "");
XSetLocaleModifiers("");
if(!(xw.dpy = XOpenDisplay(NULL)))
die("Can't open display\n");
config_init();
cols = MAX(cols, 1);
rows = MAX(rows, 1);
tnew(cols, rows);