├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.md ├── sample.sh └── src ├── iomuxer.rs └── main.rs /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | - nightly 6 | script: 7 | - make build 8 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "colerr" 3 | version = "1.0.0" 4 | dependencies = [ 5 | "docopt 0.6.82 (registry+https://github.com/rust-lang/crates.io-index)", 6 | "env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 7 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 8 | "mioco 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 9 | "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 10 | "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", 11 | ] 12 | 13 | [[package]] 14 | name = "aho-corasick" 15 | version = "0.5.2" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | dependencies = [ 18 | "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "bitflags" 23 | version = "0.4.0" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "bytes" 28 | version = "0.3.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | 31 | [[package]] 32 | name = "cfg-if" 33 | version = "0.1.0" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | 36 | [[package]] 37 | name = "context" 38 | version = "1.0.0" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | dependencies = [ 41 | "gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 44 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 45 | ] 46 | 47 | [[package]] 48 | name = "docopt" 49 | version = "0.6.82" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | dependencies = [ 52 | "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 56 | ] 57 | 58 | [[package]] 59 | name = "env_logger" 60 | version = "0.3.4" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | dependencies = [ 63 | "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 64 | "regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)", 65 | ] 66 | 67 | [[package]] 68 | name = "gcc" 69 | version = "0.3.32" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | 72 | [[package]] 73 | name = "kernel32-sys" 74 | version = "0.2.2" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | dependencies = [ 77 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 78 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 79 | ] 80 | 81 | [[package]] 82 | name = "lazy_static" 83 | version = "0.2.1" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | 86 | [[package]] 87 | name = "libc" 88 | version = "0.2.15" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | 91 | [[package]] 92 | name = "log" 93 | version = "0.3.6" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | 96 | [[package]] 97 | name = "memchr" 98 | version = "0.1.11" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | dependencies = [ 101 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 102 | ] 103 | 104 | [[package]] 105 | name = "mio" 106 | version = "0.5.1" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | dependencies = [ 109 | "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 110 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 112 | "miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 113 | "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", 114 | "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 115 | "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 118 | ] 119 | 120 | [[package]] 121 | name = "mioco" 122 | version = "0.8.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | dependencies = [ 125 | "context 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 126 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 127 | "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 128 | "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 129 | "nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 130 | "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", 131 | "owning_ref 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 132 | "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 133 | "spin 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 135 | "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 136 | ] 137 | 138 | [[package]] 139 | name = "miow" 140 | version = "0.1.3" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | dependencies = [ 143 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 144 | "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", 145 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 147 | ] 148 | 149 | [[package]] 150 | name = "net2" 151 | version = "0.2.26" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | dependencies = [ 154 | "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 155 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 156 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 157 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 159 | ] 160 | 161 | [[package]] 162 | name = "nix" 163 | version = "0.5.1" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | dependencies = [ 166 | "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 167 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 168 | ] 169 | 170 | [[package]] 171 | name = "nix" 172 | version = "0.6.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | dependencies = [ 175 | "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 176 | "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 177 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 178 | "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 179 | "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", 180 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 181 | ] 182 | 183 | [[package]] 184 | name = "num_cpus" 185 | version = "0.2.13" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | dependencies = [ 188 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 189 | ] 190 | 191 | [[package]] 192 | name = "owning_ref" 193 | version = "0.2.0" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | 196 | [[package]] 197 | name = "regex" 198 | version = "0.1.73" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 202 | "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 203 | "regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 205 | "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 206 | ] 207 | 208 | [[package]] 209 | name = "regex-syntax" 210 | version = "0.3.4" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | 213 | [[package]] 214 | name = "rustc-serialize" 215 | version = "0.3.19" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | 218 | [[package]] 219 | name = "rustc_version" 220 | version = "0.1.7" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | dependencies = [ 223 | "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", 224 | ] 225 | 226 | [[package]] 227 | name = "semver" 228 | version = "0.1.20" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | 231 | [[package]] 232 | name = "slab" 233 | version = "0.1.3" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | 236 | [[package]] 237 | name = "slab" 238 | version = "0.2.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | 241 | [[package]] 242 | name = "spin" 243 | version = "0.4.3" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | 246 | [[package]] 247 | name = "strsim" 248 | version = "0.3.0" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | 251 | [[package]] 252 | name = "thread-id" 253 | version = "2.0.0" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | dependencies = [ 256 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 257 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 258 | ] 259 | 260 | [[package]] 261 | name = "thread-scoped" 262 | version = "1.0.1" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | 265 | [[package]] 266 | name = "thread_local" 267 | version = "0.2.6" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | dependencies = [ 270 | "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 271 | ] 272 | 273 | [[package]] 274 | name = "time" 275 | version = "0.1.35" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | dependencies = [ 278 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 279 | "libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", 280 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 281 | ] 282 | 283 | [[package]] 284 | name = "utf8-ranges" 285 | version = "0.1.3" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | 288 | [[package]] 289 | name = "void" 290 | version = "1.0.2" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | 293 | [[package]] 294 | name = "winapi" 295 | version = "0.2.8" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | 298 | [[package]] 299 | name = "winapi-build" 300 | version = "0.1.1" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | 303 | [[package]] 304 | name = "ws2_32-sys" 305 | version = "0.2.1" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | dependencies = [ 308 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 309 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 310 | ] 311 | 312 | [metadata] 313 | "checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9" 314 | "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" 315 | "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" 316 | "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" 317 | "checksum context 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32079bad06e056de0007a408d217fd37d9b0835a655beb8813d49eca50dbb7c0" 318 | "checksum docopt 0.6.82 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20016093b4e545dccf6ad4a01099de0b695f9bc99b08210e68f6425db2d37d" 319 | "checksum env_logger 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "82dcb9ceed3868a03b335657b85a159736c961900f7e7747d3b0b97b9ccb5ccb" 320 | "checksum gcc 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "dcb000abd6df9df4c637f75190297ebe56c1d7e66b56bbf3b4aa7aece15f61a2" 321 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 322 | "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" 323 | "checksum libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "23e3757828fa702a20072c37ff47938e9dd331b92fac6e223d26d4b7a55f7ee2" 324 | "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" 325 | "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" 326 | "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" 327 | "checksum mioco 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbbc5c55b2135ed8739097854ddbbed45188a2dc6f58f2bd0e5984a10a60b15" 328 | "checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a" 329 | "checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2" 330 | "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" 331 | "checksum nix 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a7bb1da2be7da3cbffda73fc681d509ffd9e665af478d2bee1907cee0bc64b2" 332 | "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" 333 | "checksum owning_ref 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ba6a14c7d6fb686c1c542663b2094934f1cbfbdb22b70305f09ed8eb2f2edf3" 334 | "checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2" 335 | "checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199" 336 | "checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" 337 | "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" 338 | "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" 339 | "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" 340 | "checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" 341 | "checksum spin 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b1f9f6eb067165a890f257804d5f4e358b7b7811a4a7c34b0345f624c0f94" 342 | "checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825" 343 | "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" 344 | "checksum thread-scoped 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14387dce246d09efe184c8ebc34d9db5c0672a908b2f50efc53359ae13d5ae68" 345 | "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d" 346 | "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" 347 | "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" 348 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 349 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 350 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 351 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 352 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "colerr" 3 | version = "1.0.0" 4 | authors = ["Dawid Ciężarkiewicz "] 5 | description = "colerr will wrap a given process and colorize it's standard error output." 6 | keywords = ["cli", "color", "colour", "tool"] 7 | license = "MPL-2.0" 8 | documentation = "https://github.com/dpc/colerr/" 9 | homepage = "https://github.com/dpc/colerr" 10 | repository = "https://github.com/dpc/colerr" 11 | readme = "README.md" 12 | 13 | 14 | [dependencies] 15 | libc = "0.2.13" 16 | env_logger = "0.3.3" 17 | docopt = "0.6.18" 18 | rustc-serialize = "0.3.19" 19 | mioco = "0.8.0" 20 | nix = "0.6.0" 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PKG_NAME=colerr 2 | DOCS_DEFAULT_MODULE=colerr 3 | DEFAULT_TARGET=build 4 | EXAMPLES = 5 | 6 | default: $(DEFAULT_TARGET) 7 | 8 | # Mostly generic part goes below 9 | 10 | ifneq ($(RELEASE),) 11 | $(info RELEASE BUILD) 12 | CARGO_FLAGS += --release 13 | ALL_TARGETS += build test bench $(EXAMPLES) 14 | else 15 | $(info DEBUG BUILD; use `RELEASE=true make [args]` for release build) 16 | ALL_TARGETS += build test $(EXAMPLES) 17 | endif 18 | 19 | all: $(ALL_TARGETS) 20 | 21 | .PHONY: run test build doc clean 22 | run test build clean: 23 | cargo $@ $(CARGO_FLAGS) 24 | 25 | .PHONY: bench 26 | bench: 27 | cargo $@ $(filter-out --release,$(CARGO_FLAGS)) 28 | 29 | .PHONY: longtest 30 | longtest: 31 | for i in `seq 100`; do cargo test $(CARGO_FLAGS) || exit 1 ; done 32 | 33 | .PHONY: $(EXAMPLES) 34 | $(EXAMPLES): 35 | cargo build --example $@ $(CARGO_FLAGS) 36 | 37 | .PHONY: doc 38 | doc: 39 | cargo doc 40 | 41 | .PHONY: publishdoc 42 | publishdoc: doc 43 | echo '' > target/doc/index.html 44 | ghp-import -n target/doc 45 | git push -f origin gh-pages 46 | 47 | .PHONY: docview 48 | docview: doc 49 | xdg-open target/doc/$(PKG_NAME)/index.html 50 | 51 | .PHONY: FORCE 52 | FORCE: 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `colerr` 2 | 3 |

4 | 5 | Build Status 6 | 7 | 8 | Gitter Chat 9 | 10 |
11 | Documentation 12 |

13 | 14 | ## Introduction 15 | 16 | `colerr` will wrap a given process and colorize it's standard error output. 17 | 18 | `colerr` is written in [rust programming language][rust] and utilizes: 19 | [mio][mio] and [mioco][mioco] libraries. You probably don't care, but it's kind 20 | of important so I've mentioned it here. 21 | 22 | [mio]: https://github.com/carllerche/mio 23 | [mioco]: https://github.com/dpc/mioco 24 | [rust]: http://rust-lang.org 25 | 26 | # Building 27 | 28 | You need [rust][rust] compiler bundled with `cargo`. Then `cargo build --release` should do the job. 29 | 30 | Resulting binary will be in `./target/release/colerr`. Just copy it to somewhere to your `$PATH`. 31 | 32 | ``` 33 | Usage: 34 | colorout [--] ... 35 | ``` 36 | 37 | # Internals 38 | 39 | `colerr` works by spawning a IO-handling child process that takes care of 40 | colorizing output. The parent process `exec`-s the requested command with 41 | `stdin`, `stdout` and `stderr` routed to a child. 42 | 43 | This way `colerr` can be used as a drop-in replacement, as the `colerr`-ed PID 44 | will be the PID of the wrapped command. All signals etc. will be handled by the 45 | wrapped process itself, the only difference being a standard IO being handled 46 | by additional child process. 47 | -------------------------------------------------------------------------------- /sample.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export 4 | while read line ; do 5 | #for line in `seq 0 10`; do 6 | if [ $(($RANDOM % 2)) == "0" ] ; then 7 | echo "STDOUT: $line" 8 | else 9 | echo "STDERR: $line" 1>&2 10 | fi 11 | sleep 1 12 | done 13 | -------------------------------------------------------------------------------- /src/iomuxer.rs: -------------------------------------------------------------------------------- 1 | use mioco::unix::{UnixStream}; 2 | use std::os::unix::io::{FromRawFd, AsRawFd}; 3 | use std::io; 4 | use nix; 5 | 6 | use mioco; 7 | 8 | use FdPipe; 9 | use Fd; 10 | 11 | pub fn start(parent_stdin : FdPipe, parent_stdout : FdPipe, parent_stderr : FdPipe) { 12 | let parent_stdin = parent_stdin.tx; 13 | let parent_stdout = parent_stdout.rx; 14 | let parent_stderr = parent_stderr.rx; 15 | let own_stdin = Fd(0); 16 | let own_stdout = Fd(1); 17 | 18 | parent_stdin.set_nonblocking(); 19 | parent_stdout.set_nonblocking(); 20 | parent_stdout.set_nonblocking(); 21 | own_stdin.set_nonblocking(); 22 | own_stdout.set_nonblocking(); 23 | 24 | mioco::start(move || -> io::Result<()> { 25 | mioco::spawn(move || -> io::Result<()> { 26 | let mut from = unsafe {UnixStream::from_raw_fd(own_stdin.raw())}; 27 | let mut to = unsafe {UnixStream::from_raw_fd(parent_stdin.raw())}; 28 | try!(io::copy(&mut from, &mut to)); 29 | nix::unistd::close(to.as_raw_fd()).expect("close()"); 30 | Ok(()) 31 | }); 32 | 33 | mioco::spawn(move || -> io::Result<()> { 34 | use std::io::{Read, Write}; 35 | 36 | let mut buf = [0u8; 1024]; 37 | let mut from0 = unsafe {UnixStream::from_raw_fd(parent_stdout.raw())}; 38 | let mut from1 = unsafe {UnixStream::from_raw_fd(parent_stderr.raw())}; 39 | let mut to = unsafe {UnixStream::from_raw_fd(own_stdout.raw())}; 40 | let mut last_source = 0; 41 | 42 | let _ : io::Result<()> = (|| -> io::Result<()> { 43 | loop { 44 | let mut source = 0u8; 45 | select!( 46 | r:from0 => { source = 0; }, 47 | r:from1 => { source = 1; }, 48 | ); 49 | 50 | let mut changed = false; 51 | 52 | if last_source != source { 53 | last_source = source; 54 | changed = true; 55 | } 56 | 57 | if changed { 58 | if let Err(_) = to.write_all( 59 | if source == 0 { 60 | "\x1b[0m" 61 | } else if source == 1 { 62 | "\x1b[31m" 63 | } else { 64 | panic!("wrong source") 65 | }.as_bytes() 66 | ) { 67 | break; 68 | } 69 | } 70 | 71 | let res = if source == 0 { 72 | &mut from0 73 | } else if source == 1 { 74 | &mut from1 75 | } else { 76 | panic!() 77 | }.read(&mut buf); 78 | 79 | match res { 80 | Err(_) => break, 81 | Ok(0) => /* EOF */ break, 82 | Ok(size) => { 83 | try!(to.write_all(&mut buf[0..size])); 84 | } 85 | } 86 | let _ = try!(to.write_all("\x1b[0m".as_bytes())); 87 | } 88 | Ok(()) 89 | })(); 90 | 91 | let _ = try!(to.write_all("\x1b[0m".as_bytes())); 92 | Ok(()) 93 | }); 94 | Ok(()) 95 | }).unwrap().unwrap(); 96 | } 97 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate rustc_serialize; 2 | extern crate libc; 3 | #[macro_use] 4 | extern crate mioco; 5 | extern crate nix; 6 | extern crate docopt; 7 | extern crate env_logger; 8 | 9 | use docopt::Docopt; 10 | use std::os::unix::io::FromRawFd; 11 | use std::fs; 12 | use std::io; 13 | use libc::c_int; 14 | use std::ffi::CString; 15 | use nix::unistd::execvp; 16 | use nix::fcntl::{fcntl, FcntlArg, O_NONBLOCK}; 17 | 18 | mod iomuxer; 19 | 20 | static USAGE: &'static str = " 21 | Usage: 22 | colorout [--] ... 23 | "; 24 | 25 | #[derive(Copy, Clone, Debug)] 26 | pub struct Fd(c_int); 27 | 28 | impl Fd { 29 | 30 | pub fn raw(&self) -> c_int { 31 | let Fd(fd) = *self; 32 | 33 | fd 34 | } 35 | 36 | pub fn close(&self) -> io::Result<()> { 37 | match unsafe { libc::close(self.raw()) } { 38 | err if err < 0 => { 39 | Err(io::Error::from_raw_os_error(err)) 40 | }, 41 | _ => Ok(()) 42 | } 43 | } 44 | 45 | pub fn to_file(&self) -> fs::File { 46 | unsafe { fs::File::from_raw_fd(self.raw()) } 47 | } 48 | 49 | 50 | pub fn dup_as(&self, to : Fd) -> io::Result<()> { 51 | match unsafe { libc::dup2(self.raw(), to.raw()) } { 52 | err if err < 0 => { 53 | Err(io::Error::from_raw_os_error(err)) 54 | }, 55 | _ => Ok(()) 56 | } 57 | } 58 | 59 | pub fn set_nonblocking(&self) { 60 | fcntl(self.raw(), FcntlArg::F_SETFL(O_NONBLOCK)).expect("fcntl"); 61 | } 62 | } 63 | 64 | #[derive(Copy, Clone, Debug)] 65 | pub struct FdPipe { 66 | rx : Fd, 67 | tx : Fd, 68 | } 69 | 70 | impl FdPipe { 71 | fn new() -> FdPipe { 72 | let mut fds = [0 as c_int, 0 as c_int]; 73 | 74 | let ret = unsafe { libc::pipe(fds.as_mut_ptr())}; 75 | if ret < 0 { 76 | panic!("unistd::pipe failed: {}", ret); 77 | } 78 | 79 | FdPipe { rx: Fd(fds[0]), tx: Fd(fds[1]) } 80 | } 81 | 82 | fn rx(&self) -> Fd { 83 | self.rx 84 | } 85 | 86 | fn tx(&self) -> Fd { 87 | self.tx 88 | } 89 | } 90 | 91 | #[derive(Debug, RustcDecodable)] 92 | struct Args { 93 | arg_cmd: Vec, 94 | } 95 | 96 | fn main() { 97 | env_logger::init().unwrap(); 98 | 99 | let args : Args = Docopt::new(USAGE) 100 | .and_then(|d| d.decode()) 101 | .unwrap_or_else(|e| e.exit()); 102 | 103 | let stdout_pipe = FdPipe::new(); 104 | let stderr_pipe = FdPipe::new(); 105 | let stdin_pipe = FdPipe::new(); 106 | 107 | let child_pid = unsafe { libc::fork() }; 108 | 109 | if child_pid == 0 { 110 | // Output colorizing child 111 | stdin_pipe.rx().close().unwrap(); 112 | stdout_pipe.tx().close().unwrap(); 113 | stderr_pipe.tx().close().unwrap(); 114 | 115 | iomuxer::start(stdin_pipe, stdout_pipe, stderr_pipe); 116 | 117 | } else { 118 | // The program to be run 119 | stdin_pipe.tx().close().unwrap(); 120 | stdout_pipe.rx().close().unwrap(); 121 | stderr_pipe.rx().close().unwrap(); 122 | 123 | stdin_pipe.rx().dup_as(Fd(0)).unwrap(); 124 | stdout_pipe.tx().dup_as(Fd(1)).unwrap(); 125 | stderr_pipe.tx().dup_as(Fd(2)).unwrap(); 126 | 127 | stdin_pipe.rx().close().unwrap(); 128 | stdout_pipe.tx().close().unwrap(); 129 | stderr_pipe.tx().close().unwrap(); 130 | 131 | let cmd = CString::new(args.arg_cmd[0].as_str()).unwrap(); 132 | let args_iter = args.arg_cmd.iter(); 133 | let args : Vec = args_iter.map(|s| CString::new(s.as_str()).unwrap()).collect(); 134 | 135 | execvp( 136 | &cmd, 137 | args.as_slice(), 138 | ).expect("execve failed"); 139 | } 140 | } 141 | --------------------------------------------------------------------------------