From 336ce2a1b3eed77e8916ebec79d31a8372de09ac Mon Sep 17 00:00:00 2001 From: s13bby Date: Thu, 3 Sep 2026 21:00:32 +0600 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.парсинг аргументов 2.скачивание файла по ссылке --- build.sh | 6 + libs/argparse.c | 395 ++++++++++++++++++++++++++++++++++++++++++++++++ libs/argparse.h | 133 ++++++++++++++++ main.c | 79 +++++++++- zenith-cli | Bin 0 -> 29136 bytes 5 files changed, 607 insertions(+), 6 deletions(-) create mode 100755 build.sh create mode 100644 libs/argparse.c create mode 100644 libs/argparse.h create mode 100755 zenith-cli diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..a1d0027 --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +echo "начинаю сборку" + +gcc main.c libs/argparse.c -o zenith-cli -lcurl + +echo "сборкa завершена" \ No newline at end of file diff --git a/libs/argparse.c b/libs/argparse.c new file mode 100644 index 0000000..f3bfe17 --- /dev/null +++ b/libs/argparse.c @@ -0,0 +1,395 @@ +/** + * Copyright (C) 2012-2015 Yecheng Fu + * All rights reserved. + * + * Use of this source code is governed by a MIT-style license that can be found + * in the LICENSE file. + */ +#include +#include +#include +#include +#include +#include "argparse.h" + +#define OPT_UNSET 1 +#define OPT_LONG (1 << 1) + +static const char * +prefix_skip(const char *str, const char *prefix) +{ + size_t len = strlen(prefix); + return strncmp(str, prefix, len) ? NULL : str + len; +} + +static int +prefix_cmp(const char *str, const char *prefix) +{ + for (;; str++, prefix++) + if (!*prefix) { + return 0; + } else if (*str != *prefix) { + return (unsigned char)*prefix - (unsigned char)*str; + } +} + +static void +argparse_error(struct argparse *self, const struct argparse_option *opt, + const char *reason, int flags) +{ + (void)self; + if (flags & OPT_LONG) { + fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason); + } else { + fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason); + } + exit(EXIT_FAILURE); +} + +static int +argparse_getvalue(struct argparse *self, const struct argparse_option *opt, + int flags) +{ + const char *s = NULL; + if (!opt->value) + goto skipped; + switch (opt->type) { + case ARGPARSE_OPT_BOOLEAN: + if (flags & OPT_UNSET) { + *(int *)opt->value = *(int *)opt->value - 1; + } else { + *(int *)opt->value = *(int *)opt->value + 1; + } + if (*(int *)opt->value < 0) { + *(int *)opt->value = 0; + } + break; + case ARGPARSE_OPT_BIT: + if (flags & OPT_UNSET) { + *(int *)opt->value &= ~opt->data; + } else { + *(int *)opt->value |= opt->data; + } + break; + case ARGPARSE_OPT_STRING: + if (self->optvalue) { + *(const char **)opt->value = self->optvalue; + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(const char **)opt->value = *++self->argv; + } else { + argparse_error(self, opt, "requires a value", flags); + } + break; + case ARGPARSE_OPT_INTEGER: + errno = 0; + if (self->optvalue) { + *(int *)opt->value = strtol(self->optvalue, (char **)&s, 0); + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(int *)opt->value = strtol(*++self->argv, (char **)&s, 0); + } else { + argparse_error(self, opt, "requires a value", flags); + } + if (errno == ERANGE) + argparse_error(self, opt, "numerical result out of range", flags); + if (s[0] != '\0') // no digits or contains invalid characters + argparse_error(self, opt, "expects an integer value", flags); + break; + case ARGPARSE_OPT_FLOAT: + errno = 0; + if (self->optvalue) { + *(float *)opt->value = strtof(self->optvalue, (char **)&s); + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(float *)opt->value = strtof(*++self->argv, (char **)&s); + } else { + argparse_error(self, opt, "requires a value", flags); + } + if (errno == ERANGE) + argparse_error(self, opt, "numerical result out of range", flags); + if (s[0] != '\0') // no digits or contains invalid characters + argparse_error(self, opt, "expects a numerical value", flags); + break; + default: + assert(0); + } + +skipped: + if (opt->callback) { + return opt->callback(self, opt); + } + return 0; +} + +static void +argparse_options_check(const struct argparse_option *options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + switch (options->type) { + case ARGPARSE_OPT_END: + case ARGPARSE_OPT_BOOLEAN: + case ARGPARSE_OPT_BIT: + case ARGPARSE_OPT_INTEGER: + case ARGPARSE_OPT_FLOAT: + case ARGPARSE_OPT_STRING: + case ARGPARSE_OPT_GROUP: + continue; + default: + fprintf(stderr, "wrong option type: %d", options->type); + break; + } + } +} + +static int +argparse_short_opt(struct argparse *self, const struct argparse_option *options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + if (options->short_name == *self->optvalue) { + self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL; + return argparse_getvalue(self, options, 0); + } + } + return -2; +} + +static int +argparse_long_opt(struct argparse *self, const struct argparse_option *options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + const char *rest; + int opt_flags = 0; + if (!options->long_name) + continue; + + rest = prefix_skip(self->argv[0] + 2, options->long_name); + if (!rest) { + // negation disabled? + if (options->flags & OPT_NONEG) { + continue; + } + // only OPT_BOOLEAN/OPT_BIT supports negation + if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != + ARGPARSE_OPT_BIT) { + continue; + } + + if (prefix_cmp(self->argv[0] + 2, "no-")) { + continue; + } + rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name); + if (!rest) + continue; + opt_flags |= OPT_UNSET; + } + if (*rest) { + if (*rest != '=') + continue; + self->optvalue = rest + 1; + } + return argparse_getvalue(self, options, opt_flags | OPT_LONG); + } + return -2; +} + +int +argparse_init(struct argparse *self, struct argparse_option *options, + const char *const *usages, int flags) +{ + memset(self, 0, sizeof(*self)); + self->options = options; + self->usages = usages; + self->flags = flags; + self->description = NULL; + self->epilog = NULL; + return 0; +} + +void +argparse_describe(struct argparse *self, const char *description, + const char *epilog) +{ + self->description = description; + self->epilog = epilog; +} + +int +argparse_parse(struct argparse *self, int argc, const char **argv) +{ + self->argc = argc - 1; + self->argv = argv + 1; + self->out = argv; + + argparse_options_check(self->options); + + for (; self->argc; self->argc--, self->argv++) { + const char *arg = self->argv[0]; + if (arg[0] != '-' || !arg[1]) { + if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) { + goto end; + } + // if it's not option or is a single char '-', copy verbatim + self->out[self->cpidx++] = self->argv[0]; + continue; + } + // short option + if (arg[1] != '-') { + self->optvalue = arg + 1; + switch (argparse_short_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + while (self->optvalue) { + switch (argparse_short_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + } + continue; + } + // if '--' presents + if (!arg[2]) { + self->argc--; + self->argv++; + break; + } + // long option + switch (argparse_long_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + continue; + +unknown: + fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]); + argparse_usage(self); + if (!(self->flags & ARGPARSE_IGNORE_UNKNOWN_ARGS)) { + exit(EXIT_FAILURE); + } + } + +end: + memmove(self->out + self->cpidx, self->argv, + self->argc * sizeof(*self->out)); + self->out[self->cpidx + self->argc] = NULL; + + return self->cpidx + self->argc; +} + +void +argparse_usage(struct argparse *self) +{ + if (self->usages) { + const char *const *usages = self->usages; + fprintf(stdout, "Usage: %s\n", *usages++); + while (*usages && **usages) + fprintf(stdout, " or: %s\n", *usages++); + } else { + fprintf(stdout, "Usage:\n"); + } + + // print description + if (self->description) + fprintf(stdout, "%s\n", self->description); + + fputc('\n', stdout); + + const struct argparse_option *options; + + // figure out best width + size_t usage_opts_width = 0; + size_t len; + options = self->options; + for (; options->type != ARGPARSE_OPT_END; options++) { + len = 0; + if ((options)->short_name) { + len += 2; + } + if ((options)->short_name && (options)->long_name) { + len += 2; // separator ", " + } + if ((options)->long_name) { + len += strlen((options)->long_name) + 2; + } + if (options->type == ARGPARSE_OPT_INTEGER) { + len += strlen("="); + } + if (options->type == ARGPARSE_OPT_FLOAT) { + len += strlen("="); + } else if (options->type == ARGPARSE_OPT_STRING) { + len += strlen("="); + } + len = (len + 3) - ((len + 3) & 3); + if (usage_opts_width < len) { + usage_opts_width = len; + } + } + usage_opts_width += 4; // 4 spaces prefix + + options = self->options; + for (; options->type != ARGPARSE_OPT_END; options++) { + size_t pos = 0; + size_t pad = 0; + if (options->type == ARGPARSE_OPT_GROUP) { + fputc('\n', stdout); + fprintf(stdout, "%s", options->help); + fputc('\n', stdout); + continue; + } + pos = fprintf(stdout, " "); + if (options->short_name) { + pos += fprintf(stdout, "-%c", options->short_name); + } + if (options->long_name && options->short_name) { + pos += fprintf(stdout, ", "); + } + if (options->long_name) { + pos += fprintf(stdout, "--%s", options->long_name); + } + if (options->type == ARGPARSE_OPT_INTEGER) { + pos += fprintf(stdout, "="); + } else if (options->type == ARGPARSE_OPT_FLOAT) { + pos += fprintf(stdout, "="); + } else if (options->type == ARGPARSE_OPT_STRING) { + pos += fprintf(stdout, "="); + } + if (pos <= usage_opts_width) { + pad = usage_opts_width - pos; + } else { + fputc('\n', stdout); + pad = usage_opts_width; + } + fprintf(stdout, "%*s%s\n", (int)pad + 2, "", options->help ? options->help : ""); + } + + // print epilog + if (self->epilog) + fprintf(stdout, "%s\n", self->epilog); +} + +int +argparse_help_cb_no_exit(struct argparse *self, + const struct argparse_option *option) +{ + (void)option; + argparse_usage(self); + return 0; +} + +int +argparse_help_cb(struct argparse *self, const struct argparse_option *option) +{ + argparse_help_cb_no_exit(self, option); + exit(EXIT_SUCCESS); +} + diff --git a/libs/argparse.h b/libs/argparse.h new file mode 100644 index 0000000..34bfc76 --- /dev/null +++ b/libs/argparse.h @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2012-2015 Yecheng Fu + * All rights reserved. + * + * Use of this source code is governed by a MIT-style license that can be found + * in the LICENSE file. + */ +#ifndef ARGPARSE_H +#define ARGPARSE_H + +/* For c++ compatibility */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct argparse; +struct argparse_option; + +typedef int argparse_callback (struct argparse *self, + const struct argparse_option *option); + +enum argparse_flag { + ARGPARSE_STOP_AT_NON_OPTION = 1 << 0, + ARGPARSE_IGNORE_UNKNOWN_ARGS = 1 << 1, +}; + +enum argparse_option_type { + /* special */ + ARGPARSE_OPT_END, + ARGPARSE_OPT_GROUP, + /* options with no arguments */ + ARGPARSE_OPT_BOOLEAN, + ARGPARSE_OPT_BIT, + /* options with arguments (optional or required) */ + ARGPARSE_OPT_INTEGER, + ARGPARSE_OPT_FLOAT, + ARGPARSE_OPT_STRING, +}; + +enum argparse_option_flags { + OPT_NONEG = 1, /* disable negation */ +}; + +/** + * argparse option + * + * `type`: + * holds the type of the option, you must have an ARGPARSE_OPT_END last in your + * array. + * + * `short_name`: + * the character to use as a short option name, '\0' if none. + * + * `long_name`: + * the long option name, without the leading dash, NULL if none. + * + * `value`: + * stores pointer to the value to be filled. + * + * `help`: + * the short help message associated to what the option does. + * Must never be NULL (except for ARGPARSE_OPT_END). + * + * `callback`: + * function is called when corresponding argument is parsed. + * + * `data`: + * associated data. Callbacks can use it like they want. + * + * `flags`: + * option flags. + */ +struct argparse_option { + enum argparse_option_type type; + const char short_name; + const char *long_name; + void *value; + const char *help; + argparse_callback *callback; + intptr_t data; + int flags; +}; + +/** + * argparse + */ +struct argparse { + // user supplied + const struct argparse_option *options; + const char *const *usages; + int flags; + const char *description; // a description after usage + const char *epilog; // a description at the end + // internal context + int argc; + const char **argv; + const char **out; + int cpidx; + const char *optvalue; // current option value +}; + +// built-in callbacks +int argparse_help_cb(struct argparse *self, + const struct argparse_option *option); +int argparse_help_cb_no_exit(struct argparse *self, + const struct argparse_option *option); + +// built-in option macros +#define OPT_END() { ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 } +#define OPT_BOOLEAN(...) { ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ } +#define OPT_BIT(...) { ARGPARSE_OPT_BIT, __VA_ARGS__ } +#define OPT_INTEGER(...) { ARGPARSE_OPT_INTEGER, __VA_ARGS__ } +#define OPT_FLOAT(...) { ARGPARSE_OPT_FLOAT, __VA_ARGS__ } +#define OPT_STRING(...) { ARGPARSE_OPT_STRING, __VA_ARGS__ } +#define OPT_GROUP(h) { ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 } +#define OPT_HELP() OPT_BOOLEAN('h', "help", NULL, \ + "show this help message and exit", \ + argparse_help_cb, 0, OPT_NONEG) + +int argparse_init(struct argparse *self, struct argparse_option *options, + const char *const *usages, int flags); +void argparse_describe(struct argparse *self, const char *description, + const char *epilog); +int argparse_parse(struct argparse *self, int argc, const char **argv); +void argparse_usage(struct argparse *self); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/main.c b/main.c index 5f1669b..0fe5a31 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,9 @@ #include +#include +#include -#scheme = 0 -- темная тема +#include "libs/argparse.h" +#include "curl/curl.h" struct Scheme{ char fg_color[8]; @@ -14,12 +17,76 @@ struct Scheme{ }; void write_pallete(const struct Scheme *s){ -#s->bg_color +//s->bg_color } -int main(){ +int download_wall(const char *link){ + CURL *curl; + FILE *fp; + CURLcode res; - printf("asdasd\n"); + const char *outfilename = "wallpaper.jpg"; - return 0; -} \ No newline at end of file + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if(curl) { + fp = fopen(outfilename, "wb"); + + if(fp == NULL) { + fprintf(stderr, "ошибка: не удалось создать или открыть файл %s\n", outfilename); + + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return 1; + } + + curl_easy_setopt(curl, CURLOPT_URL, link); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + + res = curl_easy_perform(curl); + + if(res != CURLE_OK) { + fprintf(stderr, "ошибка скачивания: %s\n", curl_easy_strerror(res)); + } + + fclose(fp); + + curl_easy_cleanup(curl); + } + + curl_global_cleanup(); + + return 0; +} + +int main(int argc, const char **argv) { + const char* link = NULL; + const char* scheme_output = NULL; + const char* wall_output = NULL; + int is_pastel = 0; + + struct argparse_option options[] = { + OPT_HELP(), + OPT_STRING(0,"link", &link, "ссылка на изображение с сайта wallhave.cc", NULL, 0, 0), + OPT_BOOLEAN('p', "pastel", &is_pastel, "создать пастельные палитры", NULL, 0, 0), + OPT_STRING(0,"scheme-output", &scheme_output, "директория для сохранения палитр", NULL, 0, 0), + OPT_STRING(0,"wall-output", &wall_output, "директория для сохранения обоев", NULL, 0, 0), + OPT_END(), + }; + + struct argparse argparse; + argparse_init(&argparse, options, NULL, 0); + argc = argparse_parse(&argparse, argc, argv); + + download_wall(link); + + return 0; +} +/* + +zenith-cli --link="link" -p/--pastel --scheme-output="path" --wall-output="path" + +*/ \ No newline at end of file diff --git a/zenith-cli b/zenith-cli new file mode 100755 index 0000000000000000000000000000000000000000..cdf9365aaab89469d5f60cffaa470dceb9d8465e GIT binary patch literal 29136 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