mirror of
				https://github.com/Clortox/rss-cli.git
				synced 2025-07-17 14:12:11 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			219 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
///////////////////////////////////////////////////////////////////////////////
 | 
						|
// Tyler Perkins
 | 
						|
// 7-23-21
 | 
						|
// options implementation
 | 
						|
//
 | 
						|
 | 
						|
#include "options.hpp"
 | 
						|
 | 
						|
void help(char* progName){
 | 
						|
    std::cout << "Usage: " << progName << " [-u FEED_URI] [CHANNEL FLAGS] ";
 | 
						|
    std::cout << "[-i ITEM_INDEX] [ITEM FLAGS]\n";
 | 
						|
    std::cout << "Options:\n";
 | 
						|
    std::cout << "Required Options:\n";
 | 
						|
    std::cout << " [-u, --uri] URI        URI of the rss stream\n\n";
 | 
						|
 | 
						|
    std::cout << "Channel information:\n";
 | 
						|
    std::cout << " [-t, --title]          Get title of channel\n";
 | 
						|
    std::cout << " [-l, --link]           Get link to channel\n";
 | 
						|
    std::cout << " [-d, --description]    Get description of channel\n";
 | 
						|
    std::cout << " [-e, --language]       Get language code of channel\n";
 | 
						|
    std::cout << " [-m, --webmaster]      Get webMaster's email\n";
 | 
						|
    std::cout << " [-c, --copyright]      Get copyright\n";
 | 
						|
    std::cout << " [-p, --pubdate]        Get publishing date\n";
 | 
						|
    std::cout << " [-q, --managingeditor] Get managing editor\n";
 | 
						|
    std::cout << " [-g, --generator]      Get generator of this feed\n";
 | 
						|
    std::cout << " [-o, --docs]           Get link to RSS documentation\n";
 | 
						|
    std::cout << " [-w, --ttl]            Get ttl, time that channel can be\n";
 | 
						|
    std::cout << "                        cached before being updated\n";
 | 
						|
    std::cout << " [-b, --builddate]      Get last time the channel's\n";
 | 
						|
    std::cout << "                        content changed\n";
 | 
						|
    std::cout << " [-i, --item] INDEX     Provide index of item to display\n";
 | 
						|
    std::cout << "                        If no index is provided, assume the first\n";
 | 
						|
    std::cout << "                        item in the feed. All following flags will\n";
 | 
						|
    std::cout << "                        be parsed as item options, till another\n";
 | 
						|
    std::cout << "                        item is provided\n\n";
 | 
						|
 | 
						|
    std::cout << "Item options:\n";
 | 
						|
    std::cout << " [-t, --title]          Get title of item\n";
 | 
						|
    std::cout << " [-l, --link]           Get link\n";
 | 
						|
    std::cout << " [-d, --description]    Get description\n";
 | 
						|
    std::cout << " [-a, --author]         Get author\n";
 | 
						|
    std::cout << " [-z, --category]       Get category list\n";
 | 
						|
    std::cout << " [-f, --comments]       Get link to comments\n";
 | 
						|
    std::cout << " [-j, --guid]           Get GUID\n";
 | 
						|
    std::cout << " [-p, --pubdate]        Get publishing date\n";
 | 
						|
    std::cout << " [-s, --source]         Get source of item\n\n";
 | 
						|
 | 
						|
    std::cout << "General options:\n";
 | 
						|
    std::cout << " [-h, --help]           Show this message\n\n";
 | 
						|
 | 
						|
    std::cout << "For more information, refer to the RSS 2.0 documentation\n";
 | 
						|
    std::cout << "https://validator.w3.org/feed/docs/rss2.html\n";
 | 
						|
 | 
						|
    exit(1);
 | 
						|
}
 | 
						|
 | 
						|
option_flags* parse_options(int argc, char** argv) {
 | 
						|
    int option_index = 0;
 | 
						|
    int c;
 | 
						|
 | 
						|
    item_flags* current_item = nullptr;
 | 
						|
    option_flags* ret = new option_flags;
 | 
						|
 | 
						|
    ret->item_count = 0;
 | 
						|
    ret->items = nullptr;
 | 
						|
 | 
						|
    while(true){
 | 
						|
        c = getopt_long(argc, argv, optarg_string, 
 | 
						|
                long_options, &option_index);
 | 
						|
        if(c == -1)
 | 
						|
            break;
 | 
						|
 | 
						|
        switch(c){
 | 
						|
            case 'u':
 | 
						|
                ret->uri = std::string(optarg);
 | 
						|
                break;
 | 
						|
            case 't':
 | 
						|
                if(current_item == nullptr)
 | 
						|
                    ret->title ^= 1;
 | 
						|
                else
 | 
						|
                    current_item->title ^= 1;
 | 
						|
                break;
 | 
						|
            case 'l':
 | 
						|
                if(current_item == nullptr)
 | 
						|
                    ret->link ^= 1;
 | 
						|
                else
 | 
						|
                    current_item->link ^= 1;
 | 
						|
                break;
 | 
						|
            case 'd':
 | 
						|
                if(current_item == nullptr)
 | 
						|
                    ret->description ^= 1;
 | 
						|
                else
 | 
						|
                    current_item->description ^= 1;
 | 
						|
                break;
 | 
						|
            case 'e':
 | 
						|
                ret->language ^= 1;
 | 
						|
                break;
 | 
						|
            case 'm':
 | 
						|
                ret->webmaster ^= 1;
 | 
						|
                break;
 | 
						|
            case 'c':
 | 
						|
                ret->copyright ^= 1;
 | 
						|
                break;
 | 
						|
            case 'p':
 | 
						|
                if(current_item == nullptr)
 | 
						|
                    ret->pubdate ^= 1;
 | 
						|
                else
 | 
						|
                    current_item->pubdate ^= 1;
 | 
						|
                break;
 | 
						|
            case 'q':
 | 
						|
                ret->managingeditor ^= 1;
 | 
						|
                break;
 | 
						|
            case 'g':
 | 
						|
                ret->generator ^= 1;
 | 
						|
                break;
 | 
						|
            case 'o':
 | 
						|
                ret->docs ^= 1;
 | 
						|
                break;
 | 
						|
            case 'w':
 | 
						|
                ret->ttl ^= 1;
 | 
						|
                break;
 | 
						|
            case 'b':
 | 
						|
                ret->builddate ^= 1;
 | 
						|
                break;
 | 
						|
            case 'i':
 | 
						|
                if(ret->items == nullptr){
 | 
						|
                    ret->items = new item_flags[ret->item_count + 1];
 | 
						|
                    current_item = &(ret->items[0]);
 | 
						|
                    ret->item_count++;
 | 
						|
                    current_item->index = optarg ? atoi(optarg) : 0;
 | 
						|
                } else {
 | 
						|
                    item_flags* new_flags = new item_flags[ret->item_count + 1];
 | 
						|
                    for(unsigned int i=0;i<ret->item_count;++i)
 | 
						|
                        new_flags[i] = ret->items[i];
 | 
						|
                    delete ret->items;
 | 
						|
                    ret->items = new_flags;
 | 
						|
                    current_item = &(ret->items[ret->item_count]);
 | 
						|
                    ret->item_count++;
 | 
						|
                    current_item->index = optarg ? atoi(optarg) : 0;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case 'a':
 | 
						|
                if(current_item == nullptr){
 | 
						|
                    std::cerr << "Invalid option in this context: [-a --author]" << std::endl;
 | 
						|
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
						|
                } else
 | 
						|
                    current_item->author ^= 1;
 | 
						|
                break;
 | 
						|
            case 'z':
 | 
						|
                if(current_item == nullptr){
 | 
						|
                    std::cerr << "Invalid option in this context: [-z --category]" << std::endl;
 | 
						|
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
						|
                } else
 | 
						|
                    current_item->category ^= 1;
 | 
						|
                break;
 | 
						|
            case 'f':
 | 
						|
                if(current_item == nullptr){
 | 
						|
                    std::cerr << "Invalid option in this context: [-f --comments]" << std::endl;
 | 
						|
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
						|
                } else
 | 
						|
                    current_item->comments ^= 1;
 | 
						|
                break;
 | 
						|
            case 'j':
 | 
						|
                if(current_item == nullptr){
 | 
						|
                    std::cerr << "Invalid option in this context: [-j --guid]" << std::endl;
 | 
						|
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
						|
                } else
 | 
						|
                    current_item->guid ^= 1;
 | 
						|
                break;
 | 
						|
            case 's':
 | 
						|
                if(current_item == nullptr){
 | 
						|
                    std::cerr << "Invalid option in this context: [-s --source]" << std::endl;
 | 
						|
                    std::cerr << "Did you provide the [-i --index] flag first?" << std::endl;
 | 
						|
                } else
 | 
						|
                    current_item->source ^= 1;
 | 
						|
                break;
 | 
						|
            case ':': //go here if flag that requires argument is passed, but no arg given
 | 
						|
                switch(optopt){
 | 
						|
                    case 'i':
 | 
						|
                        if(ret->items == nullptr){
 | 
						|
                            ret->item_count++;
 | 
						|
                            ret->items = new item_flags[ret->item_count];
 | 
						|
                            current_item = &(ret->items[0]);
 | 
						|
                            current_item->index = 1;
 | 
						|
                        } else {
 | 
						|
                            item_flags* new_flags = new item_flags[ret->item_count + 1];
 | 
						|
                            for(unsigned int i=0;i<ret->item_count;++i)
 | 
						|
                                new_flags[i] = ret->items[i];
 | 
						|
                            delete ret->items;
 | 
						|
                            ret->items = new_flags;
 | 
						|
                            current_item = &(ret->items[ret->item_count]);
 | 
						|
                            ret->item_count++;
 | 
						|
                            current_item->index = 1;
 | 
						|
                        }
 | 
						|
                        break;
 | 
						|
                    default:
 | 
						|
                        std::cerr << "Invalid use: option -" << (char)optopt 
 | 
						|
                            << " requires an argument" << std::endl;
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
                break;
 | 
						|
            case '?':
 | 
						|
                std::cerr << "Unknown option: " << (char)optopt << std::endl;
 | 
						|
            case 'h':
 | 
						|
                help(argv[0]);
 | 
						|
                break;
 | 
						|
            default:
 | 
						|
                abort();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if(ret->uri == ""){
 | 
						|
        std::cerr << "Missing required option! -u/--uri" << std::endl;
 | 
						|
        exit(-1);
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 |