Skip to content

Commit

Permalink
Language autoselect and sudo installs
Browse files Browse the repository at this point in the history
Lingwi now supports autoselected language at the start (will consider making it available as a flag for --source-language). Target language now by default uses the system's default language. Lastly, you can build and install the project locally or in the /usr/bin by using shell scripts or Makefile with sudo privileges.
  • Loading branch information
itsYakub committed Jan 1, 2025
1 parent e756d9e commit 04d0e91
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 52 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf

# Vim files
*.swp
*.swo
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ FetchContent_MakeAvailable(libcurl)

project(
lingwi
VERSION 1.1
VERSION 1.2
DESCRIPTION "Translation command-line utility for linux"
HOMEPAGE_URL "https://github.com/itsYakub/lingw"
LANGUAGES C
Expand Down
6 changes: 5 additions & 1 deletion INSTALL.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#!/bin/bash

cp ./lingwi ~/.local/bin
if [ $(id -u) -ne 0 ]; then
cp ./lingwi $HOME/.local/bin
else
cp ./lingwi /usr/bin
fi
15 changes: 12 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ all: build install clean
build:
$(CC) $(CFLAGS) $(SRC) -o $(TARGET) $(LIBS)

install:
cp $(TARGET) ~/.local/bin
install: $(TARGET)
ifneq ($(shell id -u), 0)
cp $(TARGET) ~/.local/bin
else
cp $(TARGET) /usr/bin
endif


rebuild: clean build

Expand All @@ -24,4 +29,8 @@ clean:
rm $(TARGET)

remove:
rm ~/.local/bin/$(TARGET)
ifneq ($(shell id -u), 0)
rm -f ~/.local/bin/$(TARGET)
else
rm -f /usr/bin/$(TARGET)
endif
7 changes: 7 additions & 0 deletions REMOVE.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

if [ $(id -u) -ne 0 ]; then
rm -f $HOME/.local/bin/lingwi
else
rm -f /usr/bin/lingwi
fi
107 changes: 60 additions & 47 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
#include <curl/curl.h>

// SECTION: Macro definitions
#define LINGWI_VERSION "1.1"
#define LINGWI_VERSION "1.2"
#define LINGWI_IO_SIZE 5001
#define LINGWI_LANGCODE_SIZE 9
#define LINGWI_APINAME_SIZE 9
#define LINGWI_URL_SIZE (LINGWI_IO_SIZE + 128)
#define LINGWI_DATA_SIZE (LINGWI_IO_SIZE + LINGWI_LANGCODE_SIZE + 13)
#define LINGWI_ISO639_1_LANGCODE_COUNT 184
#define LINGWI_TRANSLATION_ENGINES_COUNT 1

Expand All @@ -32,6 +35,7 @@
size_t callback(char* ptr, size_t size, size_t nmemb, char* data);

// SECTION: Function: Program arguments
char *get_system_language(char lang[8]);
int process_options(int ac, char** av, char* sl, char* tl, char* engine, char* apikey, char* text);

// SECTION: Function: Translation
Expand Down Expand Up @@ -101,32 +105,39 @@ int main(int ac, char** av) {
char input[LINGWI_IO_SIZE] = { 0 };
char output[LINGWI_IO_SIZE] = { 0 };

char sl[8] = "en";
char tl[8] = "en";
char engine[8] = "google";
char sl[LINGWI_LANGCODE_SIZE] = "auto";
char tl[LINGWI_LANGCODE_SIZE];
char engine[LINGWI_APINAME_SIZE] = "google";
char apikey[128];

get_system_language(tl);
process_options(ac, av, sl, tl, engine, apikey, input);
translate(engine, apikey, output, input, sl, tl);

print(output);

return EXIT_SUCCESS;
return (EXIT_SUCCESS);
}

size_t callback(char* ptr, size_t size, size_t nmemb, char* data) {
size_t bytes = size * nmemb;

strcpy(data, ptr);

return bytes;
return (bytes);
}

char *get_system_language(char lang[8]) {
char *envlang = getenv("LANG");

return (strncpy(lang, envlang, strchr(envlang, '_') - envlang));
}

int process_options(int ac, char** av, char* sl, char* tl, char* engine, char* apikey, char* text) {
// Processing program options
char opt;
while((opt = getopt_long(ac, av, ":s:t:e:a:vVhl", long_option_s, NULL)) != -1) {
switch(opt) {
while ((opt = getopt_long(ac, av, ":s:t:e:a:vVhl", long_option_s, NULL)) != -1) {
switch (opt) {
case 's': {
if(!lang_valid(optarg)) {
fprintf(stderr, "[ ERR ] Invalid language code: %s\n", optarg);
Expand Down Expand Up @@ -160,8 +171,8 @@ int process_options(int ac, char** av, char* sl, char* tl, char* engine, char* a

case 'h':
fprintf(stdout, "\033[1mlingwi\033[0m - translation command-line utility\n");
fprintf(stdout, " \033[1m-s\033[0m, \033[1m--source-language\033[0m select a source language (translation from...) (DEFAULT: en)\n");
fprintf(stdout, " \033[1m-t\033[0m, \033[1m--target-language\033[0m select a target language (translation to...) (DEFAULT: en)\n");
fprintf(stdout, " \033[1m-s\033[0m, \033[1m--source-language\033[0m select a source language (translation from...) (DEFAULT: auto)\n");
fprintf(stdout, " \033[1m-t\033[0m, \033[1m--target-language\033[0m select a target language (translation to...) (DEFAULT: {system language (check 'env')})\n");
fprintf(stdout, " \033[1m-e\033[0m, \033[1m--engine\033[0m select a translation engine (DEFAULT: google)\n");
fprintf(stdout, " \033[1m-a\033[0m, \033[1m--api-key\033[0m select an api key (DEFAULT: none)\n");
fprintf(stdout, " \033[1m-v\033[0m, \033[1m--version\033[0m display a version (%s)\n", LINGWI_VERSION);
Expand Down Expand Up @@ -191,17 +202,17 @@ int process_options(int ac, char** av, char* sl, char* tl, char* engine, char* a
// Processing program inputs
char str[LINGWI_IO_SIZE];
int is_str_processed = 0;
for(int i = optind; i < ac; i++) {
for (int i = optind; i < ac; i++) {
strcpy(str, av[i]);
is_str_processed = 1;
}

// There was no input string provided
// Thus we can check if input wasn't actually piped to the program
if(!is_str_processed) {
if(!isatty(fileno(stdin))) {
if (!is_str_processed) {
if (!isatty(fileno(stdin))) {
int i = 0;
while((text[i++] = getchar()) != -1);
while ((text[i++] = getchar()) != -1);
text[i - 1] = 0;
}

Expand All @@ -214,58 +225,59 @@ int process_options(int ac, char** av, char* sl, char* tl, char* engine, char* a
else {
// If the input string is a file name ...
// Treat the input as a file name, thus the final input will be the content of this file
if(fexist(str)) {
if (fexist(str)) {
FILE* f = fopen(str, "rb");
if(!f) {
if (!f) {
fprintf(stderr, "Invalid file");
exit(EXIT_FAILURE);
}

fread(text, sizeof(char), LINGWI_IO_SIZE, f);
fclose(f);

if(text == NULL || *text == 0) {
if (text == NULL || *text == 0) {
fprintf(stderr, "[ ERR ] Empty file input\n");
exit(EXIT_FAILURE);
}

} else { // Otherwise the input is a string, thus we just copy the 'str' to 'text'
strcpy(text, str);

if(*text == 0 || text == NULL) {
if (*text == 0 || text == NULL) {
fprintf(stderr, "[ ERR ] Invalid text input\n");
exit(EXIT_FAILURE);
}
}
}
return 1;
return (1);
}

int translate(char* engine, char* apikey, char* dest, char* src, char* sl, char* tl) {
if(strcmp(engine, TRANSLATION_ENGINES[0]) == 0) { // Engine: google
if (strcmp(engine, TRANSLATION_ENGINES[0]) == 0) { // Engine: google
(void) apikey;
translate_engine_google(dest, src, sl, tl);
} else {
fprintf(stderr, "[ ERR ] Invalid engine\n");
}

return 1;
return (1);
}

int translate_engine_google(char* dest, char* src, char* sl, char* tl) {
// Setup
CURL* curl;
CURLcode ccode;
CURLcode ccode;
char cinput[LINGWI_DATA_SIZE];

curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(!curl) {
if (!curl) {
fprintf(stderr, "[ ERR ] Could not initialize cURL\n");
exit(EXIT_FAILURE);
}

char* text = curl_easy_escape(curl, src, 0);
if(!text) {
if (!text) {
fprintf(stderr, "[ ERR ] Modified translation string is invalid\n");

curl_easy_cleanup(curl);
Expand All @@ -284,79 +296,80 @@ int translate_engine_google(char* dest, char* src, char* sl, char* tl) {

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, dest);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, cinput);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

// Translation
ccode = curl_easy_perform(curl);

if(ccode != CURLE_OK) {
if (ccode != CURLE_OK) {
fprintf(stderr, "[ ERR ] %s\n", curl_easy_strerror(ccode));

curl_easy_cleanup(curl);
curl_free(text);
exit(EXIT_FAILURE);
}

curl_easy_cleanup(curl);
curl_free(text);

// Parsing
sscanf(dest, "[\"%5000[^\"]", dest);
if(!dest) {
if (!sscanf(cinput, "[[\"%5000[^\"]\", \"%8[a-z]\"]]", dest, tl) || !dest) {
fprintf(stderr, "[ ERR ] Parsing failed\n");
exit(EXIT_FAILURE);
}

return 1;
return (1);
}

int lang_valid(char* lang) {
for(int i = 0; i < LINGWI_ISO639_1_LANGCODE_COUNT; i++) {
if(strcmp(lang, ISO_639_1_LANGUAGE_CODES[i]) == 0)
return 1;
for (int i = 0; i < LINGWI_ISO639_1_LANGCODE_COUNT; i++) {
if (strcmp(lang, ISO_639_1_LANGUAGE_CODES[i]) == 0)
return (1);
}

return 0;
return (0);
}

int engine_valid(char* engine) {
for(int i = 0; i < LINGWI_TRANSLATION_ENGINES_COUNT; i++) {
if(strcmp(engine, TRANSLATION_ENGINES[i]) == 0)
return 1;
for (int i = 0; i < LINGWI_TRANSLATION_ENGINES_COUNT; i++) {
if (strcmp(engine, TRANSLATION_ENGINES[i]) == 0)
return (1);
}

return 0;
return (0);
}

int fexist(char* fpath) {
if(access(fpath, F_OK) == 0)
return 1;
return 0;
if (access(fpath, F_OK) == 0)
return (1);
return (0);
}

int print(char* str) {
int i;
for(i = 0; i < (int) strlen(str); i++) {
if(str[i] == '\\' && str[i + 1] == 'n') {
for (i = 0; i < (int) strlen(str); i++) {
if (str[i] == '\\' && str[i + 1] == 'n') {
fputc('\n', stdout);
i++;

continue;
continue ;
}

else if(str[i] == '\\' && str[i] == '\\' && str[i + 2] == 'n') {
else if (str[i] == '\\' && str[i] == '\\' && str[i + 2] == 'n') {
fputc('\n', stdout);
i += 2;

continue;
continue ;
}

fputc(str[i], stdout);
}

if(str[i - 2] != '\\' && str[i - 1] != 'n')
if (str[i - 2] != '\\' && str[i - 1] != 'n')
fputc('\n', stdout);

return 1;
return (1);
}

// + ------------------------------------------------------------------------------ +
Expand Down

0 comments on commit 04d0e91

Please sign in to comment.