11use std:: error:: Error ;
2- #[ cfg( not( feature = "inline-fortune" ) ) ]
3- use std:: {
4- ffi:: OsStr ,
5- fs:: { self , File } ,
6- io:: { self , Read } ,
7- path:: PathBuf ,
8- } ;
2+ use std:: { fs:: File , io:: Read } ;
93use tinyrand:: Rand ;
104
115fn check_fortune_constraints (
@@ -34,8 +28,42 @@ fn check_fortune_constraints(
3428 } )
3529}
3630
31+ fn get_external_fortune (
32+ rng : & mut impl Rand ,
33+ list : & [ String ] ,
34+ include_off : bool ,
35+ max_width : Option < u64 > ,
36+ max_lines : Option < u64 > ,
37+ ) -> Result < String , Box < dyn Error > > {
38+ let file_path = match include_off {
39+ true => {
40+ let idx = rng. next_lim_usize ( list. len ( ) ) ;
41+ list[ idx] . clone ( )
42+ }
43+ false => {
44+ let filtered: Vec < & String > = list. into_iter ( ) . filter ( |x| !x. contains ( "off" ) ) . collect ( ) ;
45+ let idx = rng. next_lim_usize ( filtered. len ( ) ) ;
46+ filtered[ idx] . clone ( )
47+ }
48+ } ;
49+
50+ match File :: open ( file_path) {
51+ Ok ( mut file) => {
52+ let mut string_buf = String :: new ( ) ;
53+ let _result = file. read_to_string ( & mut string_buf) ?;
54+ let no_cr = string_buf. replace ( "\r " , "" ) ;
55+ let split: Vec < & str > = no_cr
56+ . split ( "\n %\n " )
57+ . filter ( |element| check_fortune_constraints ( element, max_width, max_lines) )
58+ . collect ( ) ;
59+ let chosen_idx = rng. next_lim_usize ( split. len ( ) ) ;
60+ Ok ( split[ chosen_idx] . to_string ( ) )
61+ }
62+ Err ( e) => panic ! ( "Could not open Fortune file! {e}" ) ,
63+ }
64+ }
65+
3766///default method of getting a fortune, without using the index file.
38- #[ cfg( not( feature = "inline-fortune" ) ) ]
3967pub fn get_fortune (
4068 _fortune_files : & [ String ] ,
4169 rng : & mut impl Rand ,
@@ -45,55 +73,52 @@ pub fn get_fortune(
4573) -> Result < String , Box < dyn Error > > {
4674 cfg_select ! {
4775 feature = "inline-fortune" => {
48- macro_rules! choose_inline_fortune {
49- ( $rng_ident: ident, $list_ident: ident, $max_wid_ident: ident, $max_lines_ident: ident) => { {
50- let list_iter: Vec <& ' static str > = $list_ident
51- . into_iter( )
52- . filter( |element| {
53- check_fortune_constraints( element, $max_wid_ident, $max_lines_ident)
54- } )
55- . collect( ) ;
56- let chosen_idx = $rng_ident. next_lim_usize( list_iter. len( ) ) ;
57- Ok ( $list_ident[ chosen_idx] . to_string( ) )
58- } } ;
59- }
60-
61- cfg_if:: cfg_if! {
62- if #[ cfg( feature="inline-off-fortune" ) ] {
63- if include_offensive {
64- let weight_off: f64 = OFF_FORTUNE_LIST . len( ) as f64 /( FORTUNE_LIST . len( ) as f64 + OFF_FORTUNE_LIST . len( ) as f64 ) ;
65- match rng. next_bool( weight_off. into( ) ) {
66- true => choose_inline_fortune!( rng, OFF_FORTUNE_LIST , max_width, max_lines) ,
67- false => choose_inline_fortune!( rng, FORTUNE_LIST , max_width, max_lines) ,
68- }
69- } else {
70- choose_inline_fortune!( rng, FORTUNE_LIST , max_width, max_lines)
76+ if !_fortune_files. is_empty( ) {
77+ get_external_fortune(
78+ rng,
79+ _fortune_files,
80+ include_offensive,
81+ max_width,
82+ max_lines
83+ )
84+ } else {
85+ let list = match include_offensive {
86+ true => {
87+ cfg_select! {
88+ feature = "inline-off-fortune" => {
89+ if include_offensive {
90+ let weight_off: f64 = OFF_FORTUNE_LIST . len( ) as f64 /( FORTUNE_LIST . len( ) as f64 + OFF_FORTUNE_LIST . len( ) as f64 ) ;
91+ match rng. next_bool( weight_off. into( ) ) {
92+ true => OFF_FORTUNE_LIST ,
93+ false => FORTUNE_LIST ,
94+ }
95+ } else {
96+ FORTUNE_LIST
97+ }
98+ }
99+ not( feature = "inline-off-fortune" ) => { FORTUNE_LIST }
100+ }
71101 }
72- } else {
73- let _ = include_offensive;
74- choose_inline_fortune!( rng, FORTUNE_LIST , max_width, max_lines)
75- }
102+ false => FORTUNE_LIST ,
103+ } ;
104+
105+ let list_iter: Vec <& ' static str > = list
106+ . into_iter( )
107+ . filter( |element| check_fortune_constraints( element, max_width, max_lines) )
108+ . collect( ) ;
109+ let chosen_idx = rng. next_lim_usize( list_iter. len( ) ) ;
110+ Ok ( list[ chosen_idx] . to_string( ) )
76111 }
77112
78113 }
79114 not( feature = "inline-fortune" ) => {
80- // TODO Choose the file to open, exclude offensive as necessary
81-
82- match File :: open( file_path) {
83- Ok ( mut file) => {
84- let mut string_buf = String :: new( ) ;
85- let _result = file. read_to_string( & mut string_buf) ?;
86- let no_cr = string_buf. replace( "\r " , "" ) ;
87- let split: Vec <& str > = no_cr
88- . split( "\n %\n " )
89- . filter( |element| check_fortune_constraints( element, max_width, max_lines) )
90- . collect( ) ;
91- let chosen_idx = rng. next_lim_usize( split. len( ) ) ;
92- Ok ( split[ chosen_idx] . to_string( ) )
93- }
94- Err ( e) => panic!( "Could not open Fortune file! {e}" ) ,
95- }
96-
115+ get_external_fortune(
116+ rng,
117+ _fortune_files,
118+ include_offensive,
119+ max_width,
120+ max_lines
121+ )
97122 }
98123 }
99124}
0 commit comments