forked from bonsai/harakit
		
	stris(1)
This commit is contained in:
		
							parent
							
								
									6132c9bf47
								
							
						
					
					
						commit
						cfef7aec1d
					
				
							
								
								
									
										13
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Makefile
									
									
									
									
									
								
							| @ -28,7 +28,7 @@ RUSTLIBS = --extern getopt=build/o/libgetopt.rlib \ | ||||
| CFLAGS += -I$(SYSEXITS) | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: dj false fop hru intcmp mm npc rpn scrut str strcmp swab true | ||||
| all: dj false fop hru intcmp mm npc rpn scrut str strcmp stris swab true | ||||
| 
 | ||||
| build: | ||||
| 	# keep build/include until bindgen(1) has stdin support | ||||
| @ -123,6 +123,14 @@ str: build/bin/str | ||||
| build/bin/str: src/str.c build | ||||
| 	$(CC) $(CFLAGS) -o $@ src/str.c | ||||
| 
 | ||||
| .PHONY: stris | ||||
| stris: build/bin/stris | ||||
| build/bin/stris: src/stris.rs build build/o/libgetopt.rlib \ | ||||
| 		build/o/libsysexits.rlib | ||||
| 	$(RUSTC) $(RUSTFLAGS) --extern getopt=build/o/libgetopt.rlib \
 | ||||
| 		--extern sysexits=build/o/libsysexits.rlib \
 | ||||
| 		-o $@ src/stris.rs | ||||
| 
 | ||||
| .PHONY: strcmp | ||||
| strcmp: build/bin/strcmp | ||||
| build/bin/strcmp: src/strcmp.c build | ||||
| @ -130,7 +138,8 @@ build/bin/strcmp: src/strcmp.c build | ||||
| 
 | ||||
| .PHONY: swab | ||||
| swab: build/bin/swab | ||||
| build/bin/swab: src/swab.rs build build/o/libsysexits.rlib | ||||
| build/bin/swab: src/swab.rs build build/o/libgetopt.rlib \ | ||||
| 		build/o/libsysexits.rlib | ||||
| 	$(RUSTC) $(RUSTFLAGS) --extern getopt=build/o/libgetopt.rlib \
 | ||||
| 		--extern sysexits=build/o/libsysexits.rlib \
 | ||||
| 		-o $@ src/swab.rs | ||||
|  | ||||
							
								
								
									
										118
									
								
								docs/stris.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								docs/stris.1
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | ||||
| .\" Copyright (c) 2023–2024 DTB <trinity@trinity.moe> | ||||
| .\" Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media> | ||||
| .\" | ||||
| .\" This work is licensed under CC BY-SA 4.0. To see a copy of this license, | ||||
| .\" visit <http://creativecommons.org/licenses/by-sa/4.0/>. | ||||
| 
 | ||||
| .TH STRIS 1 | ||||
| 
 | ||||
| .SH NAME | ||||
| 
 | ||||
| stris \(en test the character types of string arguments | ||||
| 
 | ||||
| .SH SYNOPSIS | ||||
| 
 | ||||
| stris | ||||
| .RB ( -7bcdlu ) | ||||
| .RB ( -i [ inclusions ]) | ||||
| .RB [ strings... ] | ||||
| 
 | ||||
| .SH DESCRIPTION | ||||
| 
 | ||||
| Stris tests each rune in an arbitrary quantity of string arguments, ensuring | ||||
| each meets any of the parameters specified in the program options. | ||||
| 
 | ||||
| .SH OPTIONS | ||||
| 
 | ||||
| .B -7 | ||||
| .RS | ||||
| Tests to see if runes are fit within seven bits; that is, that they are encoded | ||||
| with ASCII. | ||||
| .RE | ||||
| 
 | ||||
| .B -b | ||||
| .RS | ||||
| Tests to see if runes are blank or "whitespace"; characters that do not print | ||||
| but fill a predictable amount of space. | ||||
| .RE | ||||
| 
 | ||||
| .B -c | ||||
| .RS | ||||
| Tests to see if runes are control characters; characters that are not printing | ||||
| or graphical. | ||||
| .RE | ||||
| 
 | ||||
| .B -d | ||||
| .RS | ||||
| Tests to see if runes are numeric. This test does not only allow the ASCII | ||||
| digits but any numeric symbol. | ||||
| .RE | ||||
| 
 | ||||
| .B -i | ||||
| .RS | ||||
| Permits, in addition to the given specified parameters, all of the runes | ||||
| supplied in its option argument. | ||||
| .RE | ||||
| 
 | ||||
| .B -l | ||||
| .RS | ||||
| Tests to see if runes are in their lower case. | ||||
| .RE | ||||
| 
 | ||||
| .B -u | ||||
| .RS | ||||
| Tests to see if runes are in their upper case, or capitalized. | ||||
| .RE | ||||
| 
 | ||||
| .SH DIAGNOSTICS | ||||
| 
 | ||||
| Stris exits successfully if all runes in all given strings meet any of the | ||||
| specified parameters, or if no parameters were specified but all given strings | ||||
| were legibly encoded. It exits unsuccessfully if the previous is untrue, and if | ||||
| invalid options were given, or if no strings were given, a usage synopsis will | ||||
| be printed to the standard error. | ||||
| 
 | ||||
| .SH BUGS | ||||
| 
 | ||||
| There's no way of knowing which argument failed the test without re-testing | ||||
| arguments individually. | ||||
| 
 | ||||
| Some runes that can losslessly be encoded into ASCII from UTF-8 but in an | ||||
| "overlong encoding", where the rune was encoded with unnecessary leading | ||||
| zeroes causing it to span multiple bytes, won't be detected as ASCII. | ||||
| 
 | ||||
| .SH EXAMPLES | ||||
| 
 | ||||
| This is an sh(1p) snippet that checks to see if an environment variable is an | ||||
| ASCII digit. | ||||
| 
 | ||||
| .RS | ||||
| .R stris -7 "$v" && stris -d "$v" && echo ASCII digit. | ||||
| .RE | ||||
| 
 | ||||
| This is an sh(1p) snippet that checks to see if an environment variable is a | ||||
| hexadecimal number. | ||||
| 
 | ||||
| .RS | ||||
| .R stris -7 "$v" && stris -di ABCDEFabcdef "$v" && echo Hexadecimal number. | ||||
| .RE | ||||
| 
 | ||||
| .SH AUTHOR | ||||
| 
 | ||||
| Written by DTB <trinity@trinity.moe>. | ||||
| 
 | ||||
| .SH HISTORY | ||||
| 
 | ||||
| Stris replaces the former str(1) which took the name of a function from | ||||
| ctype(3) as its first argument and checked the following strings against it; | ||||
| str(1) exited unsuccessfully when it encountered any non-ASCII runes and could | ||||
| only have one parameter specified. | ||||
| 
 | ||||
| .SH COPYRIGHT | ||||
| 
 | ||||
| Copyright © 2023–2024 DTB. License AGPLv3+: GNU AGPL version 3 or later | ||||
| <https://gnu.org/licenses/gpl.html>. | ||||
| 
 | ||||
| .SH SEE ALSO | ||||
| 
 | ||||
| ascii(7), ctype(3p), strcmp(1) | ||||
							
								
								
									
										93
									
								
								src/stris.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/stris.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| /* | ||||
|  * Copyright (c) 2023–2024 DTB <trinity@trinity.moe> | ||||
|  * Copyright (c) 2023 Marceline Cramer <mars@tebibyte.media> | ||||
|  * SPDX-License-Identifier: AGPL-3.0-or-later | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify it under | ||||
|  * the terms of the GNU Affero General Public License as published by the Free | ||||
|  * Software Foundation, either version 3 of the License, or (at your option) any | ||||
|  * later version. | ||||
|  * 
 | ||||
|  * This program is distributed in the hope that it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
|  * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | ||||
|  * details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program. If not, see https://www.gnu.org/licenses/.
 | ||||
|  */ | ||||
| 
 | ||||
| use std::{ | ||||
| 	env::args, | ||||
| 	process::ExitCode | ||||
| }; | ||||
| 
 | ||||
| extern crate getopt; | ||||
| use getopt::{ Opt, Parser }; | ||||
| 
 | ||||
| extern crate sysexits; | ||||
| use sysexits::EX_USAGE; | ||||
| 
 | ||||
| struct Reqs { | ||||
| 	ascii: bool, blank: bool, cntrl: bool, digit: bool, lower: bool, | ||||
| 	upper: bool, inuse: bool, extra: String | ||||
| } | ||||
| 
 | ||||
| fn usage(s: &str) -> ExitCode { | ||||
| 	eprintln!("Usage: {} (-7bcdlu) (-i [inclusions]) [strings...]", s); | ||||
| 	ExitCode::from(EX_USAGE as u8) | ||||
| } | ||||
| 
 | ||||
| fn main() -> ExitCode { | ||||
| 	let argv = args().collect::<Vec<String>>(); | ||||
| 	let mut opts = Parser::new(&argv, "7bcdi:lu"); | ||||
| 	let mut reqs = Reqs { | ||||
| 		ascii: false, blank: false, cntrl: false, digit: false, lower: false, | ||||
| 		upper: false, inuse: false, extra: String::new() | ||||
| 	}; | ||||
| 
 | ||||
| 	loop { | ||||
| 		match opts.next() { | ||||
| 			None => break, | ||||
| 			Some(opt) => { | ||||
| 				match opt { | ||||
| 					Ok(Opt('7', None)) => reqs.ascii = true, | ||||
| 					Ok(Opt('b', None)) => reqs.blank = true, | ||||
| 					Ok(Opt('c', None)) => reqs.cntrl = true, | ||||
| 					Ok(Opt('d', None)) => reqs.digit = true, | ||||
| 					Ok(Opt('i', Some(arg))) => reqs.extra = arg, | ||||
| 					Ok(Opt('l', None)) => reqs.lower = true, | ||||
| 					Ok(Opt('u', None)) => reqs.upper = true, | ||||
| 					_ => { return usage(&argv[0]); } | ||||
| 				} | ||||
| 				reqs.inuse = true; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if argv.len() == opts.index() { | ||||
| 		return usage(&argv[0]); | ||||
| 	} | ||||
| 
 | ||||
| 	drop(argv); | ||||
| 
 | ||||
| 	if reqs.inuse { | ||||
| 		'args: for arg in args().skip(opts.index()) { | ||||
| 			for c in arg.chars() { | ||||
| 				if (reqs.ascii && c.is_ascii()) | ||||
| 						|| (reqs.blank && c.is_whitespace()) | ||||
| 						|| (reqs.cntrl && c.is_control()) | ||||
| 						|| (reqs.digit && c.is_numeric()) | ||||
| 						|| (reqs.lower && c.is_lowercase()) | ||||
| 						|| (reqs.upper && c.is_uppercase()) | ||||
| 						|| reqs.extra.contains(c) { | ||||
| 					continue 'args; | ||||
| 				} else { | ||||
| 					return ExitCode::FAILURE; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ExitCode::SUCCESS | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user