├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs ├── legacy ├── .gitignore ├── Cakefile ├── LICENSE ├── README.md ├── doc │ └── spec.md ├── lib │ ├── .gitignore │ └── .npmignore ├── package.json ├── src │ ├── cli.coffee │ └── index.coffee ├── test │ ├── default-config │ ├── test.coffee │ └── theme.json └── themes │ ├── alphare │ ├── archlinux │ ├── base16-tomorrow │ ├── debian │ ├── deep-purple │ ├── default │ ├── flat-gray │ ├── gruvbox │ ├── icelines │ ├── lime │ ├── mate │ ├── okraits │ ├── purple │ ├── seti │ ├── slate │ ├── solarized │ ├── tomorrow-night-80s │ └── ubuntu ├── src ├── main.rs ├── theme.rs └── writer.rs ├── test-resources ├── default-config ├── minimal-config ├── minimal-config-expected ├── missing-config ├── missing-config-expected └── test-theme.yaml └── themes ├── alphare ├── archlinux ├── base16-tomorrow ├── debian ├── deep-purple ├── default ├── flat-gray ├── gruvbox ├── icelines ├── lime ├── mate ├── oceanic-next ├── okraits ├── purple ├── seti ├── slate ├── solarized ├── tomorrow-night-80s └── ubuntu /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | lib-cov 3 | *.seed 4 | *.log 5 | *.csv 6 | *.dat 7 | *.out 8 | *.pid 9 | *.gz 10 | 11 | /target/ 12 | Cargo.lock 13 | **/*.rs.bk 14 | 15 | # legacy npm 16 | node_modules 17 | package-lock.json 18 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "i3-style" 3 | description = "Make your i3 config a little more stylish" 4 | version = "1.0.2" 5 | authors = ["Tony Crisci "] 6 | license = "BSD-2-Clause" 7 | repository = "https://github.com/acrisci/i3-style" 8 | build = "build.rs" 9 | exclude = ["legacy/*", "test-resources/*"] 10 | 11 | [dependencies] 12 | yaml-rust = "0.4" 13 | clap = "2.31.2" 14 | phf = "0.7.21" 15 | includedir = "0.4.0" 16 | colornamer = "0.1.0" 17 | regex = "1.0.0" 18 | lazy_static = "1.0.0" 19 | linked-hash-map = "0.5.1" 20 | 21 | [dev-dependencies] 22 | tempfile = "3.0.1" 23 | 24 | [build-dependencies] 25 | includedir_codegen = "0.4.0" 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Tony Crisci 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of the FreeBSD Project. 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i3-style 2 | 3 | Make your [i3](http://i3wm.org) config a little more stylish. 4 | 5 | ## About 6 | 7 | `i3-style` applies a theme to your i3 config file to change the colorscheme of the window decorations and the different parts of i3bar. It's designed especially for people who make frequent changes to their colorscheme to get things just right. 8 | 9 | * Easy to try out new themes right after you install. 10 | * Themes are easy to read, modify, and share. 11 | * Modifies your theme in place - extra template files are not needed. 12 | 13 | [Chat](https://discord.gg/UdbXHVX) 14 | 15 | ## Installing 16 | 17 | If you have a Rust toolchain available, you can install with Cargo: 18 | 19 | cargo install i3-style 20 | 21 | Otherwise, check the [releases](https://github.com/acrisci/i3-style/releases) page where I post precompiled binaries. 22 | 23 | ## Usage 24 | 25 | Just call `i3-style` with the name of the theme you want to try and where you want to write the config file to. i3-style will look for your config in the default place and apply the theme. 26 | 27 | i3-style solarized -o ~/.config/i3/config --reload 28 | 29 | Check the `themes` directory for the list of built-in themes. 30 | 31 | i3-style ~/.config/i3/solarized.yaml -o ~/.config/i3/config 32 | 33 | Just keep doing that until you get it perfect (which might be never). 34 | 35 | ## Send us themes! 36 | 37 | Do you have a cool colorscheme in your config file that you want to share with other people? i3-style can automatically convert it to a theme file: 38 | 39 | i3-style --to-theme ~/.config/i3/config -o my-theme.yaml 40 | 41 | If you have a new theme, or made an improvement to an existing theme, please make a pull request adding your theme to the `themes` directory! 42 | 43 | ## License 44 | 45 | This work is available under a FreeBSD License (see LICENSE). 46 | 47 | Copyright © 2013, Tony Crisci 48 | 49 | All rights reserved. 50 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate includedir_codegen; 2 | 3 | use includedir_codegen::Compression; 4 | 5 | fn main() { 6 | includedir_codegen::start("FILES") 7 | .dir("./themes", Compression::Gzip) 8 | .build("data.rs") 9 | .unwrap(); 10 | } 11 | -------------------------------------------------------------------------------- /legacy/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | lib-cov 3 | *.seed 4 | *.log 5 | *.csv 6 | *.dat 7 | *.out 8 | *.pid 9 | *.gz 10 | 11 | pids 12 | logs 13 | results 14 | 15 | npm-debug.log 16 | node_modules 17 | -------------------------------------------------------------------------------- /legacy/Cakefile: -------------------------------------------------------------------------------- 1 | files = [ 2 | 'lib' 3 | 'src' 4 | ] 5 | 6 | fs = require 'fs' 7 | {print} = require 'util' 8 | {spawn, exec} = require 'child_process' 9 | 10 | try 11 | which = require('which').sync 12 | catch err 13 | if process.platform.match(/^win/)? 14 | console.log 'WARNING: the which module is required for windows\ntry: npm install which' 15 | which = null 16 | 17 | bold = '\x1b[0;1m' 18 | green = '\x1b[0;32m' 19 | reset = '\x1b[0m' 20 | red = '\x1b[0;31m' 21 | 22 | task 'docs', 'generate documentation', -> docco() 23 | 24 | task 'build', 'compile source', -> build -> log ":)", green 25 | 26 | task 'watch', 'compile and watch', -> build true, -> log ":-)", green 27 | 28 | task 'test', 'run tests', -> build -> mocha -> log ":)", green 29 | 30 | task 'clean', 'clean generated files', -> clean -> log ";)", green 31 | 32 | 33 | walk = (dir, done) -> 34 | results = [] 35 | fs.readdir dir, (err, list) -> 36 | return done(err, []) if err 37 | pending = list.length 38 | return done(null, results) unless pending 39 | for name in list 40 | file = "#{dir}/#{name}" 41 | try 42 | stat = fs.statSync file 43 | catch err 44 | stat = null 45 | if stat?.isDirectory() 46 | walk file, (err, res) -> 47 | results.push name for name in res 48 | done(null, results) unless --pending 49 | else 50 | results.push file 51 | done(null, results) unless --pending 52 | 53 | log = (message, color, explanation) -> console.log color + message + reset + ' ' + (explanation or '') 54 | 55 | launch = (cmd, options=[], callback) -> 56 | cmd = which(cmd) if which 57 | app = spawn cmd, options 58 | app.stdout.pipe(process.stdout) 59 | app.stderr.pipe(process.stderr) 60 | app.on 'exit', (status) -> callback?() if status is 0 61 | 62 | build = (watch, callback) -> 63 | if typeof watch is 'function' 64 | callback = watch 65 | watch = false 66 | 67 | options = ['-c', '-b', '-o' ] 68 | options = options.concat files 69 | options.unshift '-w' if watch 70 | launch 'coffee', options, -> 71 | cliText = fs.readFileSync('./lib/cli.js').toString() 72 | cliText = "#!/usr/bin/env node\n#{cliText}" 73 | fs.writeFile './lib/cli.js', cliText, (err) -> 74 | throw err if err? 75 | fs.chmod './lib/cli.js', '0755', callback 76 | 77 | unlinkIfCoffeeFile = (file) -> 78 | if file.match /\.coffee$/ 79 | fs.unlink file.replace('src','lib').replace(/\.coffee$/, '.js'), -> 80 | true 81 | else false 82 | 83 | clean = (callback) -> 84 | try 85 | for file in files 86 | unless unlinkIfCoffeeFile file 87 | walk file, (err, results) -> 88 | for f in results 89 | unlinkIfCoffeeFile f 90 | 91 | callback?() 92 | catch err 93 | 94 | moduleExists = (name) -> 95 | try 96 | require name 97 | catch err 98 | log "#{name} required: npm install #{name}", red 99 | false 100 | 101 | 102 | mocha = (options, callback) -> 103 | #if moduleExists('mocha') 104 | if typeof options is 'function' 105 | callback = options 106 | options = [] 107 | # add coffee directive 108 | options.push '--compilers' 109 | options.push 'coffee:coffee-script/register' 110 | options.push '-C' 111 | 112 | launch 'mocha', options, callback 113 | 114 | docco = (callback) -> 115 | #if moduleExists('docco') 116 | walk 'src', (err, files) -> launch 'docco', files, callback 117 | 118 | -------------------------------------------------------------------------------- /legacy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Tony Crisci 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are those 25 | of the authors and should not be interpreted as representing official policies, 26 | either expressed or implied, of the FreeBSD Project. 27 | -------------------------------------------------------------------------------- /legacy/README.md: -------------------------------------------------------------------------------- 1 | # i3-style 2 | 3 | Make your [i3](http://i3wm.org) config a little more stylish. 4 | 5 | [![NPM](https://nodei.co/npm/i3-style.png?compact=true)](https://nodei.co/npm/i3-style/) 6 | 7 | [![NPM](https://nodei.co/npm-dl/i3-style.png?months=6)](https://nodei.co/npm/i3-style/) 8 | 9 | ## About 10 | 11 | `i3-style` applies a theme to your i3 config file to change the colorscheme of the window decorations and the different parts of i3bar. It's designed especially for people who make frequent changes to their colorscheme to get things just right. 12 | 13 | * Easy to try out new themes right after you install. 14 | * Themes are easy to read, modify, and share. 15 | * Modifies your theme in place - extra template files are not needed. 16 | 17 | For an overview of the capabilities of i3-style, see my [blog post](http://dubstepdish.com/blog/2013/11/06/introducing-i3-style/). 18 | 19 | ## Installing 20 | 21 | To install with [npm](https://npmjs.org/): 22 | 23 | npm install -g i3-style 24 | 25 | The `i3-style` executable should now be in your PATH. 26 | 27 | ## Usage 28 | 29 | Just call `i3-style` with the name of the theme you want to try and where you want to write the config file to. i3-style will look for your config in the default place and apply the theme. 30 | 31 | i3-style solarized -o ~/.config/i3/config --reload 32 | 33 | Check the `themes` directory for the list of built-in themes. 34 | 35 | If you want to modify a theme, copy it from `themes` and give it a `.yaml` extension. The object format is [well-documented](https://github.com/acrisci/i3-style/blob/master/doc/spec.md) and includes support for color aliases. Then back up your config and call i3-style. 36 | 37 | i3-style ~/.config/i3/solarized.yaml -o ~/.config/i3/config 38 | 39 | Just keep doing that until you get it perfect (which might be never). 40 | 41 | ## Send us themes! 42 | 43 | Do you have a cool colorscheme in your config file that you want to share with other people? i3-style can automatically convert it to a theme file: 44 | 45 | i3-style --to-theme ~/.config/i3/config -o my-theme.yaml 46 | 47 | If you have a new theme, or made an improvement to an existing theme, please make a pull request adding your theme to the `themes` directory! 48 | 49 | ## License 50 | 51 | This work is available under a FreeBSD License (see LICENSE). 52 | 53 | Copyright © 2013, Tony Crisci 54 | 55 | All rights reserved. 56 | -------------------------------------------------------------------------------- /legacy/doc/spec.md: -------------------------------------------------------------------------------- 1 | # The i3-config-builder Format Specification 2 | 3 |
4 |
Authors
5 |
Tony Crisci (dubstepdish.com)
6 | 7 |
Revision
8 |
0.1.0
9 | 10 |
Date
11 |
10 April 2014
12 | 13 |
Copyright
14 |
Copyright © 2013 Tony Crisci. This work is licensed CC-BY-SA 3.0 15 |
16 | 17 |
Abstract
18 |
i3-config-builder is a format to create a context for templating i3 window manager config files. based on JavaScript Object Notation (JSON).
19 |
20 | 21 | ## Introduction 22 | 23 | i3-config-builder is a format for encoding context for i3 config templates. 24 | 25 | A complete i3-config-builder data structure is a [JSON](http://www.json.org/) object, but may be expressed in formats that map to JSON such as [YAML](http://yaml.org/). 26 | 27 | ### Example 28 | 29 | An i3-config-builder object for an i3 theme: 30 | 31 | ```YAML 32 | --- 33 | colors: 34 | base03: '#002b36' 35 | base02: '#073642' 36 | base01: '#586e75' 37 | base00: '#657b83' 38 | base0: '#839496' 39 | base1: '#93a1a1' 40 | base2: '#eee8d5' 41 | base3: '#fdf6e3' 42 | yellow: '#b58900' 43 | orange: '#cb4b16' 44 | red: '#dc322f' 45 | magenta: '#d33682' 46 | violet: '#6c71c4' 47 | blue: '#268bd2' 48 | cyan: '#2aa198' 49 | green: '#859900' 50 | custom: '#1c5766' 51 | window_colors: 52 | focused: 53 | border: 'base1' 54 | background: 'green' 55 | text: 'base3' 56 | indicator: 'green' 57 | focused_inactive: 58 | border: 'base02' 59 | background: 'base02' 60 | text: 'base2' 61 | indicator: 'violet' 62 | unfocused: 63 | border: 'base02' 64 | background: 'base02' 65 | text: 'base1' 66 | indicator: 'base01' 67 | urgent: 68 | border: 'magenta' 69 | background: 'magenta' 70 | text: 'base3' 71 | indicator: 'red' 72 | bar_colors: 73 | separator: 'red' 74 | background: 'base02' 75 | statusline: 'blue' 76 | focused_workspace: 77 | border: 'base3' 78 | background: 'green' 79 | text: 'base3' 80 | active_workspace: 81 | border: 'base3' 82 | background: 'violet' 83 | text: 'base3' 84 | inactive_workspace: 85 | border: 'base01' 86 | background: 'base1' 87 | text: 'base03' 88 | urgent_workspace: 89 | border: 'magenta' 90 | background: 'magenta' 91 | text: 'base3' 92 | ``` 93 | 94 | ## i3-config-builder Objects 95 | 96 | An *i3-config-builder object* is always a single object. The i3-config-builder object may optionally have any of the members described below at its root. Each of the keys for the i3-config-builder object and all their members must only consist of word characters, digits, and the underscore. 97 | 98 | ### The Meta Object 99 | 100 | The *meta object* may be present at the root of the i3-config-builder object with the key `meta`. If present, its value must be an object which may contain any of the following keys: 101 | 102 | * `description` 103 | 104 | If `description` is present, it must be a string less than 140 characters long and should briefly describe the purpose of the object. 105 | 106 | ### The Colors Object 107 | 108 | The *colors object* may be present at the root of the i3-config-builder object with the key `colors`. If present, its value must be a single object with keys that each represent a *color alias*. The value of a color alias must be a single string value that expresses a valid *hex color code* in the same format as HTML hex color codes. 109 | 110 | Other members of the i3-config-builder object may be specified to use color aliases in place of, or in addition to, hex color codes. Any other member with such a specificiation must satisfy: 111 | 112 | 1. It must have exactly one member which must be specified to be exclusively either a string or an object with string values but not both. 113 | 2. The string value or any member value of object each must be either a color alias such that there is a key in the colors object equal to that value or a valid hex color code. 114 | 115 | ### The Window Colors Object 116 | 117 | The *windows colors object* may be present at the root of the i3-config-builder object with the key `window_colors`. If present, its value must be an object which may contain any of the following keys: 118 | 119 | * `focused` 120 | * `focused_inactive` 121 | * `unfocused` 122 | * `urgent` 123 | 124 | For each of these keys that are present, its value must be an object which may contain any of the following keys: 125 | 126 | * `border` 127 | * `background` 128 | * `text` 129 | * `indicator` 130 | 131 | For each of these keys that are present, its value must be a single string which is either a color alias or a hex color code. 132 | 133 | ### The Bar Colors Object 134 | 135 | The bar colors object may be present at the root of the i3-config-builder object with the key `bar_colors`. If present, its value must be an object which may contain any of the following keys: 136 | 137 | * `separator` 138 | * `background` 139 | * `statusline` 140 | * `focused_workspace` 141 | * `active_workspace` 142 | * `inactive_workspace` 143 | * `urgent_workspace` 144 | 145 | If the any of the keys `separator`, `background`, or `statusline`, are present, its value must be a single string which is either a color alias or a hex color code. 146 | 147 | If any of the keys `focused_workspace`, `active_workspace`, `inactive_workspace`, or `urgent_workspace` are present, its value must be a single object which may contain any of the following keys: 148 | 149 | * `border` 150 | * `background` 151 | * `text` 152 | 153 | If any of these keys are present, its value must be a single string which is either a color alias or a hex color code. 154 | -------------------------------------------------------------------------------- /legacy/lib/.gitignore: -------------------------------------------------------------------------------- 1 | /*.js 2 | -------------------------------------------------------------------------------- /legacy/lib/.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altdesktop/i3-style/f93821b239667cb4ecff41e6ad9632da0b5aaa50/legacy/lib/.npmignore -------------------------------------------------------------------------------- /legacy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "i3-style", 3 | "author": "Tony Crisci (http://dubstepdish.com)", 4 | "main": "./lib/index.js", 5 | "directories": [ 6 | "lib", 7 | "doc", 8 | "themes" 9 | ], 10 | "bin": { 11 | "i3-style": "./lib/cli.js" 12 | }, 13 | "preferGlobal": true, 14 | "keywords": [ 15 | "i3", 16 | "i3wm", 17 | "theme", 18 | "style", 19 | "colorscheme" 20 | ], 21 | "license": "BSD-2-Clause", 22 | "dependencies": { 23 | "color-namer": "^1.0.0", 24 | "commander": "^2.9.0", 25 | "js-yaml": "^3.4.3", 26 | "shelljs": "^0.3.0", 27 | "underscore": "^1.8.3" 28 | }, 29 | "devDependencies": { 30 | "chai": "^3.4.0", 31 | "coffee-script": "^1.10.0", 32 | "mocha": "^2.3.3", 33 | "which": "^1.2.0" 34 | }, 35 | "version": "0.10.0", 36 | "description": "Make your i3wm config a little more stylish", 37 | "scripts": { 38 | "test": "cake test", 39 | "prepublish": "cake build" 40 | }, 41 | "repository": { 42 | "type": "git", 43 | "url": "https://github.com/acrisci/i3-style.git" 44 | }, 45 | "bugs": { 46 | "url": "https://github.com/acrisci/i3-style/issues" 47 | }, 48 | "homepage": "https://github.com/acrisci/i3-style" 49 | } 50 | -------------------------------------------------------------------------------- /legacy/src/cli.coffee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env coffee 2 | 3 | _ = require 'underscore' 4 | fs = require 'fs' 5 | sh = require 'shelljs' 6 | program = require 'commander' 7 | yaml = require 'js-yaml' 8 | pathUtil = require 'path' 9 | {mkConfig, mkTheme} = require './index' 10 | VERSION = require('../package.json').version 11 | 12 | sh.config.silent = yes 13 | 14 | # convenience function to test existence of a file 15 | fileExists = (path) -> path? and sh.test('-f', path) 16 | 17 | # convenience function to exit with code 1 error. also prints usage. 18 | exitWithError = (msg) -> 19 | program.outputHelp() 20 | process.stderr.write "Error: #{msg}\n" 21 | process.exit 1 22 | 23 | program 24 | .version(VERSION) 25 | .usage(' [options]') 26 | .option('-c, --config ', 'The config file the theme should be applied to. Defaults to the default i3 location') 27 | .option('-o, --output ', 'Apply the theme, attempt to validate the result, and write it to ') 28 | .option('-s, --save', 'Set the output file to the path of the input file') 29 | .option('-r, --reload', 'Apply the theme by reloading the config') 30 | .option('-l, --list-all', 'Print a list of all available themes') 31 | .option('-t, --to-theme [file]', 'Prints an i3-style theme based on the given config suitable for sharing with others') 32 | .parse(process.argv) 33 | 34 | themesDir = pathUtil.resolve(__dirname, '../themes') 35 | themesAvailable = sh.ls themesDir 36 | 37 | # if --list-all was passed, print themes and exit 38 | if program.listAll 39 | sh.echo '\n Available themes:\n' 40 | themesList = [] 41 | themesAvailable.forEach (themePath) -> 42 | theme = yaml.safeLoad sh.cat pathUtil.join(themesDir, themePath) 43 | paddedName = (themePath[i] or ' ' for i in [0..17]).join('') 44 | themesList.push " #{paddedName} - #{theme.meta?.description or ''}" 45 | sh.echo themesList.join('\n') + '\n' 46 | process.exit 0 47 | 48 | # get the contents of the config file specified on the command line, or look in 49 | # the default locations for the config file 50 | HOME = process.env.HOME 51 | configPath = switch 52 | when program.config 53 | program.config 54 | when _.isString program.toTheme 55 | program.toTheme 56 | when HOME and fileExists "#{HOME}/.i3/config" 57 | "#{HOME}/.i3/config" 58 | when HOME and fileExists "#{HOME}/.config/i3/config" 59 | "#{HOME}/.config/i3/config" 60 | else 61 | exitWithError "Could not find a valid i3 config file" 62 | 63 | # throw an error when a config file is not found 64 | unless fileExists configPath 65 | exitWithError "Config file not found: #{configPath}" 66 | 67 | if program.toTheme 68 | theme = mkTheme sh.cat configPath 69 | yamlTheme = """# vim: filetype=yaml 70 | --- 71 | #{yaml.safeDump theme}""" 72 | 73 | if program.output 74 | fs.writeFileSync(program.output, yamlTheme) 75 | else 76 | sh.echo yamlTheme 77 | 78 | process.exit 0 79 | 80 | # print usage if no arguments 81 | unless program.args.length 82 | program.outputHelp() 83 | process.exit 0 84 | 85 | # throw an error if the theme file does not exist 86 | unless fileExists(program.args[0]) or program.args[0] in themesAvailable 87 | exitWithError "Theme or file not found: #{program.args[0]}" 88 | 89 | # try to parse the theme file they specified. it has to have the right file 90 | # extension. 91 | theme = switch 92 | when program.args[0].match /\.json$/ 93 | JSON.parse sh.cat program.args[0] 94 | when program.args[0].match(/\.yaml$/) or program.args[0].match(/\.yml$/) 95 | yaml.safeLoad sh.cat program.args[0] 96 | when program.args[0] in themesAvailable 97 | yaml.safeLoad sh.cat pathUtil.join(themesDir, program.args[0]) 98 | else 99 | yaml.safeLoad sh.cat program.args[0] 100 | 101 | # do the heavy lifting 102 | config = mkConfig theme, sh.cat(configPath) 103 | 104 | # no output file specified. echo result to stdout and we are done. 105 | outputPath = switch 106 | when program.output 107 | program.output 108 | when program.save 109 | configPath 110 | else 111 | null 112 | 113 | unless outputPath 114 | sh.echo config 115 | sh.exec('i3-msg reload') if program.reload 116 | process.exit 0 117 | 118 | # try to validate the generated config if we can 119 | i3Path = sh.which 'i3' 120 | tmpdir = sh.tempdir() 121 | 122 | if i3Path and tmpdir 123 | # write the output config to the tmp directory 124 | tmpConfigPath = pathUtil.join tmpdir, 'i3-style-config' 125 | fs.writeFileSync tmpConfigPath, config 126 | if fileExists tmpConfigPath 127 | # try to validate it with the i3 -C flag 128 | validation = sh.exec("#{i3Path} -c #{tmpConfigPath} -C") 129 | sh.rm tmpConfigPath 130 | if validation.output.indexOf('ERROR:') > 0 or validation.code > 0 131 | exitWithError "Could not validate output configuration.\n\n#{validation.output}" 132 | 133 | # make a backup (if not testing) 134 | if tmpdir and not process.env.I3STYLETEST 135 | sh.mkdir pathUtil.join(tmpdir, 'i3-style') 136 | tmpPath = pathUtil.join(tmpdir, 'i3-style', "config.bak.#{Date.now()}") 137 | sh.echo "#{configPath} -> #{tmpPath}" 138 | sh.cp(configPath, tmpPath) 139 | 140 | # finally write the file to the specified location 141 | fs.writeFile outputPath, config, (err) -> 142 | exitWithError "Could not write to file: #{program.output}\n\n#{err}" if err 143 | sh.echo "Applied #{program.args[0]} theme to #{outputPath}" 144 | sh.exec('i3-msg reload') if program.reload 145 | -------------------------------------------------------------------------------- /legacy/src/index.coffee: -------------------------------------------------------------------------------- 1 | _ = require 'underscore' 2 | namer = require 'color-namer' 3 | 4 | # change to mustache style templates 5 | _.templateSettings = interpolate :/\{\{(.+?)\}\}/g 6 | 7 | # templates to build lines in the config 8 | templates = 9 | windowColors: _.template "client.{{state}} {{border}} {{background}} {{text}} {{indicator}}" 10 | barColors: _.template "{{state}} {{border}} {{background}} {{text}}" 11 | 12 | # matches the bar directive and captures the inside 13 | # IMPORTANT: only works if the bar doesn't have colors directive! strip first! 14 | # TODO: fix this so it will ignore inner braces 15 | matchBar = /// 16 | bar\s*{\s*\n 17 | ([^}]*) 18 | \n} 19 | ///g 20 | 21 | # matches a colors directive, such as may be inside a bar directive 22 | matchBarColors = /// 23 | \s*colors\s*{ 24 | [^}]* 25 | } 26 | ///g 27 | 28 | # matches a client color directive 29 | matchWindowColors = /// 30 | \s*client\. 31 | (?:focused | focused_inactive | unfocused | urgent) 32 | \s+ 33 | .* 34 | ///g 35 | 36 | # strips the config of any (bar) color directives and client color directives 37 | stripConfig = (config) -> 38 | config.replace(matchWindowColors, '').replace(matchBarColors, '') 39 | 40 | # takes color aliases and window_color directive object and returns i3 config 41 | # client color directives string 42 | mkWindowColors = (colors = {}, windowColors) -> 43 | result = [] 44 | _.each windowColors, (parts, state) -> 45 | result.push templates.windowColors 46 | state: state 47 | border: colors[parts.border] or parts.border 48 | background: colors[parts.background] or parts.background 49 | text: colors[parts.text] or parts.text 50 | indicator: colors[parts.indicator] or parts.indicator 51 | return result.join '\n' 52 | 53 | # takes color aliases and bar color directive object and returns i3 config bar 54 | # color directive string 55 | mkBarColors = (colors = {}, bar_colors) -> 56 | result = [] 57 | _.each bar_colors, (parts, state) -> 58 | if _.isString parts 59 | result.push "#{state} #{colors[parts] or parts}" 60 | else 61 | result.push templates.barColors 62 | state: state 63 | border: colors[parts.border] or parts.border 64 | background: colors[parts.background] or parts.background 65 | text: colors[parts.text] or parts.text 66 | return result.join "\n " 67 | 68 | 69 | # takes theme object and i3 config string and returns a new i3 config string 70 | # with the theme applied 71 | mkConfig = (theme, config) -> 72 | config = stripConfig config 73 | config = config.replace matchBar, (match, inside) -> 74 | return """ 75 | bar { 76 | #{inside.trim()} 77 | colors { 78 | #{mkBarColors theme.colors, theme.bar_colors} 79 | } 80 | } 81 | """ 82 | config += "\n#{mkWindowColors theme.colors, theme.window_colors}\n" 83 | return config 84 | 85 | # takes a config and returns an i3-style theme 86 | mkTheme = (config) -> 87 | theme = 88 | meta: 89 | description: 'AUTOMATICALLY GENERATED THEME' 90 | 91 | # add a color name to the theme for the given hex color and return the name 92 | # of the color 93 | addColor = (hex) -> 94 | if not hex 95 | return null 96 | 97 | unless theme.colors? 98 | theme.colors = {} 99 | 100 | colorName = namer(hex).html[0].name 101 | 102 | if theme.colors[colorName]? and theme.colors[colorName] isnt hex 103 | i = 0 104 | while true 105 | i += 1 106 | c = "#{colorName}#{i}" 107 | if not theme.colors[c] or theme.colors[c] == hex 108 | colorName = c 109 | break 110 | 111 | theme.colors[colorName] = hex 112 | return colorName 113 | 114 | stateBarInside = off 115 | stateColorsInside = off 116 | 117 | for line in config.split('\n') 118 | # trim the line 119 | line = line.replace(/^\s+|\s+$/g, '') 120 | # remove duplicate spaces between words 121 | line = line.replace(/\s+/g, ' ') 122 | 123 | # beginning of a bar block 124 | if line.indexOf('bar {') is 0 125 | stateBarInside = on 126 | continue 127 | 128 | # beginning of a bar color block 129 | if line.indexOf('colors {') is 0 and stateBarInside 130 | stateColorsInside = on 131 | continue 132 | 133 | if line.indexOf('}') is 0 134 | if stateColorsInside 135 | # end of a bar color block 136 | stateColorsInside = off 137 | continue 138 | if stateBarInside 139 | # end of a bar block 140 | stateBarInside = off 141 | continue 142 | 143 | # check for window color config directive 144 | if line.indexOf('client.') == 0 145 | color = line.split(' ') 146 | color[0] = color[0].substring('client.'.length) 147 | if color[0] in ['focused', 'focused_inactive', 'unfocused', 'urgent'] 148 | border = addColor color[1] 149 | background = addColor color[2] 150 | text = addColor color[3] 151 | indicator = addColor color[4] 152 | 153 | unless theme.window_colors? 154 | theme.window_colors = {} 155 | 156 | theme.window_colors[color[0]] = {} 157 | if border? then theme.window_colors[color[0]].border = border 158 | if background? then theme.window_colors[color[0]].background = background 159 | if text? then theme.window_colors[color[0]].text = text 160 | if indicator? then theme.window_colors[color[0]].indicator = indicator 161 | 162 | continue 163 | 164 | # check for bar color config directive 165 | if stateColorsInside 166 | barColor = line.split(' ') 167 | if barColor[0] in ['separator', 'background', 'statusline'] 168 | unless theme.bar_colors? 169 | theme.bar_colors = {} 170 | 171 | theme.bar_colors[barColor[0]] = addColor barColor[1] 172 | else if barColor[0] in ['focused_workspace', 'active_workspace', 173 | 'inactive_workspace', 'urgent_workspace'] 174 | border = addColor barColor[1] 175 | background = addColor barColor[2] 176 | text = addColor barColor[3] 177 | 178 | unless theme.bar_colors? 179 | theme.bar_colors = {} 180 | 181 | theme.bar_colors[barColor[0]] = {} 182 | if border? then theme.bar_colors[barColor[0]].border = border 183 | if background? then theme.bar_colors[barColor[0]].background = background 184 | if text? then theme.bar_colors[barColor[0]].text = text 185 | 186 | continue 187 | 188 | return theme 189 | 190 | module.exports = 191 | mkConfig: mkConfig 192 | mkTheme: mkTheme 193 | -------------------------------------------------------------------------------- /legacy/test/default-config: -------------------------------------------------------------------------------- 1 | # i3 config file (v4) 2 | # 3 | # Please see http://i3wm.org/docs/userguide.html for a complete reference! 4 | # 5 | # This config file uses keycodes (bindsym) and was written for the QWERTY 6 | # layout. 7 | # 8 | # To get a config file with the same key positions, but for your current 9 | # layout, use the i3-config-wizard 10 | # 11 | 12 | # Font for window titles. Will also be used by the bar unless a different font 13 | # is used in the bar {} block below. ISO 10646 = Unicode 14 | font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 15 | # The font above is very space-efficient, that is, it looks good, sharp and 16 | # clear in small sizes. However, if you need a lot of unicode glyphs or 17 | # right-to-left text rendering, you should instead use pango for rendering and 18 | # chose a FreeType font, such as: 19 | # font pango:DejaVu Sans Mono 10 20 | 21 | # use Mouse+Mod1 to drag floating windows to their wanted position 22 | floating_modifier Mod1 23 | 24 | # start a terminal 25 | bindsym Mod1+Return exec i3-sensible-terminal 26 | 27 | # kill focused window 28 | bindsym Mod1+Shift+q kill 29 | 30 | # start dmenu (a program launcher) 31 | bindsym Mod1+d exec dmenu_run 32 | # There also is the (new) i3-dmenu-desktop which only displays applications 33 | # shipping a .desktop file. It is a wrapper around dmenu, so you need that 34 | # installed. 35 | # bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop 36 | 37 | # change focus 38 | bindsym Mod1+j focus left 39 | bindsym Mod1+k focus down 40 | bindsym Mod1+l focus up 41 | bindsym Mod1+semicolon focus right 42 | 43 | # alternatively, you can use the cursor keys: 44 | bindsym Mod1+Left focus left 45 | bindsym Mod1+Down focus down 46 | bindsym Mod1+Up focus up 47 | bindsym Mod1+Right focus right 48 | 49 | # move focused window 50 | bindsym Mod1+Shift+j move left 51 | bindsym Mod1+Shift+k move down 52 | bindsym Mod1+Shift+l move up 53 | bindsym Mod1+Shift+semicolon move right 54 | 55 | # alternatively, you can use the cursor keys: 56 | bindsym Mod1+Shift+Left move left 57 | bindsym Mod1+Shift+Down move down 58 | bindsym Mod1+Shift+Up move up 59 | bindsym Mod1+Shift+Right move right 60 | 61 | # split in horizontal orientation 62 | bindsym Mod1+h split h 63 | 64 | # split in vertical orientation 65 | bindsym Mod1+v split v 66 | 67 | # enter fullscreen mode for the focused container 68 | bindsym Mod1+f fullscreen 69 | 70 | # change container layout (stacked, tabbed, toggle split) 71 | bindsym Mod1+s layout stacking 72 | bindsym Mod1+w layout tabbed 73 | bindsym Mod1+e layout toggle split 74 | 75 | # toggle tiling / floating 76 | bindsym Mod1+Shift+space floating toggle 77 | 78 | # change focus between tiling / floating windows 79 | bindsym Mod1+space focus mode_toggle 80 | 81 | # focus the parent container 82 | bindsym Mod1+a focus parent 83 | 84 | # focus the child container 85 | #bindsym Mod1+d focus child 86 | 87 | # move the currently focused window to the scratchpad 88 | bindsym Mod1+Shift+minus move scratchpad 89 | 90 | # Show the next scratchpad window or hide the focused scratchpad window. 91 | # If there are multiple scratchpad windows, this command cycles through them. 92 | bindsym Mod1+minus scratchpad show 93 | 94 | # switch to workspace 95 | bindsym Mod1+1 workspace 1 96 | bindsym Mod1+2 workspace 2 97 | bindsym Mod1+3 workspace 3 98 | bindsym Mod1+4 workspace 4 99 | bindsym Mod1+5 workspace 5 100 | bindsym Mod1+6 workspace 6 101 | bindsym Mod1+7 workspace 7 102 | bindsym Mod1+8 workspace 8 103 | bindsym Mod1+9 workspace 9 104 | bindsym Mod1+0 workspace 10 105 | 106 | # move focused container to workspace 107 | bindsym Mod1+Shift+1 move container to workspace 1 108 | bindsym Mod1+Shift+2 move container to workspace 2 109 | bindsym Mod1+Shift+3 move container to workspace 3 110 | bindsym Mod1+Shift+4 move container to workspace 4 111 | bindsym Mod1+Shift+5 move container to workspace 5 112 | bindsym Mod1+Shift+6 move container to workspace 6 113 | bindsym Mod1+Shift+7 move container to workspace 7 114 | bindsym Mod1+Shift+8 move container to workspace 8 115 | bindsym Mod1+Shift+9 move container to workspace 9 116 | bindsym Mod1+Shift+0 move container to workspace 10 117 | 118 | # reload the configuration file 119 | bindsym Mod1+Shift+c reload 120 | # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 121 | bindsym Mod1+Shift+r restart 122 | # exit i3 (logs you out of your X session) 123 | bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" 124 | 125 | # resize window (you can also use the mouse for that) 126 | mode "resize" { 127 | # These bindings trigger as soon as you enter the resize mode 128 | 129 | # Pressing left will shrink the window’s width. 130 | # Pressing right will grow the window’s width. 131 | # Pressing up will shrink the window’s height. 132 | # Pressing down will grow the window’s height. 133 | bindsym j resize shrink width 10 px or 10 ppt 134 | bindsym k resize grow height 10 px or 10 ppt 135 | bindsym l resize shrink height 10 px or 10 ppt 136 | bindsym semicolon resize grow width 10 px or 10 ppt 137 | 138 | # same bindings, but for the arrow keys 139 | bindsym Left resize shrink width 10 px or 10 ppt 140 | bindsym Down resize grow height 10 px or 10 ppt 141 | bindsym Up resize shrink height 10 px or 10 ppt 142 | bindsym Right resize grow width 10 px or 10 ppt 143 | 144 | # back to normal: Enter or Escape 145 | bindsym Return mode "default" 146 | bindsym Escape mode "default" 147 | } 148 | 149 | bindsym Mod1+r mode "resize" 150 | 151 | # Start i3bar to display a workspace bar (plus the system information i3status 152 | # finds out, if available) 153 | bar { 154 | status_command i3status 155 | } 156 | 157 | ####################################################################### 158 | # automatically start i3-config-wizard to offer the user to create a 159 | # keysym-based config which used his favorite modifier (alt or windows) 160 | # 161 | # i3-config-wizard will not launch if there already is a config file 162 | # in ~/.i3/config. 163 | # 164 | # Please remove the following exec line: 165 | ####################################################################### 166 | exec i3-config-wizard 167 | -------------------------------------------------------------------------------- /legacy/test/test.coffee: -------------------------------------------------------------------------------- 1 | chai = require 'chai' 2 | {mkConfig} = require '../src' 3 | theme = require './theme.json' 4 | sh = require 'shelljs' 5 | chai.should() 6 | 7 | sh.config.silent = yes 8 | process.env.I3STYLETEST = "yes" 9 | 10 | commentedBar = """ 11 | #bar {} 12 | #bar { 13 | #stuff 14 | #} 15 | """ 16 | 17 | normalBar = """ 18 | bar { 19 | verbose true 20 | # @bar_comment@ 21 | colors { 22 | } 23 | } 24 | """ 25 | 26 | testForColors = (config) -> 27 | /client\.focused #859900 #859900 #fdf6e3 #859900/.test(config).should.be.true 28 | /client\.focused_inactive #073642 #073642 #eee8d5 #6c71c4/.test(config).should.be.true 29 | /client\.unfocused #073642 #073642 #93a1a1 #586e75/.test(config).should.be.true 30 | /client\.urgent #d33682 #d33682 #fdf6e3 #dc322f/.test(config).should.be.true 31 | 32 | testForBarColors = (config) -> 33 | /separator #dc322f/.test(config).should.be.true 34 | /background #002b36/.test(config).should.be.true 35 | /statusline #268bd2/.test(config).should.be.true 36 | /active_workspace #fdf6e3 #6c71c4 #fdf6e3/.test(config).should.be.true 37 | /inactive_workspace #586e75 #93a1a1 #002b36/.test(config).should.be.true 38 | /focused_workspace #fdf6e3 #859900 #fdf6e3/.test(config).should.be.true 39 | /urgent_workspace #d33682 #d33682 #fdf6e3/.test(config).should.be.true 40 | 41 | describe 'Bar block', -> 42 | result = mkConfig(theme, normalBar) 43 | it 'should add a colors block', -> 44 | /colors {/.test(result).should.be.true 45 | it 'should preserve bar comments and directives', -> 46 | /# @bar_comment@/.test(result).should.be.true 47 | /verbose true/.test(result).should.be.true 48 | it 'should add colors to the colors block', -> 49 | testForBarColors result 50 | it 'should add colors to the end', -> 51 | testForColors result 52 | 53 | describe 'Config with comments', -> 54 | result = mkConfig(theme, commentedBar) 55 | it 'should ignore bar blocks within comments', -> 56 | /colors {/.test(result).should.be.false 57 | 58 | describe 'Default config', -> 59 | it 'should apply the theme with no errors', -> 60 | # you need to have `i3` in your PATH for this to work 61 | {code} = sh.exec('src/cli.coffee solarized -c test/default-config -o /dev/null') 62 | code.should.be.equal 0 63 | it 'should apply the theme to the default config', -> 64 | {output, code} = sh.exec('src/cli.coffee -c test/default-config test/theme.json') 65 | code.should.be.equal 0 66 | testForColors output 67 | testForBarColors output 68 | -------------------------------------------------------------------------------- /legacy/test/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "bar_colors": { 3 | "active_workspace": { 4 | "background": "violet", 5 | "border": "base3", 6 | "text": "base3" 7 | }, 8 | "background": "base03", 9 | "focused_workspace": { 10 | "background": "green", 11 | "border": "base3", 12 | "text": "base3" 13 | }, 14 | "inactive_workspace": { 15 | "background": "base1", 16 | "border": "base01", 17 | "text": "base03" 18 | }, 19 | "separator": "red", 20 | "statusline": "blue", 21 | "urgent_workspace": { 22 | "background": "magenta", 23 | "border": "magenta", 24 | "text": "base3" 25 | } 26 | }, 27 | "colors": { 28 | "base0": "#839496", 29 | "base00": "#657b83", 30 | "base01": "#586e75", 31 | "base02": "#073642", 32 | "base03": "#002b36", 33 | "base1": "#93a1a1", 34 | "base2": "#eee8d5", 35 | "base3": "#fdf6e3", 36 | "blue": "#268bd2", 37 | "custom": "#1c5766", 38 | "cyan": "#2aa198", 39 | "green": "#859900", 40 | "magenta": "#d33682", 41 | "orange": "#cb4b16", 42 | "red": "#dc322f", 43 | "violet": "#6c71c4", 44 | "yellow": "#b58900" 45 | }, 46 | "meta": { 47 | "description": "Solarized theme by lasers" 48 | }, 49 | "window_colors": { 50 | "focused": { 51 | "background": "green", 52 | "border": "green", 53 | "indicator": "green", 54 | "text": "base3" 55 | }, 56 | "focused_inactive": { 57 | "background": "base02", 58 | "border": "base02", 59 | "indicator": "violet", 60 | "text": "base2" 61 | }, 62 | "unfocused": { 63 | "background": "base02", 64 | "border": "base02", 65 | "indicator": "base01", 66 | "text": "base1" 67 | }, 68 | "urgent": { 69 | "background": "magenta", 70 | "border": "magenta", 71 | "indicator": "red", 72 | "text": "base3" 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /legacy/themes/alphare: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: A beige theme by Alphare 5 | colors: 6 | black: '#000000' 7 | oldlace: '#FDF6E3' 8 | darkslategray: '#002B36' 9 | steelblue: '#268BD2' 10 | dimgray: '#5F676A' 11 | darkslategrey: '#484E50' 12 | crimson: '#DC322F' 13 | steelblue1: '#4C7899' 14 | steelblue2: '#285577' 15 | white: '#FFFFFF' 16 | darkslategrey1: '#333333' 17 | black1: '#222222' 18 | gray: '#888888' 19 | darkslategray1: '#2F343A' 20 | darkred: '#900000' 21 | window_colors: 22 | focused: 23 | border: black 24 | background: oldlace 25 | text: darkslategray 26 | indicator: black 27 | focused_inactive: 28 | border: black 29 | background: dimgray 30 | text: oldlace 31 | indicator: darkslategrey 32 | unfocused: 33 | border: black 34 | background: black 35 | text: oldlace 36 | indicator: black 37 | urgent: 38 | border: black 39 | background: crimson 40 | text: oldlace 41 | indicator: crimson 42 | bar_colors: 43 | background: oldlace 44 | statusline: darkslategray 45 | separator: black 46 | focused_workspace: 47 | border: black 48 | background: steelblue 49 | text: white 50 | active_workspace: 51 | border: darkslategrey1 52 | background: black1 53 | text: white 54 | inactive_workspace: 55 | border: darkslategrey1 56 | background: black1 57 | text: gray 58 | urgent_workspace: 59 | border: darkslategray1 60 | background: darkred 61 | text: white 62 | -------------------------------------------------------------------------------- /legacy/themes/archlinux: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Archlinux theme by okraits ' 6 | window_colors: 7 | focused: 8 | border: '#0088CC' 9 | background: '#0088CC' 10 | text: '#ffffff' 11 | indicator: '#dddddd' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#333333' 15 | text: '#888888' 16 | indicator: '#292d2e' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#222222' 30 | statusline: '#dddddd' 31 | focused_workspace: 32 | border: '#0088CC' 33 | background: '#0088CC' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#333333' 38 | text: '#ffffff' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#333333' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /legacy/themes/base16-tomorrow: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | colors: 4 | base00: '#1d1f21' 5 | base01: '#282a2e' 6 | base02: '#373b41' 7 | base03: '#969896' 8 | base04: '#b4b7b4' 9 | base05: '#c5c8c6' 10 | base06: '#e0e0e0' 11 | base07: '#ffffff' 12 | base08: '#cc6666' 13 | base09: '#de935f' 14 | base0A: '#f0c674' 15 | base0B: '#b5bd68' 16 | base0C: '#8abeb7' 17 | base0D: '#81a2be' 18 | base0E: '#b294bb' 19 | base0F: '#a3685a' 20 | 21 | meta: 22 | description: 'Base16 Tomorrow, by Chris Kempson (http://chriskempson.com)' 23 | window_colors: 24 | focused: 25 | border: 'base0D' 26 | background: 'base0D' 27 | text: 'base00' 28 | indicator: 'base01' 29 | focused_inactive: 30 | border: 'base02' 31 | background: 'base02' 32 | text: 'base03' 33 | indicator: 'base01' 34 | unfocused: 35 | border: 'base01' 36 | background: 'base01' 37 | text: 'base03' 38 | indicator: 'base01' 39 | urgent: 40 | border: 'base02' 41 | background: 'base08' 42 | text: 'base07' 43 | indicator: 'base08' 44 | bar_colors: 45 | separator: 'base03' 46 | background: 'base00' 47 | statusline: 'base05' 48 | focused_workspace: 49 | border: 'base0D' 50 | background: 'base0D' 51 | text: 'base00' 52 | active_workspace: 53 | border: 'base02' 54 | background: 'base02' 55 | text: 'base07' 56 | inactive_workspace: 57 | border: 'base01' 58 | background: 'base01' 59 | text: 'base03' 60 | urgent_workspace: 61 | border: 'base08' 62 | background: 'base08' 63 | text: 'base07' 64 | -------------------------------------------------------------------------------- /legacy/themes/debian: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Debian theme by lasers' 6 | window_colors: 7 | focused: 8 | border: '#d70a53' 9 | background: '#d70a53' 10 | text: '#ffffff' 11 | indicator: '#8c0333' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#333333' 15 | text: '#888888' 16 | indicator: '#333333' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#333333' 22 | urgent: 23 | border: '#eb709b' 24 | background: '#eb709b' 25 | text: '#ffffff' 26 | indicator: '#eb709b' 27 | bar_colors: 28 | separator: '#444444' 29 | background: '#222222' 30 | statusline: '#666666' 31 | focused_workspace: 32 | border: '#d70a53' 33 | background: '#d70a53' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#333333' 38 | text: '#888888' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#333333' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#eb709b' 45 | background: '#eb709b' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /legacy/themes/deep-purple: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Inspired by the Purple and Default themes. By jcpst ' 5 | bar_colors: 6 | separator: dimgrey 7 | background: black 8 | statusline: white 9 | focused_workspace: 10 | border: indigo 11 | background: indigo 12 | text: white 13 | active_workspace: 14 | border: darkslategrey 15 | background: dimgray 16 | text: white 17 | inactive_workspace: 18 | border: black 19 | background: black 20 | text: gray 21 | urgent_workspace: 22 | border: darkslategray 23 | background: darkred 24 | text: white 25 | colors: 26 | dimgrey: '#666666' 27 | black: '#000000' 28 | white: '#ffffff' 29 | indigo: '#551a8b' 30 | darkslategrey: '#333333' 31 | dimgray: '#5f676a' 32 | gray: '#888888' 33 | darkslategray: '#2f343a' 34 | darkred: '#900000' 35 | midnightblue: '#3b1261' 36 | indigo1: '#662b9c' 37 | darkslategrey1: '#484e50' 38 | black1: '#222222' 39 | darkslategray1: '#292d2e' 40 | window_colors: 41 | focused: 42 | border: midnightblue 43 | background: midnightblue 44 | text: white 45 | indicator: indigo1 46 | focused_inactive: 47 | border: darkslategrey 48 | background: dimgray 49 | text: white 50 | indicator: darkslategrey1 51 | unfocused: 52 | border: black1 53 | background: black1 54 | text: gray 55 | indicator: darkslategray1 56 | urgent: 57 | border: darkslategray 58 | background: darkred 59 | text: white 60 | indicator: darkred 61 | -------------------------------------------------------------------------------- /legacy/themes/default: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Default theme for i3wm ' 6 | window_colors: 7 | focused: 8 | border: '#4c7899' 9 | background: '#285577' 10 | text: '#ffffff' 11 | indicator: '#2e9ef4' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#5f676a' 15 | text: '#ffffff' 16 | indicator: '#484e50' 17 | unfocused: 18 | border: '#333333' 19 | background: '#222222' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#000000' 30 | statusline: '#ffffff' 31 | focused_workspace: 32 | border: '#4c7899' 33 | background: '#285577' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#5f676a' 38 | text: '#ffffff' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#222222' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /legacy/themes/flat-gray: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: flat gray based theme 5 | colors: 6 | darkslategrey: '#333333' 7 | white: '#FFFFFF' 8 | black: '#000000' 9 | darkgray: '#AAAAAA' 10 | black1: '#282828' 11 | window_colors: 12 | unfocused: 13 | border: darkslategrey 14 | background: darkslategrey 15 | text: white 16 | indicator: darkslategrey 17 | focused_inactive: 18 | border: darkslategrey 19 | background: darkslategrey 20 | text: white 21 | indicator: black 22 | focused: 23 | border: black 24 | background: black 25 | text: white 26 | indicator: black 27 | bar_colors: 28 | statusline: darkgray 29 | background: darkslategrey 30 | focused_workspace: 31 | border: black1 32 | background: black1 33 | text: white 34 | inactive_workspace: 35 | border: darkslategrey 36 | background: darkslategrey 37 | text: darkgray 38 | -------------------------------------------------------------------------------- /legacy/themes/gruvbox: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: Made by freeware-preacher to match gruvbox by morhetz 5 | bar_colors: 6 | separator: grey 7 | background: black 8 | statusline: wheat 9 | focused_workspace: 10 | border: darkseagreen 11 | background: darkseagreen 12 | text: black 13 | active_workspace: 14 | border: black1 15 | background: black1 16 | text: grey 17 | inactive_workspace: 18 | border: darkslategray 19 | background: darkslategray 20 | text: grey 21 | urgent_workspace: 22 | border: firebrick 23 | background: firebrick 24 | text: wheat 25 | colors: 26 | grey: '#928374' 27 | black: '#282828' 28 | wheat: '#ebdbb2' 29 | darkseagreen: '#689d6a' 30 | black1: '#1d2021' 31 | darkslategray: '#32302f' 32 | firebrick: '#cc241d' 33 | window_colors: 34 | focused: 35 | border: darkseagreen 36 | background: darkseagreen 37 | text: black 38 | indicator: black 39 | focused_inactive: 40 | border: black1 41 | background: black1 42 | text: grey 43 | indicator: black 44 | unfocused: 45 | border: darkslategray 46 | background: darkslategray 47 | text: grey 48 | indicator: black 49 | urgent: 50 | border: firebrick 51 | background: firebrick 52 | text: wheat 53 | indicator: black 54 | 55 | -------------------------------------------------------------------------------- /legacy/themes/icelines: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # Theme meant to be simple but visually efficient 3 | --- 4 | meta: 5 | description: 'icelines theme by mbfraga' 6 | colors: 7 | darkgray: '#141414' 8 | ice: '#00b0ef' 9 | gray: '#7d7d7d' 10 | darkred: '#472b2a' 11 | urgent: '#ff7066' 12 | window_colors: 13 | focused: 14 | border: 'ice' 15 | background: 'ice' 16 | text: 'darkgray' 17 | indicator: 'urgent' 18 | focused_inactive: 19 | border: 'darkgray' 20 | background: 'darkgray' 21 | text: 'ice' 22 | indicator: 'darkred' 23 | unfocused: 24 | border: 'darkgray' 25 | background: 'darkgray' 26 | text: 'gray' 27 | indicator: 'darkgray' 28 | urgent: 29 | border: 'urgent' 30 | background: 'urgent' 31 | text: 'darkgray' 32 | indicator: 'urgent' 33 | bar_colors: 34 | separator: 'gray' 35 | background: 'darkgray' 36 | statusline: 'ice' 37 | focused_workspace: 38 | border: 'ice' 39 | background: 'darkgray' 40 | text: 'ice' 41 | active_workspace: 42 | border: 'darkgray' 43 | background: 'darkgray' 44 | text: 'ice' 45 | inactive_workspace: 46 | border: 'darkgray' 47 | background: 'darkgray' 48 | text: 'gray' 49 | urgent_workspace: 50 | border: 'urgent' 51 | background: 'darkgray' 52 | text: 'urgent' 53 | -------------------------------------------------------------------------------- /legacy/themes/lime: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Lime theme by wei2912 , based on Archlinux theme by okraits ' 5 | colors: 6 | lime: '#4E9C00' # main colour 7 | lime_inactive: '#1B3600' 8 | 9 | red: '#C20000' # urgent colour 10 | black: '#333333' # background 11 | 12 | txt_active: '#FFFFFF' # white 13 | txt_inactive: '#888888' # grey 14 | 15 | indicator: '#FFFFFF' # white 16 | 17 | window_colors: 18 | focused: 19 | border: 'lime' 20 | background: 'lime' 21 | text: 'txt_active' 22 | indicator: 'indicator' 23 | focused_inactive: 24 | border: 'lime_inactive' 25 | background: 'lime_inactive' 26 | text: 'txt_inactive' 27 | indicator: 'indicator' 28 | unfocused: 29 | border: 'black' 30 | background: 'black' 31 | text: 'txt_inactive' 32 | indicator: 'indicator' 33 | urgent: 34 | border: 'red' 35 | background: 'red' 36 | text: 'txt_active' 37 | indicator: 'indicator' 38 | bar_colors: 39 | separator: 'txt_inactive' 40 | background: 'black' 41 | statusline: 'txt_active' 42 | focused_workspace: 43 | border: 'lime' 44 | background: 'lime' 45 | text: 'txt_active' 46 | active_workspace: 47 | border: 'black' 48 | background: 'black' 49 | text: 'txt_active' 50 | inactive_workspace: 51 | border: 'black' 52 | background: 'black' 53 | text: 'txt_inactive' 54 | urgent_workspace: 55 | border: 'red' 56 | background: 'red' 57 | text: 'txt_active' 58 | -------------------------------------------------------------------------------- /legacy/themes/mate: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Theme for blending i3 into MATE' 5 | colors: 6 | green: '#526532' 7 | lightgreen: '#a4cb64' 8 | darkgrey: '#3c3b37' 9 | grey: '#4c4c4c' 10 | lightgrey: '#aea79f' 11 | black: '#000000' 12 | white: '#ffffff' 13 | red: '#FF0000' 14 | window_colors: 15 | focused: 16 | border: green 17 | background: green 18 | text: white 19 | indicator: lightgreen 20 | focused_inactive: 21 | border: lightgrey 22 | background: lightgrey 23 | text: darkgrey 24 | indicator: lightgrey 25 | unfocused: 26 | border: darkgrey 27 | background: darkgrey 28 | text: lightgrey 29 | indicator: darkgrey 30 | urgent: 31 | border: red 32 | background: red 33 | text: white 34 | indicator: red 35 | bar_colors: 36 | separator: white 37 | background: darkgrey 38 | statusline: white 39 | focused_workspace: 40 | border: green 41 | background: green 42 | text: white 43 | active_workspace: 44 | border: lightgrey 45 | background: lightgrey 46 | text: darkgrey 47 | inactive_workspace: 48 | border: darkgrey 49 | background: darkgrey 50 | text: lightgrey 51 | urgent_workspace: 52 | border: red 53 | background: red 54 | text: white 55 | -------------------------------------------------------------------------------- /legacy/themes/okraits: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'A simple theme by okraits ' 6 | window_colors: 7 | focused: 8 | border: '#888888' 9 | background: '#dddddd' 10 | text: '#222222' 11 | indicator: '#2e9ef4' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#555555' 15 | text: '#bbbbbb' 16 | indicator: '#484e50' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#333333' 30 | statusline: '#bbbbbb' 31 | focused_workspace: 32 | border: '#888888' 33 | background: '#dddddd' 34 | text: '#222222' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#555555' 38 | text: '#bbbbbb' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#555555' 42 | text: '#bbbbbb' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /legacy/themes/purple: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Purple theme by AAlakkad ' 5 | bar_colors: 6 | separator: darkgray 7 | background: black 8 | statusline: white 9 | focused_workspace: 10 | border: darkslateblue 11 | background: darkslateblue 12 | text: lightgray 13 | active_workspace: 14 | border: khaki 15 | background: khaki 16 | text: black1 17 | inactive_workspace: 18 | border: black 19 | background: black 20 | text: darkgray 21 | urgent_workspace: 22 | border: firebrick 23 | background: firebrick 24 | text: white 25 | colors: 26 | darkgray: '#AAAAAA' 27 | black: '#222133' 28 | white: '#FFFFFF' 29 | wheat: '#e7d8b1' 30 | black1: '#181715' 31 | khaki: '#DCCD69' 32 | firebrick: '#CE4045' 33 | darkslateblue: '#664477' 34 | lightgray: '#cccccc' 35 | mediumpurple: '#A074C4' 36 | window_colors: 37 | focused: 38 | border: darkslateblue 39 | background: darkslateblue 40 | text: lightgray 41 | indicator: wheat 42 | focused_inactive: 43 | border: wheat 44 | background: wheat 45 | text: black1 46 | indicator: mediumpurple 47 | unfocused: 48 | border: black 49 | background: black 50 | text: darkgray 51 | indicator: mediumpurple 52 | urgent: 53 | border: firebrick 54 | background: firebrick 55 | text: wheat 56 | indicator: khaki 57 | -------------------------------------------------------------------------------- /legacy/themes/seti: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'seti theme by Jody Ribton - based on the seti Atom theme at https://atom.io/themes/seti-ui' 5 | colors: 6 | blue: '#4F99D3' 7 | green: '#9FCA56' 8 | yellow: '#DCCD69' 9 | red: '#CE4045' 10 | orange: '#FF8315' 11 | purple: '#A074C4' 12 | grey: '#1f2326' 13 | white: '#FFFFFF' 14 | dull_white: '#AAAAAA' 15 | base: '#151718' 16 | window_colors: 17 | focused: 18 | border: 'blue' 19 | background: 'blue' 20 | text: 'base' 21 | indicator: 'green' 22 | focused_inactive: 23 | border: 'green' 24 | background: 'green' 25 | text: 'base' 26 | indicator: 'purple' 27 | unfocused: 28 | border: 'grey' 29 | background: 'grey' 30 | text: 'dull_white' 31 | indicator: 'purple' 32 | urgent: 33 | border: 'red' 34 | background: 'red' 35 | text: 'white' 36 | indicator: 'yellow' 37 | bar_colors: 38 | separator: 'dull_white' 39 | background: 'grey' 40 | statusline: 'white' 41 | focused_workspace: 42 | border: 'green' 43 | background: 'green' 44 | text: 'base' 45 | active_workspace: 46 | border: 'yellow' 47 | background: 'yellow' 48 | text: 'base' 49 | inactive_workspace: 50 | border: 'grey' 51 | background: 'grey' 52 | text: 'dull_white' 53 | urgent_workspace: 54 | border: 'red' 55 | background: 'red' 56 | text: 'white' 57 | 58 | 59 | -------------------------------------------------------------------------------- /legacy/themes/slate: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Slate theme by Jody Ribton ' 5 | colors: 6 | # focused 7 | slate: '#586e75' # main color 8 | cream: '#fdf6e3' # focused text color 9 | sky_blue: '#268bd2' # focused indicator color 10 | 11 | # inactive and unfocused 12 | dark_teal: '#073642' # inactive windoww border 13 | darker_teal: '#002b36' # unfocused window border 14 | white_teal: '#93a1a1' # inactive text 15 | grey: '#aea79f' # statusline 16 | 17 | # urgent 18 | red: '#dc322f' # urgent window border 19 | white: '#ffffff' # workspace text 20 | purple: '#77216f' # urgent workspace color 21 | 22 | window_colors: 23 | focused: 24 | border: 'slate' 25 | background: 'slate' 26 | text: 'cream' 27 | indicator: 'sky_blue' 28 | focused_inactive: 29 | border: 'dark_teal' 30 | background: 'dark_teal' 31 | text: 'white_teal' 32 | indicator: 'darker_teal' 33 | unfocused: 34 | border: 'darker_teal' 35 | background: 'darker_teal' 36 | text: 'slate' 37 | indicator: 'darker_teal' 38 | urgent: 39 | border: 'red' 40 | background: 'red' 41 | text: 'cream' 42 | indicator: 'red' 43 | bar_colors: 44 | separator: 'slate' 45 | background: 'darker_teal' 46 | statusline: 'grey' 47 | focused_workspace: 48 | border: 'slate' 49 | background: 'slate' 50 | text: 'white' 51 | active_workspace: 52 | border: 'dark_teal' 53 | background: 'dark_teal' 54 | text: 'white' 55 | inactive_workspace: 56 | border: 'darker_teal' 57 | background: 'darker_teal' 58 | text: 'grey' 59 | urgent_workspace: 60 | border: 'purple' 61 | background: 'purple' 62 | text: 'white' 63 | -------------------------------------------------------------------------------- /legacy/themes/solarized: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Solarized theme by lasers' 5 | colors: 6 | base03: '#002b36' 7 | base02: '#073642' 8 | base01: '#586e75' 9 | base00: '#657b83' 10 | base0: '#839496' 11 | base1: '#93a1a1' 12 | base2: '#eee8d5' 13 | base3: '#fdf6e3' 14 | yellow: '#b58900' 15 | orange: '#cb4b16' 16 | red: '#dc322f' 17 | magenta: '#d33682' 18 | violet: '#6c71c4' 19 | blue: '#268bd2' 20 | cyan: '#2aa198' 21 | green: '#859900' 22 | custom: '#1c5766' 23 | window_colors: 24 | focused: 25 | border: 'green' 26 | background: 'green' 27 | text: 'base3' 28 | indicator: 'violet' 29 | focused_inactive: 30 | border: 'base02' 31 | background: 'base02' 32 | text: 'base2' 33 | indicator: 'violet' 34 | unfocused: 35 | border: 'base02' 36 | background: 'base02' 37 | text: 'base1' 38 | indicator: 'base01' 39 | urgent: 40 | border: 'magenta' 41 | background: 'magenta' 42 | text: 'base3' 43 | indicator: 'red' 44 | bar_colors: 45 | separator: 'red' 46 | background: 'base03' 47 | statusline: 'blue' 48 | focused_workspace: 49 | border: 'base3' 50 | background: 'green' 51 | text: 'base3' 52 | active_workspace: 53 | border: 'base3' 54 | background: 'violet' 55 | text: 'base3' 56 | inactive_workspace: 57 | border: 'base01' 58 | background: 'base1' 59 | text: 'base03' 60 | urgent_workspace: 61 | border: 'magenta' 62 | background: 'magenta' 63 | text: 'base3' 64 | -------------------------------------------------------------------------------- /legacy/themes/tomorrow-night-80s: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | colors: 5 | background: '#2d2d2d' 6 | current_line: '#393939' 7 | selection: '#515151' 8 | foreground: '#cccccc' 9 | comment: '#999999' 10 | red: '#f2777a' 11 | orange: '#f99157' 12 | yellow: '#ffcc66' 13 | green: '#99cc99' 14 | aqua: '#66cccc' 15 | blue: '#6699cc' 16 | purple: '#cc99cc' 17 | 18 | meta: 19 | description: 'Tomorrow Night 80s theme by jmfurlott ' 20 | window_colors: 21 | focused: 22 | border: 'green' 23 | background: 'green' 24 | text: '#000000' 25 | indicator: 'background' 26 | focused_inactive: 27 | border: 'current_line' 28 | background: 'current_line' 29 | text: '#888888' 30 | indicator: '#292d2e' 31 | unfocused: 32 | border: 'background' 33 | background: 'background' 34 | text: 'comment' 35 | indicator: '#292d2e' 36 | urgent: 37 | border: '#2f343a' 38 | background: '#900000' 39 | text: '#ffffff' 40 | indicator: '#900000' 41 | bar_colors: 42 | separator: 'selection' 43 | background: 'background' 44 | statusline: 'foreground' 45 | focused_workspace: 46 | border: 'green' 47 | background: 'green' 48 | text: '#000000' 49 | active_workspace: 50 | border: '#333333' 51 | background: '#333333' 52 | text: '#ffffff' 53 | inactive_workspace: 54 | border: 'background' 55 | background: 'background' 56 | text: 'comment' 57 | urgent_workspace: 58 | border: 'red' 59 | background: 'red' 60 | text: '#ffffff' 61 | -------------------------------------------------------------------------------- /legacy/themes/ubuntu: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Ubuntu theme by lasers' 6 | window_colors: 7 | focused: 8 | border: '#dd4814' 9 | background: '#dd4814' 10 | text: '#ffffff' 11 | indicator: '#902a07' 12 | focused_inactive: 13 | border: '#5e2750' 14 | background: '#5e2750' 15 | text: '#aea79f' 16 | indicator: '#5e2750' 17 | unfocused: 18 | border: '#5e2750' 19 | background: '#5e2750' 20 | text: '#aea79f' 21 | indicator: '#5e2750' 22 | urgent: 23 | border: '#77216f' 24 | background: '#77216f' 25 | text: '#ffffff' 26 | indicator: '#efb73e' 27 | bar_colors: 28 | separator: '#333333' 29 | background: '#2c001e' 30 | statusline: '#aea79f' 31 | focused_workspace: 32 | border: '#dd4814' 33 | background: '#dd4814' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#902a07' 37 | background: '#902a07' 38 | text: '#aea79f' 39 | inactive_workspace: 40 | border: '#902a07' 41 | background: '#902a07' 42 | text: '#aea79f' 43 | urgent_workspace: 44 | border: '#77216f' 45 | background: '#77216f' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate lazy_static; 3 | extern crate linked_hash_map; 4 | use std::env; 5 | use std::fs; 6 | use std::fs::create_dir_all; 7 | use std::fs::File; 8 | use std::io::prelude::*; 9 | use std::io::Error; 10 | use std::path::Path; 11 | use std::process; 12 | use std::process::{Command, Stdio}; 13 | use std::time::{SystemTime, UNIX_EPOCH}; 14 | extern crate includedir; 15 | extern crate phf; 16 | 17 | extern crate yaml_rust; 18 | use yaml_rust::{YamlEmitter, YamlLoader}; 19 | 20 | extern crate clap; 21 | use clap::{App, Arg}; 22 | 23 | mod theme; 24 | mod writer; 25 | 26 | include!(concat!(env!("OUT_DIR"), "/data.rs")); 27 | 28 | fn exit_error(msg: &str) { 29 | writeln!(&mut std::io::stderr(), "{}", msg).unwrap(); 30 | process::exit(1); 31 | } 32 | 33 | fn get_run_tmp_dir() -> String { 34 | let start = SystemTime::now(); 35 | let elapsed = start 36 | .duration_since(UNIX_EPOCH) 37 | .expect("Time went backwards"); 38 | let sec = (elapsed.as_secs() as u64) + (elapsed.subsec_nanos() as u64) / 1000_000; 39 | let mut tmp_dir = env::temp_dir(); 40 | tmp_dir.push("i3-style"); 41 | tmp_dir.push(sec.to_string()); 42 | create_dir_all(tmp_dir.as_path()).expect("Could not create temporary directory"); 43 | String::from(tmp_dir.to_str().unwrap()) 44 | } 45 | 46 | fn get_system_config_path() -> Option { 47 | let home = String::from(env::var("HOME").unwrap()); 48 | 49 | let config_path = vec![ 50 | format!("{}/{}", home, ".i3/config"), 51 | format!("{}/{}", home, ".config/i3/config"), 52 | String::from("/etc/i3/config"), 53 | String::from("/etc/xdg/i3/config"), 54 | ]; 55 | 56 | for p in config_path { 57 | if Path::new(&p).exists() { 58 | return Some(p); 59 | } 60 | } 61 | 62 | None 63 | } 64 | 65 | fn validate_config(path: &String) -> Result { 66 | let cmd = Command::new("i3") 67 | .arg("-C") 68 | .arg("-c") 69 | .arg(path) 70 | .stdout(Stdio::null()) 71 | .stderr(Stdio::null()) 72 | .status()?; 73 | 74 | Ok(cmd.success()) 75 | } 76 | 77 | fn validate_config_or_exit(path: &String) { 78 | match validate_config(&path) { 79 | Ok(result) => { 80 | if !result { 81 | writeln!( 82 | &mut std::io::stderr(), 83 | "Could not validate config.\nUse `i3 -C -c {}` to see validation errors.", 84 | path 85 | ).unwrap(); 86 | process::exit(1); 87 | } 88 | } 89 | Err(err) => { 90 | eprintln!( 91 | "Could not validate config with `i3 -C -c {}` (is i3 in the PATH?) {}", 92 | path, err 93 | ); 94 | process::exit(1); 95 | } 96 | } 97 | } 98 | 99 | fn get_embedded_theme(name: &str) -> Option { 100 | let file = format!("./themes/{}", name); 101 | 102 | if !FILES.is_available(&file) { 103 | return None; 104 | } 105 | 106 | let contents = String::from_utf8( 107 | FILES 108 | .get(&format!("{}/{}", "./themes", name)) 109 | .unwrap() 110 | .to_vec(), 111 | ) 112 | .expect("Theme yaml is not utf-8"); 113 | 114 | let docs = 115 | YamlLoader::load_from_str(contents.as_str()).expect("Could not parse yaml for theme"); 116 | let doc = &docs[0]; 117 | 118 | Some(theme::from_yaml(&doc)) 119 | } 120 | 121 | fn get_theme_from_path(path: String) -> Result { 122 | let mut file = File::open(path)?; 123 | 124 | let mut contents = String::new(); 125 | file.read_to_string(&mut contents)?; 126 | 127 | let docs = 128 | YamlLoader::load_from_str(contents.as_str()).expect("Could not parse yaml for theme"); 129 | let doc = &docs[0]; 130 | 131 | Ok(theme::from_yaml(&doc)) 132 | } 133 | 134 | fn list_themes() { 135 | println!("\nAvailable themes:\n"); 136 | let prefix_count = "./themes/".chars().count(); 137 | 138 | for file in FILES.file_names() { 139 | let contents = 140 | String::from_utf8(FILES.get(file).unwrap().to_vec()).expect("Theme yaml is not utf-8"); 141 | 142 | let docs = 143 | YamlLoader::load_from_str(contents.as_str()).expect("Could not parse yaml for theme"); 144 | let doc = &docs[0]; 145 | 146 | let description = doc["meta"]["description"] 147 | .as_str() 148 | .expect("Theme doesn't have a description"); 149 | 150 | let entry: String = file.chars().skip(prefix_count).collect(); 151 | let entry = format!(" {:width$} - {}", entry, description, width = 18); 152 | println!("{}", entry); 153 | } 154 | } 155 | 156 | fn main() { 157 | let mut cli = App::new("i3-style") 158 | .version("1.0") 159 | .about("Make your i3 config a bit more stylish") 160 | .arg(Arg::with_name("theme") 161 | .help("The theme to use") 162 | .index(1) 163 | ) 164 | .arg(Arg::with_name("config") 165 | .short("c") 166 | .long("config") 167 | .value_name("file") 168 | .help("The config file the theme should be applied to. Defaults to the default i3 location.") 169 | .takes_value(true) 170 | ) 171 | .arg(Arg::with_name("output") 172 | .short("o") 173 | .long("output") 174 | .value_name("file") 175 | .help("Apply the theme, attempt to validate the result, and write it to ") 176 | .takes_value(true) 177 | ) 178 | .arg(Arg::with_name("save") 179 | .short("s") 180 | .long("save") 181 | .help("Set the output file to the path of the input file") 182 | ) 183 | .arg(Arg::with_name("reload") 184 | .short("r") 185 | .long("reload") 186 | .help("Apply the theme by reloading the config") 187 | ) 188 | .arg(Arg::with_name("list-all") 189 | .short("l") 190 | .long("list-all") 191 | .help("Print a list of all available themes") 192 | ) 193 | .arg(Arg::with_name("to-theme") 194 | .short("t") 195 | .long("to-theme") 196 | .value_name("file") 197 | .help("Prints an i3-style theme based on the given config suitable for sharing with others") 198 | .takes_value(true) 199 | .default_value("") 200 | ); 201 | 202 | let app = cli.clone().get_matches(); 203 | 204 | if app.is_present("list-all") { 205 | list_themes(); 206 | process::exit(0); 207 | } 208 | 209 | if app.occurrences_of("to-theme") > 0 { 210 | let mut config: String = String::from(app.value_of("to-theme").unwrap()); 211 | 212 | if config.is_empty() { 213 | config = match app.value_of("config") { 214 | Some(c) => String::from(c), 215 | None => match get_system_config_path() { 216 | Some(c) => c, 217 | None => { 218 | exit_error("Could not find i3 config"); 219 | // not reached 220 | String::from("") 221 | } 222 | }, 223 | } 224 | } 225 | 226 | validate_config_or_exit(&config); 227 | 228 | let theme = theme::from_config_file(&config); 229 | 230 | let yaml = theme.to_yaml_with_colors(); 231 | 232 | let mut out_str = String::new(); 233 | { 234 | let mut emitter = YamlEmitter::new(&mut out_str); 235 | emitter.dump(&yaml).unwrap(); // dump the YAML object to a String 236 | } 237 | println!("{}", out_str); 238 | 239 | process::exit(0); 240 | } 241 | 242 | if !app.is_present("theme") { 243 | if app.args.is_empty() { 244 | cli.print_help().unwrap(); 245 | process::exit(0); 246 | } else { 247 | println!("{}\n", app.usage()); 248 | println!("Select a theme as the first argument. Use `--list-all` to see the themes."); 249 | process::exit(1); 250 | } 251 | } 252 | 253 | let config = match app.value_of("config") { 254 | Some(c) => Some(String::from(c)), 255 | None => get_system_config_path(), 256 | }; 257 | 258 | if config.is_none() { 259 | exit_error("Could not find i3 config"); 260 | } 261 | let config = config.unwrap(); 262 | 263 | validate_config_or_exit(&config); 264 | 265 | let theme_name = app.value_of("theme").unwrap(); 266 | let mut theme: Option = get_embedded_theme(theme_name); 267 | 268 | if theme.is_none() { 269 | // TODO get theme from the filesystem 270 | theme = match get_theme_from_path(theme_name.to_string()) { 271 | Ok(t) => Some(t), 272 | Err(e) => { 273 | exit_error(format!("Could not open theme: {} - {}\n Use `i3-style --list-all` to see the available themes.", theme_name, e).as_str()); 274 | None 275 | } 276 | } 277 | } 278 | let theme = theme.unwrap(); 279 | 280 | let output = if app.value_of("output").is_some() { 281 | app.value_of("output") 282 | } else if app.is_present("save") { 283 | Some(config.as_str().clone()) 284 | } else { 285 | None 286 | }; 287 | 288 | if output.is_some() { 289 | let output = output.unwrap(); 290 | let i3_style_tmp = get_run_tmp_dir(); 291 | let tmp_output = format!("{}/{}", i3_style_tmp, "config-output"); 292 | let tmp_input = format!("{}/{}", i3_style_tmp, "config-input"); 293 | // 1. write the new config in the tmp folder 294 | writer::write_config(&config, Some(&tmp_output), &theme); 295 | // 2. copy the config to the tmp folder 296 | writeln!( 297 | &mut std::io::stderr(), 298 | "saving config at {} to {}", 299 | &config, 300 | &tmp_input 301 | ).unwrap(); 302 | fs::copy(&config, &tmp_input).unwrap(); 303 | // 3. copy the new config to the config location 304 | fs::copy(&tmp_output, output).unwrap(); 305 | } else { 306 | writer::write_config(&config, None, &theme); 307 | } 308 | 309 | if app.is_present("reload") { 310 | if env::var_os("WAYLAND_DISPLAY").is_some() { 311 | let cmd = Command::new("swaymsg") 312 | .arg("reload") 313 | .stdout(Stdio::null()) 314 | .stderr(Stdio::null()) 315 | .status(); 316 | 317 | match cmd { 318 | Ok(_) => { 319 | // nop 320 | } 321 | Err(err) => { 322 | writeln!( 323 | &mut std::io::stderr(), 324 | "Could not reload config with swaymsg: {}", 325 | err 326 | ).unwrap(); 327 | process::exit(1); 328 | } 329 | } 330 | } else { 331 | let cmd = Command::new("i3-msg") 332 | .arg("reload") 333 | .stdout(Stdio::null()) 334 | .stderr(Stdio::null()) 335 | .status(); 336 | 337 | match cmd { 338 | Ok(_) => { 339 | // nop 340 | } 341 | Err(err) => { 342 | writeln!( 343 | &mut std::io::stderr(), 344 | "Could not reload config with i3-msg: {}", 345 | err 346 | ).unwrap(); 347 | process::exit(1); 348 | } 349 | } 350 | } 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /src/theme.rs: -------------------------------------------------------------------------------- 1 | extern crate colornamer; 2 | extern crate linked_hash_map; 3 | extern crate regex; 4 | extern crate yaml_rust; 5 | 6 | use linked_hash_map::LinkedHashMap; 7 | use std::fs::File; 8 | use std::io::prelude::*; 9 | use std::io::BufReader; 10 | use yaml_rust::Yaml; 11 | 12 | #[derive(Debug)] 13 | pub struct ColorGroup { 14 | pub border: Option, 15 | pub background: Option, 16 | pub text: Option, 17 | pub indicator: Option, 18 | } 19 | 20 | impl ColorGroup { 21 | fn set_part(&mut self, part: &str, value: Option) { 22 | match part { 23 | "border" => self.border = value, 24 | "background" => self.background = value, 25 | "text" => self.text = value, 26 | "indicator" => self.indicator = value, 27 | _ => panic!("got unknown part: {}", part), 28 | } 29 | } 30 | 31 | fn empty() -> ColorGroup { 32 | ColorGroup { 33 | border: None, 34 | background: None, 35 | text: None, 36 | indicator: None, 37 | } 38 | } 39 | 40 | fn to_yaml(&self, color_map: &ColorMap) -> Yaml { 41 | let mut group_yaml: LinkedHashMap = LinkedHashMap::new(); 42 | if self.border.is_some() { 43 | group_yaml.insert( 44 | Yaml::String("border".to_string()), 45 | Yaml::String(color_map.get_color(&self.border.as_ref().unwrap().to_string())), 46 | ); 47 | } 48 | if self.background.is_some() { 49 | group_yaml.insert( 50 | Yaml::String("background".to_string()), 51 | Yaml::String(color_map.get_color(&self.background.as_ref().unwrap().to_string())), 52 | ); 53 | } 54 | if self.text.is_some() { 55 | group_yaml.insert( 56 | Yaml::String("text".to_string()), 57 | Yaml::String(color_map.get_color(&self.text.as_ref().unwrap().to_string())), 58 | ); 59 | } 60 | if self.indicator.is_some() { 61 | group_yaml.insert( 62 | Yaml::String("indicator".to_string()), 63 | Yaml::String(color_map.get_color(&self.indicator.as_ref().unwrap().to_string())), 64 | ); 65 | } 66 | Yaml::Hash(group_yaml) 67 | } 68 | } 69 | 70 | #[derive(Debug)] 71 | pub struct WindowColors { 72 | pub focused: Option, 73 | pub focused_inactive: Option, 74 | pub unfocused: Option, 75 | pub urgent: Option, 76 | } 77 | 78 | #[derive(Debug)] 79 | pub struct BarColors { 80 | pub separator: Option, 81 | pub background: Option, 82 | pub statusline: Option, 83 | pub focused_workspace: Option, 84 | pub active_workspace: Option, 85 | pub inactive_workspace: Option, 86 | pub urgent_workspace: Option, 87 | } 88 | 89 | #[derive(Debug)] 90 | pub struct Theme { 91 | pub description: Option, 92 | pub window_colors: Option, 93 | pub bar_colors: Option, 94 | } 95 | 96 | #[derive(Debug)] 97 | struct ColorMap { 98 | colors: LinkedHashMap, 99 | } 100 | 101 | impl ColorMap { 102 | pub fn new() -> ColorMap { 103 | ColorMap { 104 | colors: LinkedHashMap::new(), 105 | } 106 | } 107 | 108 | fn has_color(&self, hex: &String) -> bool { 109 | for (_key, value) in &self.colors { 110 | if hex == value { 111 | return true; 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | fn get_color(&self, hex: &String) -> String { 118 | let hex_uc = hex.to_uppercase(); 119 | for (key, value) in &self.colors { 120 | if &hex_uc == value { 121 | return key.to_string(); 122 | } 123 | } 124 | return hex.to_string(); 125 | } 126 | 127 | fn add_hex(&mut self, hex: &Option) { 128 | lazy_static! { 129 | static ref RE: regex::Regex = regex::Regex::new(r"-(\d+)$").unwrap(); 130 | } 131 | 132 | match hex { 133 | &Some(ref h) => { 134 | let h = h.to_uppercase(); 135 | if self.has_color(&h) { 136 | return; 137 | } 138 | 139 | let mut color_name = 140 | colornamer::name_color_hex(h.as_str(), colornamer::Colors::HTML); 141 | let ref mut colors = self.colors; 142 | while colors.contains_key(&color_name) { 143 | if !RE.is_match(&color_name) { 144 | color_name = color_name + "-1"; 145 | } else { 146 | let cpy = color_name.clone(); 147 | let captures = RE.captures(cpy.as_str()).unwrap().get(1).unwrap(); 148 | let num: String = color_name.chars().skip(captures.start()).collect(); 149 | let num: u32 = num.parse().unwrap(); 150 | let num = num + 1; 151 | color_name = color_name.chars().take(captures.start()).collect(); 152 | color_name = color_name + num.to_string().as_str(); 153 | } 154 | } 155 | colors.insert(color_name.to_string(), h.to_string()); 156 | } 157 | &None => (), 158 | } 159 | } 160 | 161 | fn add_color_group(&mut self, group: &Option) { 162 | match group { 163 | &Some(ref g) => { 164 | self.add_hex(&g.border); 165 | self.add_hex(&g.background); 166 | self.add_hex(&g.text); 167 | self.add_hex(&g.indicator); 168 | } 169 | &None => (), 170 | } 171 | } 172 | } 173 | 174 | impl Theme { 175 | fn ensure_window_colors(&mut self) { 176 | if self.window_colors.is_none() { 177 | self.window_colors = Some(WindowColors { 178 | focused: None, 179 | focused_inactive: None, 180 | unfocused: None, 181 | urgent: None, 182 | }); 183 | } 184 | } 185 | 186 | fn ensure_bar_colors(&mut self) { 187 | if self.bar_colors.is_none() { 188 | self.bar_colors = Some(BarColors { 189 | background: None, 190 | separator: None, 191 | statusline: None, 192 | active_workspace: None, 193 | focused_workspace: None, 194 | inactive_workspace: None, 195 | urgent_workspace: None, 196 | }); 197 | } 198 | } 199 | 200 | pub fn to_yaml_with_colors(self) -> Yaml { 201 | let mut colormap = ColorMap::new(); 202 | 203 | let ref bar_colors = self.bar_colors; 204 | match bar_colors { 205 | &Some(ref bc) => { 206 | colormap.add_hex(&bc.separator); 207 | colormap.add_hex(&bc.background); 208 | colormap.add_hex(&bc.statusline); 209 | colormap.add_color_group(&bc.focused_workspace); 210 | colormap.add_color_group(&bc.active_workspace); 211 | colormap.add_color_group(&bc.inactive_workspace); 212 | colormap.add_color_group(&bc.urgent_workspace); 213 | } 214 | &None => (), 215 | } 216 | let ref window_colors = self.window_colors; 217 | match window_colors { 218 | &Some(ref wc) => { 219 | colormap.add_color_group(&wc.focused); 220 | colormap.add_color_group(&wc.focused_inactive); 221 | colormap.add_color_group(&wc.unfocused); 222 | colormap.add_color_group(&wc.urgent); 223 | } 224 | &None => (), 225 | } 226 | 227 | let mut toplevel_yaml: LinkedHashMap = LinkedHashMap::new(); 228 | let mut colormap_yaml: LinkedHashMap = LinkedHashMap::new(); 229 | let mut metamap_yaml: LinkedHashMap = LinkedHashMap::new(); 230 | let mut window_colors_yaml: LinkedHashMap = LinkedHashMap::new(); 231 | let mut bar_colors_yaml: LinkedHashMap = LinkedHashMap::new(); 232 | 233 | metamap_yaml.insert( 234 | Yaml::String("description".to_string()), 235 | Yaml::String(self.description.unwrap()), 236 | ); 237 | 238 | for (key, value) in &colormap.colors { 239 | colormap_yaml.insert( 240 | Yaml::String(key.to_string()), 241 | Yaml::String(value.to_string()), 242 | ); 243 | } 244 | 245 | match window_colors { 246 | &Some(ref wc) => { 247 | if wc.focused.is_some() { 248 | window_colors_yaml.insert( 249 | Yaml::String("focused".to_string()), 250 | wc.focused.as_ref().unwrap().to_yaml(&colormap), 251 | ); 252 | } 253 | if wc.focused_inactive.is_some() { 254 | window_colors_yaml.insert( 255 | Yaml::String("focused_inactive".to_string()), 256 | wc.focused_inactive.as_ref().unwrap().to_yaml(&colormap), 257 | ); 258 | } 259 | if wc.unfocused.is_some() { 260 | window_colors_yaml.insert( 261 | Yaml::String("unfocused".to_string()), 262 | wc.unfocused.as_ref().unwrap().to_yaml(&colormap), 263 | ); 264 | } 265 | if wc.urgent.is_some() { 266 | window_colors_yaml.insert( 267 | Yaml::String("urgent".to_string()), 268 | wc.urgent.as_ref().unwrap().to_yaml(&colormap), 269 | ); 270 | } 271 | } 272 | &None => (), 273 | } 274 | 275 | match bar_colors { 276 | &Some(ref bc) => { 277 | if bc.background.is_some() { 278 | bar_colors_yaml.insert( 279 | Yaml::String("background".to_string()), 280 | Yaml::String( 281 | colormap.get_color(&bc.background.as_ref().unwrap().to_string()), 282 | ), 283 | ); 284 | } 285 | if bc.statusline.is_some() { 286 | bar_colors_yaml.insert( 287 | Yaml::String("statusline".to_string()), 288 | Yaml::String( 289 | colormap.get_color(&bc.statusline.as_ref().unwrap().to_string()), 290 | ), 291 | ); 292 | } 293 | if bc.separator.is_some() { 294 | bar_colors_yaml.insert( 295 | Yaml::String("separator".to_string()), 296 | Yaml::String( 297 | colormap.get_color(&bc.separator.as_ref().unwrap().to_string()), 298 | ), 299 | ); 300 | } 301 | if bc.focused_workspace.is_some() { 302 | bar_colors_yaml.insert( 303 | Yaml::String("focused_workspace".to_string()), 304 | bc.focused_workspace.as_ref().unwrap().to_yaml(&colormap), 305 | ); 306 | } 307 | if bc.active_workspace.is_some() { 308 | bar_colors_yaml.insert( 309 | Yaml::String("active_workspace".to_string()), 310 | bc.active_workspace.as_ref().unwrap().to_yaml(&colormap), 311 | ); 312 | } 313 | if bc.urgent_workspace.is_some() { 314 | bar_colors_yaml.insert( 315 | Yaml::String("urgent_workspace".to_string()), 316 | bc.urgent_workspace.as_ref().unwrap().to_yaml(&colormap), 317 | ); 318 | } 319 | } 320 | &None => (), 321 | } 322 | 323 | toplevel_yaml.insert(Yaml::String("meta".to_string()), Yaml::Hash(metamap_yaml)); 324 | toplevel_yaml.insert( 325 | Yaml::String("colors".to_string()), 326 | Yaml::Hash(colormap_yaml), 327 | ); 328 | toplevel_yaml.insert( 329 | Yaml::String("window_colors".to_string()), 330 | Yaml::Hash(window_colors_yaml), 331 | ); 332 | toplevel_yaml.insert( 333 | Yaml::String("bar_colors".to_string()), 334 | Yaml::Hash(bar_colors_yaml), 335 | ); 336 | 337 | Yaml::Hash(toplevel_yaml) 338 | } 339 | } 340 | 341 | fn parse_color(doc: &Yaml, color_spec: &Yaml) -> Option { 342 | if color_spec.as_str().is_none() { 343 | return Option::None; 344 | } 345 | 346 | let color_spec = color_spec.as_str().unwrap(); 347 | let colors = &doc["colors"]; 348 | 349 | match colors[color_spec].as_str() { 350 | Some(color) => Option::from(color.to_string()), 351 | None => Option::from(color_spec.to_string()), 352 | } 353 | } 354 | 355 | fn parse_color_group(doc: &Yaml, top_key: String, bottom_key: String) -> Option { 356 | let top_key = top_key.as_str(); 357 | let bottom_key = bottom_key.as_str(); 358 | 359 | if doc[top_key][bottom_key].as_hash().is_none() { 360 | return Option::None; 361 | } 362 | 363 | let group_hash = &doc[top_key][bottom_key]; 364 | 365 | let mut group = ColorGroup { 366 | border: Option::None, 367 | background: Option::None, 368 | text: Option::None, 369 | indicator: Option::None, 370 | }; 371 | 372 | for &part in vec!["border", "background", "text", "indicator"].iter() { 373 | group.set_part(part, parse_color(&doc, &group_hash[part])); 374 | } 375 | 376 | Option::from(group) 377 | } 378 | 379 | fn parse_window_colors(doc: &Yaml) -> Option { 380 | if doc["window_colors"].as_hash().is_none() { 381 | return Option::None; 382 | } 383 | 384 | Option::from(WindowColors { 385 | focused: parse_color_group(doc, "window_colors".to_string(), "focused".to_string()), 386 | focused_inactive: parse_color_group( 387 | doc, 388 | "window_colors".to_string(), 389 | "focused_inactive".to_string(), 390 | ), 391 | unfocused: parse_color_group(doc, "window_colors".to_string(), "unfocused".to_string()), 392 | urgent: parse_color_group(doc, "window_colors".to_string(), "urgent".to_string()), 393 | }) 394 | } 395 | 396 | fn parse_bar_colors(doc: &Yaml) -> Option { 397 | let bar_colors = &doc["bar_colors"]; 398 | 399 | if bar_colors.as_hash().is_none() { 400 | return Option::None; 401 | } 402 | 403 | Option::from(BarColors { 404 | separator: parse_color(&doc, &bar_colors["separator"]), 405 | background: parse_color(&doc, &bar_colors["background"]), 406 | statusline: parse_color(&doc, &bar_colors["statusline"]), 407 | focused_workspace: parse_color_group( 408 | doc, 409 | "bar_colors".to_string(), 410 | "focused_workspace".to_string(), 411 | ), 412 | active_workspace: parse_color_group( 413 | doc, 414 | "bar_colors".to_string(), 415 | "active_workspace".to_string(), 416 | ), 417 | inactive_workspace: parse_color_group( 418 | doc, 419 | "bar_colors".to_string(), 420 | "inactive_workspace".to_string(), 421 | ), 422 | urgent_workspace: parse_color_group( 423 | doc, 424 | "bar_colors".to_string(), 425 | "urgent_workspace".to_string(), 426 | ), 427 | }) 428 | } 429 | 430 | pub fn from_yaml(doc: &Yaml) -> Theme { 431 | let description = match doc["meta"]["description"].as_str() { 432 | Some(d) => Option::from(String::from(d)), 433 | None => Option::None, 434 | }; 435 | 436 | Theme { 437 | description: description, 438 | window_colors: parse_window_colors(doc), 439 | bar_colors: parse_bar_colors(doc), 440 | } 441 | } 442 | 443 | fn from_config_reader(input: BufReader) -> Theme { 444 | let mut theme = Theme { 445 | description: Some("AUTOMATICALLY GENERATED THEME".to_string()), 446 | window_colors: None, 447 | bar_colors: None, 448 | }; 449 | 450 | let mut in_bar = false; 451 | let mut in_colors = false; 452 | 453 | for line in input.lines() { 454 | let line = line.unwrap(); 455 | let line = line.trim(); 456 | let mut vec: Vec<&str> = Vec::new(); 457 | 458 | for word in line.split(' ') { 459 | if word != "" { 460 | vec.push(word); 461 | } 462 | } 463 | 464 | if vec.len() == 0 || vec[0].starts_with("#") { 465 | continue; 466 | } 467 | 468 | if in_colors && vec[0] == "}" { 469 | in_colors = false; 470 | continue; 471 | } else if in_bar && vec[0] == "}" { 472 | in_bar = false; 473 | continue; 474 | } else if vec[0] == "bar" { 475 | in_bar = true; 476 | continue; 477 | } else if in_bar && vec[0] == "colors" { 478 | in_colors = true; 479 | continue; 480 | } 481 | 482 | if in_colors { 483 | match vec[0] { 484 | "separator" => { 485 | theme.ensure_bar_colors(); 486 | let mut bar_colors = theme.bar_colors.unwrap(); 487 | bar_colors.separator = Some(vec[1].to_string()); 488 | theme.bar_colors = Some(bar_colors); 489 | } 490 | "background" => { 491 | theme.ensure_bar_colors(); 492 | let mut bar_colors = theme.bar_colors.unwrap(); 493 | bar_colors.background = Some(vec[1].to_string()); 494 | theme.bar_colors = Some(bar_colors); 495 | } 496 | "statusline" => { 497 | theme.ensure_bar_colors(); 498 | let mut bar_colors = theme.bar_colors.unwrap(); 499 | bar_colors.statusline = Some(vec[1].to_string()); 500 | theme.bar_colors = Some(bar_colors); 501 | } 502 | "focused_workspace" => { 503 | theme.ensure_bar_colors(); 504 | let mut bar_colors = theme.bar_colors.unwrap(); 505 | let mut group = bar_colors.focused_workspace.unwrap_or(ColorGroup::empty()); 506 | group.border = Some(vec[1].to_string()); 507 | group.background = Some(vec[2].to_string()); 508 | if vec.get(3).is_some() { 509 | group.text = Some(vec[3].to_string()); 510 | } 511 | bar_colors.focused_workspace = Some(group); 512 | theme.bar_colors = Some(bar_colors); 513 | } 514 | "inactive_workspace" => { 515 | theme.ensure_bar_colors(); 516 | let mut bar_colors = theme.bar_colors.unwrap(); 517 | let mut group = bar_colors.inactive_workspace.unwrap_or(ColorGroup::empty()); 518 | group.border = Some(vec[1].to_string()); 519 | group.background = Some(vec[2].to_string()); 520 | if vec.get(3).is_some() { 521 | group.text = Some(vec[3].to_string()); 522 | } 523 | bar_colors.inactive_workspace = Some(group); 524 | theme.bar_colors = Some(bar_colors); 525 | } 526 | "urgent_workspace" => { 527 | theme.ensure_bar_colors(); 528 | let mut bar_colors = theme.bar_colors.unwrap(); 529 | let mut group = bar_colors.urgent_workspace.unwrap_or(ColorGroup::empty()); 530 | group.border = Some(vec[1].to_string()); 531 | group.background = Some(vec[2].to_string()); 532 | if vec.get(3).is_some() { 533 | group.text = Some(vec[3].to_string()); 534 | } 535 | bar_colors.urgent_workspace = Some(group); 536 | theme.bar_colors = Some(bar_colors); 537 | } 538 | _ => (), 539 | }; 540 | } else if !in_bar { 541 | match vec[0] { 542 | "client.focused" => { 543 | theme.ensure_window_colors(); 544 | let mut window_colors = theme.window_colors.unwrap(); 545 | let mut group = window_colors.focused.unwrap_or(ColorGroup::empty()); 546 | 547 | group.border = Some(vec[1].to_string()); 548 | group.background = Some(vec[2].to_string()); 549 | group.text = Some(vec[3].to_string()); 550 | if vec.get(4).is_some() { 551 | group.indicator = Some(vec[4].to_string()); 552 | } 553 | 554 | window_colors.focused = Some(group); 555 | theme.window_colors = Some(window_colors); 556 | } 557 | "client.focused_inactive" => { 558 | theme.ensure_window_colors(); 559 | let mut window_colors = theme.window_colors.unwrap(); 560 | let mut group = window_colors 561 | .focused_inactive 562 | .unwrap_or(ColorGroup::empty()); 563 | 564 | group.border = Some(vec[1].to_string()); 565 | group.background = Some(vec[2].to_string()); 566 | group.text = Some(vec[3].to_string()); 567 | if vec.get(4).is_some() { 568 | group.indicator = Some(vec[4].to_string()); 569 | } 570 | 571 | window_colors.focused_inactive = Some(group); 572 | theme.window_colors = Some(window_colors); 573 | } 574 | "client.unfocused" => { 575 | theme.ensure_window_colors(); 576 | let mut window_colors = theme.window_colors.unwrap(); 577 | let mut group = window_colors.unfocused.unwrap_or(ColorGroup::empty()); 578 | 579 | group.border = Some(vec[1].to_string()); 580 | group.background = Some(vec[2].to_string()); 581 | group.text = Some(vec[3].to_string()); 582 | if vec.get(4).is_some() { 583 | group.indicator = Some(vec[4].to_string()); 584 | } 585 | 586 | window_colors.unfocused = Some(group); 587 | theme.window_colors = Some(window_colors); 588 | } 589 | "client.urgent" => { 590 | theme.ensure_window_colors(); 591 | let mut window_colors = theme.window_colors.unwrap(); 592 | let mut group = window_colors.urgent.unwrap_or(ColorGroup::empty()); 593 | 594 | group.border = Some(vec[1].to_string()); 595 | group.background = Some(vec[2].to_string()); 596 | group.text = Some(vec[3].to_string()); 597 | if vec.get(4).is_some() { 598 | group.indicator = Some(vec[4].to_string()); 599 | } 600 | 601 | window_colors.urgent = Some(group); 602 | theme.window_colors = Some(window_colors); 603 | } 604 | _ => (), 605 | }; 606 | } 607 | } 608 | 609 | theme 610 | } 611 | 612 | pub fn from_config_file(input: &String) -> Theme { 613 | let input_file = File::open(input).unwrap(); 614 | let reader = BufReader::new(input_file); 615 | from_config_reader(reader) 616 | } 617 | 618 | #[cfg(test)] 619 | mod tests { 620 | use super::*; 621 | 622 | use std::path::PathBuf; 623 | 624 | #[test] 625 | pub fn test_config_parsing() { 626 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 627 | d.push("test-resources/minimal-config"); 628 | let theme = from_config_file(&d.to_str().unwrap().to_string()); 629 | 630 | assert_eq!(theme.description.unwrap(), "AUTOMATICALLY GENERATED THEME"); 631 | 632 | let wc = theme.window_colors.unwrap(); 633 | 634 | let group = wc.focused.unwrap(); 635 | assert_eq!(group.border, Some("#859900".to_string())); 636 | assert_eq!(group.background, Some("#859900".to_string())); 637 | assert_eq!(group.text, Some("#fdf6e3".to_string())); 638 | assert_eq!(group.indicator, None); 639 | 640 | let group = wc.focused_inactive.unwrap(); 641 | assert_eq!(group.border, Some("#073642".to_string())); 642 | assert_eq!(group.background, Some("#073642".to_string())); 643 | assert_eq!(group.text, Some("#eee8d5".to_string())); 644 | assert_eq!(group.indicator, None); 645 | 646 | let group = wc.unfocused.unwrap(); 647 | assert_eq!(group.border, Some("#073642".to_string())); 648 | assert_eq!(group.background, Some("#073642".to_string())); 649 | assert_eq!(group.text, Some("#93a1a1".to_string())); 650 | assert_eq!(group.indicator, None); 651 | 652 | let group = wc.urgent.unwrap(); 653 | assert_eq!(group.border, Some("#d33682".to_string())); 654 | assert_eq!(group.background, Some("#d33682".to_string())); 655 | assert_eq!(group.text, Some("#fdf6e3".to_string())); 656 | assert_eq!(group.indicator, None); 657 | } 658 | } 659 | -------------------------------------------------------------------------------- /src/writer.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::fs::File; 3 | use std::io::prelude::*; 4 | use std::io::{stdout, BufReader}; 5 | use std::path::Path; 6 | 7 | use theme::Theme; 8 | 9 | fn leading_spaces(string: &String) -> String { 10 | let mut leading = String::new(); 11 | 12 | for c in string.chars() { 13 | if c.is_whitespace() { 14 | leading.push(c); 15 | } else { 16 | break; 17 | } 18 | } 19 | 20 | leading 21 | } 22 | 23 | pub fn write_config(input: &String, output: Option<&String>, theme: &Theme) { 24 | let input_file = File::open(input).unwrap(); 25 | let reader = BufReader::new(input_file); 26 | write_config_from_reader(reader, output, &theme); 27 | } 28 | 29 | pub fn write_config_from_reader(input: BufReader, output: Option<&String>, theme: &Theme) { 30 | let mut writer = match output { 31 | Some(x) => { 32 | let path = Path::new(x.as_str()); 33 | Box::new(File::create(&path).unwrap()) as Box 34 | } 35 | None => Box::new(stdout()) as Box, 36 | }; 37 | 38 | let mut in_bar = false; 39 | let mut in_colors = false; 40 | let mut colors_found = false; 41 | let mut found_bar_colors = HashSet::new(); 42 | let mut found_window_colors = HashSet::new(); 43 | 44 | for line in input.lines() { 45 | let original_line = line.unwrap() + "\n"; 46 | let leading = leading_spaces(&original_line); 47 | // TODO count leading spaces 48 | let line = original_line.trim(); 49 | let mut vec: Vec<&str> = Vec::new(); 50 | 51 | for word in line.split(' ') { 52 | if word != "" { 53 | vec.push(word); 54 | } 55 | } 56 | 57 | if vec.len() > 0 && !vec[0].starts_with("#") { 58 | if in_colors && vec[0] == "}" { 59 | let bar_colors = &theme.bar_colors.as_ref().unwrap(); 60 | if !found_bar_colors.contains("separator") { 61 | bar_colors.separator.as_ref().map(|color| { 62 | writer.write(leading.as_bytes()).unwrap(); 63 | writer.write(leading.as_bytes()).unwrap(); 64 | writer.write(b"separator ").unwrap(); 65 | writer.write(color.as_bytes()).unwrap(); 66 | writer.write(b"\n").unwrap(); 67 | }); 68 | } 69 | 70 | if !found_bar_colors.contains("background") { 71 | bar_colors.background.as_ref().map(|color| { 72 | writer.write(leading.as_bytes()).unwrap(); 73 | writer.write(leading.as_bytes()).unwrap(); 74 | writer.write(b"background ").unwrap(); 75 | writer.write(color.as_bytes()).unwrap(); 76 | writer.write(b"\n").unwrap(); 77 | }); 78 | } 79 | 80 | if !found_bar_colors.contains("statusline") { 81 | bar_colors.statusline.as_ref().map(|color| { 82 | writer.write(leading.as_bytes()).unwrap(); 83 | writer.write(leading.as_bytes()).unwrap(); 84 | writer.write(b"statusline ").unwrap(); 85 | writer.write(color.as_bytes()).unwrap(); 86 | writer.write(b"\n").unwrap(); 87 | }); 88 | } 89 | 90 | let group_names = vec![ 91 | "focused_workspace", 92 | "active_workspace", 93 | "inactive_workspace", 94 | "urgent_workspace", 95 | ]; 96 | for group_name in &group_names { 97 | if found_bar_colors.contains(&group_name.to_string()) { 98 | continue; 99 | } 100 | let group = match group_name.as_ref() { 101 | "focused_workspace" => bar_colors.focused_workspace.as_ref(), 102 | "active_workspace" => bar_colors.active_workspace.as_ref(), 103 | "inactive_workspace" => bar_colors.inactive_workspace.as_ref(), 104 | "urgent_workspace" => bar_colors.urgent_workspace.as_ref(), 105 | _ => panic!("not reached"), 106 | }; 107 | if group.is_none() { 108 | continue; 109 | } 110 | 111 | let group = group.unwrap(); 112 | 113 | if group.border.is_none() || group.background.is_none() || group.text.is_none() 114 | { 115 | continue; 116 | } 117 | 118 | writer.write(leading.as_bytes()).unwrap(); 119 | writer.write(leading.as_bytes()).unwrap(); 120 | writer.write(group_name.as_bytes()).unwrap(); 121 | writer.write(b" ").unwrap(); 122 | writer 123 | .write(group.border.as_ref().unwrap().as_bytes()) 124 | .unwrap(); 125 | writer.write(b" ").unwrap(); 126 | writer 127 | .write(group.background.as_ref().unwrap().as_bytes()) 128 | .unwrap(); 129 | writer.write(b" ").unwrap(); 130 | writer 131 | .write(group.text.as_ref().unwrap().as_bytes()) 132 | .unwrap(); 133 | writer.write(b" ").unwrap(); 134 | 135 | match group.indicator { 136 | Some(ref color) => { 137 | writer.write(b" ").unwrap(); 138 | writer.write(color.as_bytes()).unwrap(); 139 | () 140 | } 141 | None => (), 142 | }; 143 | 144 | writer.write(b"\n").unwrap(); 145 | } 146 | 147 | in_colors = false; 148 | found_bar_colors.clear(); 149 | writer.write(original_line.as_bytes()).unwrap(); 150 | continue; 151 | } else if in_bar && vec[0] == "}" { 152 | let bar_colors = &theme.bar_colors.as_ref().unwrap(); 153 | if !colors_found { 154 | writer.write(b" colors {\n").unwrap(); 155 | bar_colors.separator.as_ref().map(|color| { 156 | writer.write(b" separator ").unwrap(); 157 | writer.write(color.as_bytes()).unwrap(); 158 | writer.write(b"\n").unwrap(); 159 | }); 160 | bar_colors.background.as_ref().map(|color| { 161 | writer.write(b" background ").unwrap(); 162 | writer.write(color.as_bytes()).unwrap(); 163 | writer.write(b"\n").unwrap(); 164 | }); 165 | bar_colors.statusline.as_ref().map(|color| { 166 | writer.write(b" statusline ").unwrap(); 167 | writer.write(color.as_bytes()).unwrap(); 168 | writer.write(b"\n").unwrap(); 169 | }); 170 | 171 | let group_names = vec![ 172 | "focused_workspace", 173 | "active_workspace", 174 | "inactive_workspace", 175 | "urgent_workspace", 176 | ]; 177 | for group_name in &group_names { 178 | let group = match group_name.as_ref() { 179 | "focused_workspace" => bar_colors.focused_workspace.as_ref(), 180 | "active_workspace" => bar_colors.active_workspace.as_ref(), 181 | "inactive_workspace" => bar_colors.inactive_workspace.as_ref(), 182 | "urgent_workspace" => bar_colors.urgent_workspace.as_ref(), 183 | _ => panic!("not reached"), 184 | }; 185 | if group.is_none() { 186 | continue; 187 | } 188 | 189 | let group = group.unwrap(); 190 | 191 | if group.border.is_none() 192 | || group.background.is_none() 193 | || group.text.is_none() 194 | { 195 | continue; 196 | } 197 | 198 | writer.write(b" ").unwrap(); 199 | writer.write(group_name.as_bytes()).unwrap(); 200 | writer.write(b" ").unwrap(); 201 | writer 202 | .write(group.border.as_ref().unwrap().as_bytes()) 203 | .unwrap(); 204 | writer.write(b" ").unwrap(); 205 | writer 206 | .write(group.background.as_ref().unwrap().as_bytes()) 207 | .unwrap(); 208 | writer.write(b" ").unwrap(); 209 | writer 210 | .write(group.text.as_ref().unwrap().as_bytes()) 211 | .unwrap(); 212 | writer.write(b" ").unwrap(); 213 | 214 | match group.indicator { 215 | Some(ref color) => { 216 | writer.write(b" ").unwrap(); 217 | writer.write(color.as_bytes()).unwrap(); 218 | () 219 | } 220 | None => (), 221 | }; 222 | 223 | writer.write(b"\n").unwrap(); 224 | } 225 | writer.write(b" }\n").unwrap(); 226 | } 227 | 228 | colors_found = false; 229 | in_bar = false; 230 | writer.write(original_line.as_bytes()).unwrap(); 231 | continue; 232 | } 233 | 234 | if in_colors { 235 | if theme.bar_colors.is_none() { 236 | writer.write(original_line.as_bytes()).unwrap(); 237 | continue; 238 | } 239 | 240 | let bar_colors = &theme.bar_colors.as_ref().unwrap(); 241 | 242 | if vec!["separator", "background", "statusline"].contains(&vec[0]) { 243 | found_bar_colors.insert(vec[0].to_string()); 244 | writer.write(leading.as_bytes()).unwrap(); 245 | writer.write(vec[0].as_bytes()).unwrap(); 246 | writer.write(b" ").unwrap(); 247 | 248 | writer 249 | .write(match vec[0] { 250 | "separator" => match bar_colors.separator { 251 | Some(ref color) => color.as_bytes(), 252 | None => vec[1].as_bytes(), 253 | }, 254 | "background" => match bar_colors.background { 255 | Some(ref color) => color.as_bytes(), 256 | None => vec[1].as_bytes(), 257 | }, 258 | "statusline" => match bar_colors.statusline { 259 | Some(ref color) => color.as_bytes(), 260 | None => vec[1].as_bytes(), 261 | }, 262 | _ => vec[1].as_bytes(), 263 | }) 264 | .unwrap(); 265 | writer.write(b"\n").unwrap(); 266 | continue; 267 | } else if vec![ 268 | "focused_workspace", 269 | "active_workspace", 270 | "inactive_workspace", 271 | "urgent_workspace", 272 | ] 273 | .contains(&vec[0]) 274 | { 275 | found_bar_colors.insert(vec[0].to_string()); 276 | let group = match vec[0] { 277 | "focused_workspace" => bar_colors.focused_workspace.as_ref(), 278 | "active_workspace" => bar_colors.active_workspace.as_ref(), 279 | "inactive_workspace" => bar_colors.inactive_workspace.as_ref(), 280 | "urgent_workspace" => bar_colors.urgent_workspace.as_ref(), 281 | _ => panic!("not reached"), 282 | }; 283 | 284 | if group.is_none() { 285 | writer.write(original_line.as_bytes()).unwrap(); 286 | continue; 287 | } 288 | 289 | let group = group.unwrap(); 290 | 291 | writer.write(leading.as_bytes()).unwrap(); 292 | writer.write(vec[0].as_bytes()).unwrap(); 293 | writer.write(b" ").unwrap(); 294 | 295 | writer 296 | .write(match group.border.as_ref() { 297 | Some(color) => color.as_bytes(), 298 | None => vec[1].as_bytes(), 299 | }) 300 | .unwrap(); 301 | writer.write(b" ").unwrap(); 302 | 303 | writer 304 | .write(match group.background.as_ref() { 305 | Some(color) => color.as_bytes(), 306 | None => vec[2].as_bytes(), 307 | }) 308 | .unwrap(); 309 | writer.write(b" ").unwrap(); 310 | 311 | writer 312 | .write(match group.text.as_ref() { 313 | Some(color) => color.as_bytes(), 314 | None => vec[3].as_bytes(), 315 | }) 316 | .unwrap(); 317 | 318 | if vec.get(3).is_some() || group.indicator.is_some() { 319 | writer.write(b" ").unwrap(); 320 | writer 321 | .write(match group.indicator.as_ref() { 322 | Some(color) => color.as_bytes(), 323 | None => vec[3].as_bytes(), 324 | }) 325 | .unwrap(); 326 | } 327 | writer.write(b"\n").unwrap(); 328 | 329 | continue; 330 | } 331 | continue; 332 | } 333 | 334 | if vec[0] == "bar" { 335 | in_bar = true; 336 | writer.write(original_line.as_bytes()).unwrap(); 337 | continue; 338 | } 339 | if in_bar && vec[0] == "colors" { 340 | in_colors = true; 341 | colors_found = true; 342 | writer.write(original_line.as_bytes()).unwrap(); 343 | continue; 344 | } 345 | 346 | if vec![ 347 | "client.focused", 348 | "client.unfocused", 349 | "client.focused_inactive", 350 | "client.urgent", 351 | ] 352 | .contains(&vec[0]) 353 | { 354 | found_window_colors.insert(vec[0].to_string()); 355 | if theme.window_colors.is_none() { 356 | writer.write(original_line.as_bytes()).unwrap(); 357 | continue; 358 | } 359 | 360 | let window_colors = &theme.window_colors.as_ref().unwrap(); 361 | 362 | let group = match vec[0] { 363 | "client.focused" => window_colors.focused.as_ref(), 364 | "client.unfocused" => window_colors.unfocused.as_ref(), 365 | "client.focused_inactive" => window_colors.focused_inactive.as_ref(), 366 | "client.urgent" => window_colors.urgent.as_ref(), 367 | _ => panic!("not reached"), 368 | }; 369 | 370 | if group.is_none() { 371 | writer.write(original_line.as_bytes()).unwrap(); 372 | continue; 373 | } 374 | 375 | let group = group.unwrap(); 376 | 377 | writer.write(leading.as_bytes()).unwrap(); 378 | writer.write(vec[0].as_bytes()).unwrap(); 379 | writer.write(b" ").unwrap(); 380 | 381 | writer 382 | .write(match group.border.as_ref() { 383 | Some(color) => color.as_bytes(), 384 | None => vec[1].as_bytes(), 385 | }) 386 | .unwrap(); 387 | writer.write(b" ").unwrap(); 388 | 389 | writer 390 | .write(match group.background.as_ref() { 391 | Some(color) => color.as_bytes(), 392 | None => vec[2].as_bytes(), 393 | }) 394 | .unwrap(); 395 | writer.write(b" ").unwrap(); 396 | 397 | if vec.get(3).is_some() || group.text.is_some() { 398 | writer 399 | .write(match group.text.as_ref() { 400 | Some(color) => color.as_bytes(), 401 | None => vec[3].as_bytes(), 402 | }) 403 | .unwrap(); 404 | writer.write(b" ").unwrap(); 405 | 406 | // cant write the indicator in the text field 407 | if vec.get(4).is_some() || group.indicator.is_some() { 408 | writer 409 | .write(match group.indicator.as_ref() { 410 | Some(color) => color.as_bytes(), 411 | None => vec[4].as_bytes(), 412 | }) 413 | .unwrap(); 414 | } 415 | } 416 | 417 | writer.write(b"\n").unwrap(); 418 | continue; 419 | } 420 | } 421 | 422 | writer.write(original_line.as_bytes()).unwrap(); 423 | } 424 | 425 | let window_color_names = vec![ 426 | "client.focused", 427 | "client.focused_inactive", 428 | "client.unfocused", 429 | "client.urgent", 430 | ]; 431 | for window_color_name in &window_color_names { 432 | if found_window_colors.contains(&window_color_name.to_string()) { 433 | continue; 434 | } 435 | let window_colors = &theme.window_colors.as_ref().unwrap(); 436 | 437 | let group = match window_color_name.as_ref() { 438 | "client.focused" => window_colors.focused.as_ref(), 439 | "client.unfocused" => window_colors.unfocused.as_ref(), 440 | "client.focused_inactive" => window_colors.focused_inactive.as_ref(), 441 | "client.urgent" => window_colors.urgent.as_ref(), 442 | _ => panic!("not reached"), 443 | }; 444 | 445 | if group.is_none() { 446 | continue; 447 | } 448 | 449 | let group = group.unwrap(); 450 | 451 | writer.write(window_color_name.as_bytes()).unwrap(); 452 | writer.write(b" ").unwrap(); 453 | writer 454 | .write(match group.border.as_ref() { 455 | Some(color) => color.as_bytes(), 456 | None => b"#000000", 457 | }) 458 | .unwrap(); 459 | writer.write(b" ").unwrap(); 460 | 461 | writer 462 | .write(match group.background.as_ref() { 463 | Some(color) => color.as_bytes(), 464 | None => b"#000000", 465 | }) 466 | .unwrap(); 467 | writer.write(b" ").unwrap(); 468 | 469 | writer 470 | .write(match group.text.as_ref() { 471 | Some(color) => color.as_bytes(), 472 | None => b"#000000", 473 | }) 474 | .unwrap(); 475 | 476 | group.indicator.as_ref().map(|color| { 477 | writer.write(b" ").unwrap(); 478 | writer.write(color.as_bytes()).unwrap(); 479 | }); 480 | 481 | writer.write(b"\n").unwrap(); 482 | } 483 | } 484 | 485 | #[cfg(test)] 486 | mod tests { 487 | use super::*; 488 | use theme::from_yaml; 489 | 490 | extern crate tempfile; 491 | extern crate yaml_rust; 492 | 493 | use self::tempfile::tempdir; 494 | use std::path::PathBuf; 495 | use yaml_rust::YamlLoader; 496 | 497 | fn get_file_contents(path: &String) -> String { 498 | let mut file = File::open(path).expect("could not open file"); 499 | let mut contents = String::new(); 500 | file.read_to_string(&mut contents).unwrap(); 501 | contents 502 | } 503 | 504 | fn get_resource_contents(path: &str) -> String { 505 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 506 | d.push("test-resources"); 507 | d.push(path); 508 | get_file_contents(&d.to_str().unwrap().to_string()) 509 | } 510 | 511 | #[test] 512 | fn test_minimal_config_template() { 513 | let contents = get_resource_contents("test-theme.yaml"); 514 | 515 | let docs = 516 | YamlLoader::load_from_str(contents.as_str()).expect("Could not parse yaml for theme"); 517 | let doc = &docs[0]; 518 | 519 | let theme = from_yaml(&doc); 520 | 521 | let dir = tempdir().unwrap(); 522 | let output_path = dir 523 | .path() 524 | .join("writer-test-output") 525 | .to_str() 526 | .unwrap() 527 | .to_string(); 528 | 529 | let configs = vec![ 530 | vec!["test-resources/minimal-config", "minimal-config-expected"], 531 | vec!["test-resources/missing-config", "missing-config-expected"], 532 | ]; 533 | 534 | for config in &configs { 535 | let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 536 | d.push(&config[0]); 537 | let input_path = d.to_str().unwrap().to_string(); 538 | 539 | write_config(&input_path, Some(&output_path), &theme); 540 | 541 | let contents = get_file_contents(&output_path); 542 | let expected_contents = get_resource_contents(&config[1]); 543 | 544 | println!("'{}'", contents); 545 | println!("'{}'", expected_contents); 546 | assert_eq!(contents, expected_contents); 547 | } 548 | } 549 | } 550 | -------------------------------------------------------------------------------- /test-resources/default-config: -------------------------------------------------------------------------------- 1 | # i3 config file (v4) 2 | # 3 | # Please see http://i3wm.org/docs/userguide.html for a complete reference! 4 | # 5 | # This config file uses keycodes (bindsym) and was written for the QWERTY 6 | # layout. 7 | # 8 | # To get a config file with the same key positions, but for your current 9 | # layout, use the i3-config-wizard 10 | # 11 | 12 | # Font for window titles. Will also be used by the bar unless a different font 13 | # is used in the bar {} block below. ISO 10646 = Unicode 14 | font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 15 | # The font above is very space-efficient, that is, it looks good, sharp and 16 | # clear in small sizes. However, if you need a lot of unicode glyphs or 17 | # right-to-left text rendering, you should instead use pango for rendering and 18 | # chose a FreeType font, such as: 19 | # font pango:DejaVu Sans Mono 10 20 | 21 | # use Mouse+Mod1 to drag floating windows to their wanted position 22 | floating_modifier Mod1 23 | 24 | # start a terminal 25 | bindsym Mod1+Return exec i3-sensible-terminal 26 | 27 | # kill focused window 28 | bindsym Mod1+Shift+q kill 29 | 30 | # start dmenu (a program launcher) 31 | bindsym Mod1+d exec dmenu_run 32 | # There also is the (new) i3-dmenu-desktop which only displays applications 33 | # shipping a .desktop file. It is a wrapper around dmenu, so you need that 34 | # installed. 35 | # bindsym Mod1+d exec --no-startup-id i3-dmenu-desktop 36 | 37 | # change focus 38 | bindsym Mod1+j focus left 39 | bindsym Mod1+k focus down 40 | bindsym Mod1+l focus up 41 | bindsym Mod1+semicolon focus right 42 | 43 | # alternatively, you can use the cursor keys: 44 | bindsym Mod1+Left focus left 45 | bindsym Mod1+Down focus down 46 | bindsym Mod1+Up focus up 47 | bindsym Mod1+Right focus right 48 | 49 | # move focused window 50 | bindsym Mod1+Shift+j move left 51 | bindsym Mod1+Shift+k move down 52 | bindsym Mod1+Shift+l move up 53 | bindsym Mod1+Shift+semicolon move right 54 | 55 | # alternatively, you can use the cursor keys: 56 | bindsym Mod1+Shift+Left move left 57 | bindsym Mod1+Shift+Down move down 58 | bindsym Mod1+Shift+Up move up 59 | bindsym Mod1+Shift+Right move right 60 | 61 | # split in horizontal orientation 62 | bindsym Mod1+h split h 63 | 64 | # split in vertical orientation 65 | bindsym Mod1+v split v 66 | 67 | # enter fullscreen mode for the focused container 68 | bindsym Mod1+f fullscreen 69 | 70 | # change container layout (stacked, tabbed, toggle split) 71 | bindsym Mod1+s layout stacking 72 | bindsym Mod1+w layout tabbed 73 | bindsym Mod1+e layout toggle split 74 | 75 | # toggle tiling / floating 76 | bindsym Mod1+Shift+space floating toggle 77 | 78 | # change focus between tiling / floating windows 79 | bindsym Mod1+space focus mode_toggle 80 | 81 | # focus the parent container 82 | bindsym Mod1+a focus parent 83 | 84 | # focus the child container 85 | #bindsym Mod1+d focus child 86 | 87 | # move the currently focused window to the scratchpad 88 | bindsym Mod1+Shift+minus move scratchpad 89 | 90 | # Show the next scratchpad window or hide the focused scratchpad window. 91 | # If there are multiple scratchpad windows, this command cycles through them. 92 | bindsym Mod1+minus scratchpad show 93 | 94 | # switch to workspace 95 | bindsym Mod1+1 workspace 1 96 | bindsym Mod1+2 workspace 2 97 | bindsym Mod1+3 workspace 3 98 | bindsym Mod1+4 workspace 4 99 | bindsym Mod1+5 workspace 5 100 | bindsym Mod1+6 workspace 6 101 | bindsym Mod1+7 workspace 7 102 | bindsym Mod1+8 workspace 8 103 | bindsym Mod1+9 workspace 9 104 | bindsym Mod1+0 workspace 10 105 | 106 | # move focused container to workspace 107 | bindsym Mod1+Shift+1 move container to workspace 1 108 | bindsym Mod1+Shift+2 move container to workspace 2 109 | bindsym Mod1+Shift+3 move container to workspace 3 110 | bindsym Mod1+Shift+4 move container to workspace 4 111 | bindsym Mod1+Shift+5 move container to workspace 5 112 | bindsym Mod1+Shift+6 move container to workspace 6 113 | bindsym Mod1+Shift+7 move container to workspace 7 114 | bindsym Mod1+Shift+8 move container to workspace 8 115 | bindsym Mod1+Shift+9 move container to workspace 9 116 | bindsym Mod1+Shift+0 move container to workspace 10 117 | 118 | # reload the configuration file 119 | bindsym Mod1+Shift+c reload 120 | # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 121 | bindsym Mod1+Shift+r restart 122 | # exit i3 (logs you out of your X session) 123 | bindsym Mod1+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" 124 | 125 | # resize window (you can also use the mouse for that) 126 | mode "resize" { 127 | # These bindings trigger as soon as you enter the resize mode 128 | 129 | # Pressing left will shrink the window’s width. 130 | # Pressing right will grow the window’s width. 131 | # Pressing up will shrink the window’s height. 132 | # Pressing down will grow the window’s height. 133 | bindsym j resize shrink width 10 px or 10 ppt 134 | bindsym k resize grow height 10 px or 10 ppt 135 | bindsym l resize shrink height 10 px or 10 ppt 136 | bindsym semicolon resize grow width 10 px or 10 ppt 137 | 138 | # same bindings, but for the arrow keys 139 | bindsym Left resize shrink width 10 px or 10 ppt 140 | bindsym Down resize grow height 10 px or 10 ppt 141 | bindsym Up resize shrink height 10 px or 10 ppt 142 | bindsym Right resize grow width 10 px or 10 ppt 143 | 144 | # back to normal: Enter or Escape 145 | bindsym Return mode "default" 146 | bindsym Escape mode "default" 147 | } 148 | 149 | bindsym Mod1+r mode "resize" 150 | 151 | # Start i3bar to display a workspace bar (plus the system information i3status 152 | # finds out, if available) 153 | bar { 154 | status_command i3status 155 | } 156 | 157 | ####################################################################### 158 | # automatically start i3-config-wizard to offer the user to create a 159 | # keysym-based config which used his favorite modifier (alt or windows) 160 | # 161 | # i3-config-wizard will not launch if there already is a config file 162 | # in ~/.i3/config. 163 | # 164 | # Please remove the following exec line: 165 | ####################################################################### 166 | exec i3-config-wizard 167 | -------------------------------------------------------------------------------- /test-resources/minimal-config: -------------------------------------------------------------------------------- 1 | # test templating with a minimal config 2 | font pango:Fira Mono 8 3 | 4 | bindsym Right focus right 5 | 6 | bar { 7 | colors { 8 | separator #dc322f 9 | background #002b36 10 | statusline #268bd2 11 | focused_workspace #fdf6e3 #859900 12 | active_workspace #fdf6e3 #6c71c4 13 | inactive_workspace #586e75 #93a1a1 14 | urgent_workspace #d33682 #d33682 15 | } 16 | } 17 | client.focused #859900 #859900 #fdf6e3 18 | client.focused_inactive #073642 #073642 #eee8d5 19 | client.unfocused #073642 #073642 #93a1a1 20 | client.urgent #d33682 #d33682 #fdf6e3 21 | -------------------------------------------------------------------------------- /test-resources/minimal-config-expected: -------------------------------------------------------------------------------- 1 | # test templating with a minimal config 2 | font pango:Fira Mono 8 3 | 4 | bindsym Right focus right 5 | 6 | bar { 7 | colors { 8 | separator #000000 9 | background #FDF6E3 10 | statusline #002B36 11 | focused_workspace #000000 #268BD2 #FFFFFF 12 | active_workspace #333333 #222222 #FFFFFF 13 | inactive_workspace #333333 #222222 #888888 14 | urgent_workspace #2F343A #900000 #FFFFFF 15 | } 16 | } 17 | client.focused #000000 #FDF6E3 #002B36 #000000 18 | client.focused_inactive #000000 #5F676A #FDF6E3 #484E50 19 | client.unfocused #000000 #000000 #FDF6E3 #000000 20 | client.urgent #000000 #DC322F #FDF6E3 #DC322F 21 | -------------------------------------------------------------------------------- /test-resources/missing-config: -------------------------------------------------------------------------------- 1 | # test config templating when things are missing 2 | font pango:Fira Mono 8 3 | 4 | bindsym Right focus right 5 | 6 | bar { 7 | } 8 | 9 | bar { 10 | colors { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test-resources/missing-config-expected: -------------------------------------------------------------------------------- 1 | # test config templating when things are missing 2 | font pango:Fira Mono 8 3 | 4 | bindsym Right focus right 5 | 6 | bar { 7 | colors { 8 | separator #000000 9 | background #FDF6E3 10 | statusline #002B36 11 | focused_workspace #000000 #268BD2 #FFFFFF 12 | active_workspace #333333 #222222 #FFFFFF 13 | inactive_workspace #333333 #222222 #888888 14 | urgent_workspace #2F343A #900000 #FFFFFF 15 | } 16 | } 17 | 18 | bar { 19 | colors { 20 | separator #000000 21 | background #FDF6E3 22 | statusline #002B36 23 | focused_workspace #000000 #268BD2 #FFFFFF 24 | active_workspace #333333 #222222 #FFFFFF 25 | inactive_workspace #333333 #222222 #888888 26 | urgent_workspace #2F343A #900000 #FFFFFF 27 | } 28 | } 29 | client.focused #000000 #FDF6E3 #002B36 #000000 30 | client.focused_inactive #000000 #5F676A #FDF6E3 #484E50 31 | client.unfocused #000000 #000000 #FDF6E3 #000000 32 | client.urgent #000000 #DC322F #FDF6E3 #DC322F 33 | -------------------------------------------------------------------------------- /test-resources/test-theme.yaml: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: A beige theme by Alphare 5 | colors: 6 | black: '#000000' 7 | oldlace: '#FDF6E3' 8 | darkslategray: '#002B36' 9 | steelblue: '#268BD2' 10 | dimgray: '#5F676A' 11 | darkslategrey: '#484E50' 12 | crimson: '#DC322F' 13 | steelblue1: '#4C7899' 14 | steelblue2: '#285577' 15 | white: '#FFFFFF' 16 | darkslategrey1: '#333333' 17 | black1: '#222222' 18 | gray: '#888888' 19 | darkslategray1: '#2F343A' 20 | darkred: '#900000' 21 | window_colors: 22 | focused: 23 | border: black 24 | background: oldlace 25 | text: darkslategray 26 | indicator: black 27 | focused_inactive: 28 | border: black 29 | background: dimgray 30 | text: oldlace 31 | indicator: darkslategrey 32 | unfocused: 33 | border: black 34 | background: black 35 | text: oldlace 36 | indicator: black 37 | urgent: 38 | border: black 39 | background: crimson 40 | text: oldlace 41 | indicator: crimson 42 | bar_colors: 43 | background: oldlace 44 | statusline: darkslategray 45 | separator: black 46 | focused_workspace: 47 | border: black 48 | background: steelblue 49 | text: white 50 | active_workspace: 51 | border: darkslategrey1 52 | background: black1 53 | text: white 54 | inactive_workspace: 55 | border: darkslategrey1 56 | background: black1 57 | text: gray 58 | urgent_workspace: 59 | border: darkslategray1 60 | background: darkred 61 | text: white 62 | -------------------------------------------------------------------------------- /themes/alphare: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: A beige theme by Alphare 5 | colors: 6 | black: '#000000' 7 | oldlace: '#FDF6E3' 8 | darkslategray: '#002B36' 9 | steelblue: '#268BD2' 10 | dimgray: '#5F676A' 11 | darkslategrey: '#484E50' 12 | crimson: '#DC322F' 13 | steelblue1: '#4C7899' 14 | steelblue2: '#285577' 15 | white: '#FFFFFF' 16 | darkslategrey1: '#333333' 17 | black1: '#222222' 18 | gray: '#888888' 19 | darkslategray1: '#2F343A' 20 | darkred: '#900000' 21 | window_colors: 22 | focused: 23 | border: black 24 | background: oldlace 25 | text: darkslategray 26 | indicator: black 27 | focused_inactive: 28 | border: black 29 | background: dimgray 30 | text: oldlace 31 | indicator: darkslategrey 32 | unfocused: 33 | border: black 34 | background: black 35 | text: oldlace 36 | indicator: black 37 | urgent: 38 | border: black 39 | background: crimson 40 | text: oldlace 41 | indicator: crimson 42 | bar_colors: 43 | background: oldlace 44 | statusline: darkslategray 45 | separator: black 46 | focused_workspace: 47 | border: black 48 | background: steelblue 49 | text: white 50 | active_workspace: 51 | border: darkslategrey1 52 | background: black1 53 | text: white 54 | inactive_workspace: 55 | border: darkslategrey1 56 | background: black1 57 | text: gray 58 | urgent_workspace: 59 | border: darkslategray1 60 | background: darkred 61 | text: white 62 | -------------------------------------------------------------------------------- /themes/archlinux: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Archlinux theme by okraits ' 6 | window_colors: 7 | focused: 8 | border: '#0088CC' 9 | background: '#0088CC' 10 | text: '#ffffff' 11 | indicator: '#dddddd' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#333333' 15 | text: '#888888' 16 | indicator: '#292d2e' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#222222' 30 | statusline: '#dddddd' 31 | focused_workspace: 32 | border: '#0088CC' 33 | background: '#0088CC' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#333333' 38 | text: '#ffffff' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#333333' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /themes/base16-tomorrow: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | colors: 4 | base00: '#1d1f21' 5 | base01: '#282a2e' 6 | base02: '#373b41' 7 | base03: '#969896' 8 | base04: '#b4b7b4' 9 | base05: '#c5c8c6' 10 | base06: '#e0e0e0' 11 | base07: '#ffffff' 12 | base08: '#cc6666' 13 | base09: '#de935f' 14 | base0A: '#f0c674' 15 | base0B: '#b5bd68' 16 | base0C: '#8abeb7' 17 | base0D: '#81a2be' 18 | base0E: '#b294bb' 19 | base0F: '#a3685a' 20 | 21 | meta: 22 | description: 'Base16 Tomorrow, by Chris Kempson (http://chriskempson.com)' 23 | window_colors: 24 | focused: 25 | border: 'base0D' 26 | background: 'base0D' 27 | text: 'base00' 28 | indicator: 'base01' 29 | focused_inactive: 30 | border: 'base02' 31 | background: 'base02' 32 | text: 'base03' 33 | indicator: 'base01' 34 | unfocused: 35 | border: 'base01' 36 | background: 'base01' 37 | text: 'base03' 38 | indicator: 'base01' 39 | urgent: 40 | border: 'base02' 41 | background: 'base08' 42 | text: 'base07' 43 | indicator: 'base08' 44 | bar_colors: 45 | separator: 'base03' 46 | background: 'base00' 47 | statusline: 'base05' 48 | focused_workspace: 49 | border: 'base0D' 50 | background: 'base0D' 51 | text: 'base00' 52 | active_workspace: 53 | border: 'base02' 54 | background: 'base02' 55 | text: 'base07' 56 | inactive_workspace: 57 | border: 'base01' 58 | background: 'base01' 59 | text: 'base03' 60 | urgent_workspace: 61 | border: 'base08' 62 | background: 'base08' 63 | text: 'base07' 64 | -------------------------------------------------------------------------------- /themes/debian: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Debian theme by lasers' 6 | window_colors: 7 | focused: 8 | border: '#d70a53' 9 | background: '#d70a53' 10 | text: '#ffffff' 11 | indicator: '#8c0333' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#333333' 15 | text: '#888888' 16 | indicator: '#333333' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#333333' 22 | urgent: 23 | border: '#eb709b' 24 | background: '#eb709b' 25 | text: '#ffffff' 26 | indicator: '#eb709b' 27 | bar_colors: 28 | separator: '#444444' 29 | background: '#222222' 30 | statusline: '#666666' 31 | focused_workspace: 32 | border: '#d70a53' 33 | background: '#d70a53' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#333333' 38 | text: '#888888' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#333333' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#eb709b' 45 | background: '#eb709b' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /themes/deep-purple: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Inspired by the Purple and Default themes. By jcpst ' 5 | bar_colors: 6 | separator: dimgrey 7 | background: black 8 | statusline: white 9 | focused_workspace: 10 | border: indigo 11 | background: indigo 12 | text: white 13 | active_workspace: 14 | border: darkslategrey 15 | background: dimgray 16 | text: white 17 | inactive_workspace: 18 | border: black 19 | background: black 20 | text: gray 21 | urgent_workspace: 22 | border: darkslategray 23 | background: darkred 24 | text: white 25 | colors: 26 | dimgrey: '#666666' 27 | black: '#000000' 28 | white: '#ffffff' 29 | indigo: '#551a8b' 30 | darkslategrey: '#333333' 31 | dimgray: '#5f676a' 32 | gray: '#888888' 33 | darkslategray: '#2f343a' 34 | darkred: '#900000' 35 | midnightblue: '#3b1261' 36 | indigo1: '#662b9c' 37 | darkslategrey1: '#484e50' 38 | black1: '#222222' 39 | darkslategray1: '#292d2e' 40 | window_colors: 41 | focused: 42 | border: midnightblue 43 | background: midnightblue 44 | text: white 45 | indicator: indigo1 46 | focused_inactive: 47 | border: darkslategrey 48 | background: dimgray 49 | text: white 50 | indicator: darkslategrey1 51 | unfocused: 52 | border: black1 53 | background: black1 54 | text: gray 55 | indicator: darkslategray1 56 | urgent: 57 | border: darkslategray 58 | background: darkred 59 | text: white 60 | indicator: darkred 61 | -------------------------------------------------------------------------------- /themes/default: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Default theme for i3wm ' 6 | window_colors: 7 | focused: 8 | border: '#4c7899' 9 | background: '#285577' 10 | text: '#ffffff' 11 | indicator: '#2e9ef4' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#5f676a' 15 | text: '#ffffff' 16 | indicator: '#484e50' 17 | unfocused: 18 | border: '#333333' 19 | background: '#222222' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#000000' 30 | statusline: '#ffffff' 31 | focused_workspace: 32 | border: '#4c7899' 33 | background: '#285577' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#5f676a' 38 | text: '#ffffff' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#222222' 42 | text: '#888888' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /themes/flat-gray: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: flat gray based theme 5 | colors: 6 | darkslategrey: '#333333' 7 | white: '#FFFFFF' 8 | black: '#000000' 9 | darkgray: '#AAAAAA' 10 | black1: '#282828' 11 | window_colors: 12 | unfocused: 13 | border: darkslategrey 14 | background: darkslategrey 15 | text: white 16 | indicator: darkslategrey 17 | focused_inactive: 18 | border: darkslategrey 19 | background: darkslategrey 20 | text: white 21 | indicator: black 22 | focused: 23 | border: black 24 | background: black 25 | text: white 26 | indicator: black 27 | bar_colors: 28 | statusline: darkgray 29 | background: darkslategrey 30 | focused_workspace: 31 | border: black1 32 | background: black1 33 | text: white 34 | inactive_workspace: 35 | border: darkslategrey 36 | background: darkslategrey 37 | text: darkgray 38 | -------------------------------------------------------------------------------- /themes/gruvbox: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: Made by freeware-preacher to match gruvbox by morhetz 5 | bar_colors: 6 | separator: grey 7 | background: black 8 | statusline: wheat 9 | focused_workspace: 10 | border: darkseagreen 11 | background: darkseagreen 12 | text: black 13 | active_workspace: 14 | border: black1 15 | background: black1 16 | text: grey 17 | inactive_workspace: 18 | border: darkslategray 19 | background: darkslategray 20 | text: grey 21 | urgent_workspace: 22 | border: firebrick 23 | background: firebrick 24 | text: wheat 25 | colors: 26 | grey: '#928374' 27 | black: '#282828' 28 | wheat: '#ebdbb2' 29 | darkseagreen: '#689d6a' 30 | black1: '#1d2021' 31 | darkslategray: '#32302f' 32 | firebrick: '#cc241d' 33 | window_colors: 34 | focused: 35 | border: darkseagreen 36 | background: darkseagreen 37 | text: black 38 | indicator: black 39 | focused_inactive: 40 | border: black1 41 | background: black1 42 | text: grey 43 | indicator: black 44 | unfocused: 45 | border: darkslategray 46 | background: darkslategray 47 | text: grey 48 | indicator: black 49 | urgent: 50 | border: firebrick 51 | background: firebrick 52 | text: wheat 53 | indicator: black 54 | 55 | -------------------------------------------------------------------------------- /themes/icelines: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # Theme meant to be simple but visually efficient 3 | --- 4 | meta: 5 | description: 'icelines theme by mbfraga' 6 | colors: 7 | darkgray: '#141414' 8 | ice: '#00b0ef' 9 | gray: '#7d7d7d' 10 | darkred: '#472b2a' 11 | urgent: '#ff7066' 12 | window_colors: 13 | focused: 14 | border: 'ice' 15 | background: 'ice' 16 | text: 'darkgray' 17 | indicator: 'urgent' 18 | focused_inactive: 19 | border: 'darkgray' 20 | background: 'darkgray' 21 | text: 'ice' 22 | indicator: 'darkred' 23 | unfocused: 24 | border: 'darkgray' 25 | background: 'darkgray' 26 | text: 'gray' 27 | indicator: 'darkgray' 28 | urgent: 29 | border: 'urgent' 30 | background: 'urgent' 31 | text: 'darkgray' 32 | indicator: 'urgent' 33 | bar_colors: 34 | separator: 'gray' 35 | background: 'darkgray' 36 | statusline: 'ice' 37 | focused_workspace: 38 | border: 'ice' 39 | background: 'darkgray' 40 | text: 'ice' 41 | active_workspace: 42 | border: 'darkgray' 43 | background: 'darkgray' 44 | text: 'ice' 45 | inactive_workspace: 46 | border: 'darkgray' 47 | background: 'darkgray' 48 | text: 'gray' 49 | urgent_workspace: 50 | border: 'urgent' 51 | background: 'darkgray' 52 | text: 'urgent' 53 | -------------------------------------------------------------------------------- /themes/lime: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Lime theme by wei2912 , based on Archlinux theme by okraits ' 5 | colors: 6 | lime: '#4E9C00' # main colour 7 | lime_inactive: '#1B3600' 8 | 9 | red: '#C20000' # urgent colour 10 | black: '#333333' # background 11 | 12 | txt_active: '#FFFFFF' # white 13 | txt_inactive: '#888888' # grey 14 | 15 | indicator: '#FFFFFF' # white 16 | 17 | window_colors: 18 | focused: 19 | border: 'lime' 20 | background: 'lime' 21 | text: 'txt_active' 22 | indicator: 'indicator' 23 | focused_inactive: 24 | border: 'lime_inactive' 25 | background: 'lime_inactive' 26 | text: 'txt_inactive' 27 | indicator: 'indicator' 28 | unfocused: 29 | border: 'black' 30 | background: 'black' 31 | text: 'txt_inactive' 32 | indicator: 'indicator' 33 | urgent: 34 | border: 'red' 35 | background: 'red' 36 | text: 'txt_active' 37 | indicator: 'indicator' 38 | bar_colors: 39 | separator: 'txt_inactive' 40 | background: 'black' 41 | statusline: 'txt_active' 42 | focused_workspace: 43 | border: 'lime' 44 | background: 'lime' 45 | text: 'txt_active' 46 | active_workspace: 47 | border: 'black' 48 | background: 'black' 49 | text: 'txt_active' 50 | inactive_workspace: 51 | border: 'black' 52 | background: 'black' 53 | text: 'txt_inactive' 54 | urgent_workspace: 55 | border: 'red' 56 | background: 'red' 57 | text: 'txt_active' 58 | -------------------------------------------------------------------------------- /themes/mate: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Theme for blending i3 into MATE' 5 | colors: 6 | green: '#526532' 7 | lightgreen: '#a4cb64' 8 | darkgrey: '#3c3b37' 9 | grey: '#4c4c4c' 10 | lightgrey: '#aea79f' 11 | black: '#000000' 12 | white: '#ffffff' 13 | red: '#FF0000' 14 | window_colors: 15 | focused: 16 | border: green 17 | background: green 18 | text: white 19 | indicator: lightgreen 20 | focused_inactive: 21 | border: lightgrey 22 | background: lightgrey 23 | text: darkgrey 24 | indicator: lightgrey 25 | unfocused: 26 | border: darkgrey 27 | background: darkgrey 28 | text: lightgrey 29 | indicator: darkgrey 30 | urgent: 31 | border: red 32 | background: red 33 | text: white 34 | indicator: red 35 | bar_colors: 36 | separator: white 37 | background: darkgrey 38 | statusline: white 39 | focused_workspace: 40 | border: green 41 | background: green 42 | text: white 43 | active_workspace: 44 | border: lightgrey 45 | background: lightgrey 46 | text: darkgrey 47 | inactive_workspace: 48 | border: darkgrey 49 | background: darkgrey 50 | text: lightgrey 51 | urgent_workspace: 52 | border: red 53 | background: red 54 | text: white 55 | -------------------------------------------------------------------------------- /themes/oceanic-next: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: Theme by Valentin Weber inspired by voronianski (https://github.com/voronianski/oceanic-next-color-scheme) 5 | bar_colors: 6 | separator: base03 7 | background: base00 8 | statusline: base07 9 | focused_workspace: 10 | border: base0D 11 | background: base0D 12 | text: base00 13 | active_workspace: 14 | border: base0C 15 | background: base0C 16 | text: base00 17 | inactive_workspace: 18 | border: base01 19 | background: base01 20 | text: base07 21 | urgent_workspace: 22 | border: base08 23 | background: base08 24 | text: base00 25 | colors: 26 | base00: '#1B2B34' 27 | base01: '#343D46' 28 | base02: '#4F5B66' 29 | base03: '#65737E' 30 | base04: '#A7ADBA' 31 | base05: '#C0C5CE' 32 | base06: '#CDD3DE' 33 | base07: '#D8DEE9' 34 | base08: '#EC5f67' 35 | base09: '#F99157' 36 | base0A: '#FAC863' 37 | base0B: '#99C794' 38 | base0C: '#5FB3B3' 39 | base0D: '#6699CC' 40 | base0E: '#C594C5' 41 | base0F: '#AB7967' 42 | window_colors: 43 | focused: 44 | border: base0D 45 | background: base0D 46 | text: base00 47 | indicator: base0D 48 | focused_inactive: 49 | border: base0C 50 | background: base0C 51 | text: base07 52 | indicator: base04 53 | unfocused: 54 | border: base01 55 | background: base01 56 | text: base07 57 | indicator: base01 58 | urgent: 59 | border: base08 60 | background: base08 61 | text: base00 62 | indicator: base08 63 | -------------------------------------------------------------------------------- /themes/okraits: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'A simple theme by okraits ' 6 | window_colors: 7 | focused: 8 | border: '#888888' 9 | background: '#dddddd' 10 | text: '#222222' 11 | indicator: '#2e9ef4' 12 | focused_inactive: 13 | border: '#333333' 14 | background: '#555555' 15 | text: '#bbbbbb' 16 | indicator: '#484e50' 17 | unfocused: 18 | border: '#333333' 19 | background: '#333333' 20 | text: '#888888' 21 | indicator: '#292d2e' 22 | urgent: 23 | border: '#2f343a' 24 | background: '#900000' 25 | text: '#ffffff' 26 | indicator: '#900000' 27 | bar_colors: 28 | separator: '#666666' 29 | background: '#333333' 30 | statusline: '#bbbbbb' 31 | focused_workspace: 32 | border: '#888888' 33 | background: '#dddddd' 34 | text: '#222222' 35 | active_workspace: 36 | border: '#333333' 37 | background: '#555555' 38 | text: '#bbbbbb' 39 | inactive_workspace: 40 | border: '#333333' 41 | background: '#555555' 42 | text: '#bbbbbb' 43 | urgent_workspace: 44 | border: '#2f343a' 45 | background: '#900000' 46 | text: '#ffffff' 47 | -------------------------------------------------------------------------------- /themes/purple: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Purple theme by AAlakkad ' 5 | bar_colors: 6 | separator: darkgray 7 | background: black 8 | statusline: white 9 | focused_workspace: 10 | border: darkslateblue 11 | background: darkslateblue 12 | text: lightgray 13 | active_workspace: 14 | border: khaki 15 | background: khaki 16 | text: black1 17 | inactive_workspace: 18 | border: black 19 | background: black 20 | text: darkgray 21 | urgent_workspace: 22 | border: firebrick 23 | background: firebrick 24 | text: white 25 | colors: 26 | darkgray: '#AAAAAA' 27 | black: '#222133' 28 | white: '#FFFFFF' 29 | wheat: '#e7d8b1' 30 | black1: '#181715' 31 | khaki: '#DCCD69' 32 | firebrick: '#CE4045' 33 | darkslateblue: '#664477' 34 | lightgray: '#cccccc' 35 | mediumpurple: '#A074C4' 36 | window_colors: 37 | focused: 38 | border: darkslateblue 39 | background: darkslateblue 40 | text: lightgray 41 | indicator: wheat 42 | focused_inactive: 43 | border: wheat 44 | background: wheat 45 | text: black1 46 | indicator: mediumpurple 47 | unfocused: 48 | border: black 49 | background: black 50 | text: darkgray 51 | indicator: mediumpurple 52 | urgent: 53 | border: firebrick 54 | background: firebrick 55 | text: wheat 56 | indicator: khaki 57 | -------------------------------------------------------------------------------- /themes/seti: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'seti theme by Jody Ribton - based on the seti Atom theme at https://atom.io/themes/seti-ui' 5 | colors: 6 | blue: '#4F99D3' 7 | green: '#9FCA56' 8 | yellow: '#DCCD69' 9 | red: '#CE4045' 10 | orange: '#FF8315' 11 | purple: '#A074C4' 12 | grey: '#1f2326' 13 | white: '#FFFFFF' 14 | dull_white: '#AAAAAA' 15 | base: '#151718' 16 | window_colors: 17 | focused: 18 | border: 'blue' 19 | background: 'blue' 20 | text: 'base' 21 | indicator: 'green' 22 | focused_inactive: 23 | border: 'green' 24 | background: 'green' 25 | text: 'base' 26 | indicator: 'purple' 27 | unfocused: 28 | border: 'grey' 29 | background: 'grey' 30 | text: 'dull_white' 31 | indicator: 'purple' 32 | urgent: 33 | border: 'red' 34 | background: 'red' 35 | text: 'white' 36 | indicator: 'yellow' 37 | bar_colors: 38 | separator: 'dull_white' 39 | background: 'grey' 40 | statusline: 'white' 41 | focused_workspace: 42 | border: 'green' 43 | background: 'green' 44 | text: 'base' 45 | active_workspace: 46 | border: 'yellow' 47 | background: 'yellow' 48 | text: 'base' 49 | inactive_workspace: 50 | border: 'grey' 51 | background: 'grey' 52 | text: 'dull_white' 53 | urgent_workspace: 54 | border: 'red' 55 | background: 'red' 56 | text: 'white' 57 | 58 | 59 | -------------------------------------------------------------------------------- /themes/slate: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Slate theme by Jody Ribton ' 5 | colors: 6 | # focused 7 | slate: '#586e75' # main color 8 | cream: '#fdf6e3' # focused text color 9 | sky_blue: '#268bd2' # focused indicator color 10 | 11 | # inactive and unfocused 12 | dark_teal: '#073642' # inactive windoww border 13 | darker_teal: '#002b36' # unfocused window border 14 | white_teal: '#93a1a1' # inactive text 15 | grey: '#aea79f' # statusline 16 | 17 | # urgent 18 | red: '#dc322f' # urgent window border 19 | white: '#ffffff' # workspace text 20 | purple: '#77216f' # urgent workspace color 21 | 22 | window_colors: 23 | focused: 24 | border: 'slate' 25 | background: 'slate' 26 | text: 'cream' 27 | indicator: 'sky_blue' 28 | focused_inactive: 29 | border: 'dark_teal' 30 | background: 'dark_teal' 31 | text: 'white_teal' 32 | indicator: 'darker_teal' 33 | unfocused: 34 | border: 'darker_teal' 35 | background: 'darker_teal' 36 | text: 'slate' 37 | indicator: 'darker_teal' 38 | urgent: 39 | border: 'red' 40 | background: 'red' 41 | text: 'cream' 42 | indicator: 'red' 43 | bar_colors: 44 | separator: 'slate' 45 | background: 'darker_teal' 46 | statusline: 'grey' 47 | focused_workspace: 48 | border: 'slate' 49 | background: 'slate' 50 | text: 'white' 51 | active_workspace: 52 | border: 'dark_teal' 53 | background: 'dark_teal' 54 | text: 'white' 55 | inactive_workspace: 56 | border: 'darker_teal' 57 | background: 'darker_teal' 58 | text: 'grey' 59 | urgent_workspace: 60 | border: 'purple' 61 | background: 'purple' 62 | text: 'white' 63 | -------------------------------------------------------------------------------- /themes/solarized: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | --- 3 | meta: 4 | description: 'Solarized theme by lasers' 5 | colors: 6 | base03: '#002b36' 7 | base02: '#073642' 8 | base01: '#586e75' 9 | base00: '#657b83' 10 | base0: '#839496' 11 | base1: '#93a1a1' 12 | base2: '#eee8d5' 13 | base3: '#fdf6e3' 14 | yellow: '#b58900' 15 | orange: '#cb4b16' 16 | red: '#dc322f' 17 | magenta: '#d33682' 18 | violet: '#6c71c4' 19 | blue: '#268bd2' 20 | cyan: '#2aa198' 21 | green: '#859900' 22 | custom: '#1c5766' 23 | window_colors: 24 | focused: 25 | border: 'green' 26 | background: 'green' 27 | text: 'base3' 28 | indicator: 'violet' 29 | focused_inactive: 30 | border: 'base02' 31 | background: 'base02' 32 | text: 'base2' 33 | indicator: 'violet' 34 | unfocused: 35 | border: 'base02' 36 | background: 'base02' 37 | text: 'base1' 38 | indicator: 'base01' 39 | urgent: 40 | border: 'magenta' 41 | background: 'magenta' 42 | text: 'base3' 43 | indicator: 'red' 44 | bar_colors: 45 | separator: 'red' 46 | background: 'base03' 47 | statusline: 'blue' 48 | focused_workspace: 49 | border: 'base3' 50 | background: 'green' 51 | text: 'base3' 52 | active_workspace: 53 | border: 'base3' 54 | background: 'violet' 55 | text: 'base3' 56 | inactive_workspace: 57 | border: 'base01' 58 | background: 'base1' 59 | text: 'base03' 60 | urgent_workspace: 61 | border: 'magenta' 62 | background: 'magenta' 63 | text: 'base3' 64 | -------------------------------------------------------------------------------- /themes/tomorrow-night-80s: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | colors: 5 | background: '#2d2d2d' 6 | current_line: '#393939' 7 | selection: '#515151' 8 | foreground: '#cccccc' 9 | comment: '#999999' 10 | red: '#f2777a' 11 | orange: '#f99157' 12 | yellow: '#ffcc66' 13 | green: '#99cc99' 14 | aqua: '#66cccc' 15 | blue: '#6699cc' 16 | purple: '#cc99cc' 17 | 18 | meta: 19 | description: 'Tomorrow Night 80s theme by jmfurlott ' 20 | window_colors: 21 | focused: 22 | border: 'green' 23 | background: 'green' 24 | text: '#000000' 25 | indicator: 'background' 26 | focused_inactive: 27 | border: 'current_line' 28 | background: 'current_line' 29 | text: '#888888' 30 | indicator: '#292d2e' 31 | unfocused: 32 | border: 'background' 33 | background: 'background' 34 | text: 'comment' 35 | indicator: '#292d2e' 36 | urgent: 37 | border: '#2f343a' 38 | background: '#900000' 39 | text: '#ffffff' 40 | indicator: '#900000' 41 | bar_colors: 42 | separator: 'selection' 43 | background: 'background' 44 | statusline: 'foreground' 45 | focused_workspace: 46 | border: 'green' 47 | background: 'green' 48 | text: '#000000' 49 | active_workspace: 50 | border: '#333333' 51 | background: '#333333' 52 | text: '#ffffff' 53 | inactive_workspace: 54 | border: 'background' 55 | background: 'background' 56 | text: 'comment' 57 | urgent_workspace: 58 | border: 'red' 59 | background: 'red' 60 | text: '#ffffff' 61 | -------------------------------------------------------------------------------- /themes/ubuntu: -------------------------------------------------------------------------------- 1 | # vim: filetype=yaml 2 | # TODO: use color aliases to make the theme more readable 3 | --- 4 | meta: 5 | description: 'Ubuntu theme by lasers' 6 | window_colors: 7 | focused: 8 | border: '#dd4814' 9 | background: '#dd4814' 10 | text: '#ffffff' 11 | indicator: '#902a07' 12 | focused_inactive: 13 | border: '#5e2750' 14 | background: '#5e2750' 15 | text: '#aea79f' 16 | indicator: '#5e2750' 17 | unfocused: 18 | border: '#5e2750' 19 | background: '#5e2750' 20 | text: '#aea79f' 21 | indicator: '#5e2750' 22 | urgent: 23 | border: '#77216f' 24 | background: '#77216f' 25 | text: '#ffffff' 26 | indicator: '#efb73e' 27 | bar_colors: 28 | separator: '#333333' 29 | background: '#2c001e' 30 | statusline: '#aea79f' 31 | focused_workspace: 32 | border: '#dd4814' 33 | background: '#dd4814' 34 | text: '#ffffff' 35 | active_workspace: 36 | border: '#902a07' 37 | background: '#902a07' 38 | text: '#aea79f' 39 | inactive_workspace: 40 | border: '#902a07' 41 | background: '#902a07' 42 | text: '#aea79f' 43 | urgent_workspace: 44 | border: '#77216f' 45 | background: '#77216f' 46 | text: '#ffffff' 47 | --------------------------------------------------------------------------------