summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgramanas <anastasis.gramm2@gmail.com>2019-03-20 19:34:39 +0200
committergramanas <anastasis.gramm2@gmail.com>2019-03-20 19:34:39 +0200
commit90dc7b2d2f19944b5be9b19175db14a7ece35c99 (patch)
tree61fdd1eef6528d14eddb260fbc3926bb96674d8c
parent896c4369bb9cd38aa828516f084df54e35f1371e (diff)
downloadfcomp-90dc7b2d2f19944b5be9b19175db14a7ece35c99.tar.gz
fcomp-90dc7b2d2f19944b5be9b19175db14a7ece35c99.tar.bz2
fcomp-90dc7b2d2f19944b5be9b19175db14a7ece35c99.zip
Add uniq flag for print_all and emacs frontend
-rw-r--r--fcomp.c234
-rw-r--r--fcomp.el108
2 files changed, 237 insertions, 105 deletions
diff --git a/fcomp.c b/fcomp.c
index 33944eb..a466283 100644
--- a/fcomp.c
+++ b/fcomp.c
@@ -75,8 +75,9 @@ typedef struct config {
int lisp_print; /** 0: off 1: on */
int print_count; /** 0: off 1: on */
int print_all; /** 0: off 1: on */
+ int all_uniq; /** 0: off 1: on */
int interactive; /** 0: off 1: on */
- int prompt; /** 0: off 1: on */
+ int prompt; /** 0: off 1: on */
int filestream; /** 0: off 1: on */
char *file;
char *query;
@@ -92,26 +93,27 @@ typedef struct config {
/**
* Initial config vector */
static config cfg = {
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- NULL,
- NULL,
- 3,
- 0,
- NULL,
- 0,
- NULL,
- starts,
- 1000
+ .help = 0,
+ .debug = 0,
+ .stats = 0,
+ .stdin = 1,
+ .reverse_sort = 0,
+ .lisp_print = 0,
+ .print_count = 0,
+ .print_all = 0,
+ .all_uniq = 0,
+ .interactive = 0,
+ .prompt = 1,
+ .filestream = 0,
+ .file = NULL,
+ .query = NULL,
+ .min_word_size = 3,
+ .evc = 0,
+ .extra_valid_chars = NULL,
+ .eic = 0,
+ .extra_invalid_chars = NULL,
+ .search_method = starts,
+ .max_token_size = 1000
};
static void print_help(char *argv0)
@@ -147,6 +149,8 @@ static void print_help(char *argv0)
"Print the count of each matched token");
fprintf(stderr, "%8s %4s %15s %50s\n", "-l", "", "lisp",
"Print matched tokens in a lisp list");
+ fprintf(stderr, "%8s %4s %15s %50s\n\n", "-u", "", "unique",
+ "When -a is passed, don't print duplicates");
fprintf(stderr, "%8s %4s %15s %50s\n", "-a", "", "all",
"Print all tokens of input");
fprintf(stderr, "%8s %4s %15s %50s\n\n", "", "", "",
@@ -191,6 +195,7 @@ static void print_cfg()
fprintf(stderr, "[-l:%4s]\n", cfg.lisp_print ? "on" : "off");
fprintf(stderr, " [-c:%4s] ", cfg.print_count ? "on" : "off");
fprintf(stderr, "[-a:%4s] ", cfg.print_all ? "on" : "off");
+ fprintf(stderr, "[-u:%4s] ", cfg.all_uniq ? "on" : "off");
fprintf(stderr, "[-v:%4s] ", cfg.evc ? "on" : "off");
fprintf(stderr, "[-i:%4s]\n", cfg.eic ? "on" : "off");
}
@@ -218,18 +223,18 @@ static int parse_cli(int argc, char *argv[])
if (argc < 2)
return -1;
char c;
- while ((c = getopt(argc, argv, "-hIF:xzsadclrf:i:v:w:t:")) != -1) {
+ while ((c = getopt(argc, argv, "-hIF:xzsaudclrf:i:v:w:t:")) != -1) {
switch (c) {
case 'I':
- if (cfg.interactive) {
- cfg.prompt = 0;
- }
+ if (cfg.interactive) {
+ cfg.prompt = 0;
+ }
cfg.interactive = 1;
break;
case 'F':
cfg.stdin = 0;
- cfg.filestream = 1;
- cfg.file = optarg;
+ cfg.filestream = 1;
+ cfg.file = optarg;
break;
case 'h':
cfg.help = 1;
@@ -237,6 +242,9 @@ static int parse_cli(int argc, char *argv[])
case 'd':
cfg.debug = 1;
break;
+ case 'u':
+ cfg.all_uniq = 1;
+ break;
case 's':
cfg.stats = 1;
break;
@@ -608,7 +616,7 @@ static int tokenize(FILE * f, slist * l)
while ((c = fgetc(f)) != EOF) {
if (!is_valid(c)) {
- st.discarded++;
+ st.discarded++;
if (tmp) {
finalize_str(tmp, n, l);
free(tmp);
@@ -647,10 +655,9 @@ static void get_slist_stats(slist * l)
{
if (l->n > 0) {
char tmp[] = "Total tokens:";
- st.tok_results =
- (char *)
+ st.tok_results = (char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", l->n) +
- 3) * sizeof(char));
+ 4) * sizeof(char));
sprintf(st.tok_results, "%s\t\t%d\n", tmp, l->n);
}
}
@@ -659,10 +666,9 @@ static void get_search_stats(slist * l)
{
if (l->n > 0) {
char tmp[] = "Total matches:";
- st.search_results =
- (char *)
+ st.search_results = (char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", l->n) +
- 3) * sizeof(char));
+ 4) * sizeof(char));
sprintf(st.search_results, "%s\t\t%d\n", tmp, l->n);
}
}
@@ -670,35 +676,35 @@ static void get_search_stats(slist * l)
static void get_result_stats(result * r)
{
if (r->n > 0) {
- char tmp[] = "Unique matches:";
- st.unique_results =
- (char *)
+ char tmp[] = "Unique tokens:";
+ st.unique_results = (char *)
malloc((strlen(tmp) + snprintf(NULL, 0, "%d", r->n) +
- 3) * sizeof(char));
+ 4) * sizeof(char));
sprintf(st.unique_results, "%s\t\t%d\n", tmp, r->n);
}
}
void clean_stdin(void)
{
- int c;
- do {
- c = getchar();
- } while (c != '\n' && c != EOF);
+ int c;
+ do {
+ c = getchar();
+ } while (c != '\n' && c != EOF);
}
-static void prompt(slist *l)
+static void prompt(slist * l)
{
int r = 0;
char p[20] = "";
char *tmp = NULL;
- if (cfg.prompt) sprintf(p, "[%d]> ", r);
+ if (cfg.prompt)
+ sprintf(p, "[%d]> ", r);
fflush(NULL);
- while((tmp = linenoise(p)) != NULL) {
- slist search_res = { 0 };
- if (search(l, tmp, &search_res)) {
- result count_res = { 0 };
- /* sort the results */
+ while ((tmp = linenoise(p)) != NULL) {
+ slist search_res = { 0 };
+ if (search(l, tmp, &search_res)) {
+ result count_res = { 0 };
+ /* sort the results */
qsort(&search_res.s[0], search_res.n, sizeof(char *),
cmpstringp);
@@ -706,27 +712,65 @@ static void prompt(slist *l)
count(&search_res, &count_res);
sort_by_count(&count_res);
- r = count_res.n;
+ r = count_res.n;
/* print them */
pc(&count_res);
cfree(&count_res);
- }
- if (cfg.prompt) sprintf(p, "[%d]> ", r);
- r = 0;
- free(search_res.s);
- free(tmp);
- tmp = NULL;
+ }
+ if (cfg.prompt)
+ sprintf(p, "[%d]> ", r);
+ r = 0;
+ free(search_res.s);
+ free(tmp);
+ tmp = NULL;
+ }
+ if (tmp)
+ free(tmp);
+}
+
+static int set_input(FILE **f)
+{
+ if (cfg.stdin) {
+ if (cfg.interactive) {
+ fprintf(stderr,
+ "Can't read from stdin in interactive mode.\n");
+ return -1;
+ }
+ *f = stdin;
+ } else if (cfg.filestream) {
+ *f = fmemopen(cfg.file, strlen(cfg.file), "r");
+ } else {
+ *f = fopen(cfg.file, "r");
+ if (!f) {
+ fprintf(stderr, "Couldn't open %s\n", cfg.file);
+ return -1;
+ }
}
- if (tmp) free(tmp);
+ return 0;
+}
+
+static void get_uniq(slist * l, result *r)
+{
+ /* sort the results */
+ qsort(&l->s[0], l->n, sizeof(char *),
+ cmpstringp);
+
+ /* count the unique, put it in result */
+ count(l, r);
+ sort_by_count(r);
+
+ if (cfg.stats)
+ get_result_stats(r);
}
int main(int argc, char *argv[])
{
int rc = 0;
FILE *f;
- slist list = { 0 };
- slist search_res = { 0 };
+ slist token_list = { 0 };
+ slist ref_list = { 0 };
+ slist *listp = NULL;
result count_res = { 0 };
if (parse_cli(argc, argv)
@@ -742,71 +786,51 @@ int main(int argc, char *argv[])
return -1;
}
- /* set input */
- if (cfg.stdin) {
- if (cfg.interactive) {
- fprintf(stderr, "Can't read from stdin in interactive mode.\n");
- return -1;
- }
- f = stdin;
- } else if (cfg.filestream) {
- f = fmemopen(cfg.file, strlen(cfg.file), "r");
- } else {
- f = fopen(cfg.file, "r");
- if (!f) {
- fprintf(stderr, "Couldn't open %s\n", cfg.file);
- return -1;
- }
- }
- /* tokenize */
- if (tokenize(f, &list)) {
- rc = -1;
+ if ((rc = set_input(&f)))
+ goto done;
+
+ if ((rc = tokenize(f, &token_list)))
goto done;
- }
if (cfg.stats)
- get_slist_stats(&list);
+ get_slist_stats(&token_list);
if (cfg.interactive) {
- prompt(&list);
- goto done;
+ prompt(&token_list);
+ goto done;
}
if (cfg.print_all) {
- pp(&list);
+ if (cfg.all_uniq)
+ listp = &token_list;
+ else
+ pp(&token_list);
} else {
/* search for the query */
- if (search(&list, cfg.query, &search_res)) {
-
- if (cfg.stats)
- get_search_stats(&search_res);
-
- /* sort the results */
- qsort(&search_res.s[0], search_res.n, sizeof(char *),
- cmpstringp);
-
- /* count the unique */
- count(&search_res, &count_res);
- sort_by_count(&count_res);
+ if (search(&token_list, cfg.query, &ref_list)) {
+ listp = &ref_list;
+ if (cfg.stats)
+ get_search_stats(&ref_list);
+ }
+ }
- if (cfg.stats)
- get_result_stats(&count_res);
+ if (listp) {
+ get_uniq(listp, &count_res);
+ pc(&count_res);
+ cfree(&count_res);
- /* print them */
- pc(&count_res);
-
- cfree(&count_res);
- free(search_res.s);
- }
+ if (listp == &ref_list)
+ free(ref_list.s);
}
+
if (cfg.debug)
print_cfg();
if (cfg.stats)
print_stats();
-done:
- sfree(&list);
+ done:
+ sfree(&token_list);
fclose(f);
return rc;
}
diff --git a/fcomp.el b/fcomp.el
new file mode 100644
index 0000000..4e046d9
--- /dev/null
+++ b/fcomp.el
@@ -0,0 +1,108 @@
+;;; fcomp.el --- fcomp front-end -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019 Anastasis Grammenos
+
+;; Author: Anastasis Grammenos <anastasis.gramm2@gmail.com>
+;; Keywords: lisp
+;; Version: 0.0.1
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU 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 General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Emacs front-end for fcomp. Get if from https://ubuntos.dynu.net/git/fcomp
+
+;;; Install:
+
+;; git clone https://ubuntos.dynu.net/git/fcomp && cd fcomp
+;; make && sudo ln -s fcomp /usr/local/bin/fcomp # or mv
+
+;; In the emacs init file:
+;; (add-to-list 'load-path "/your/custom/path")
+;; (require 'fcomp)
+;; (setq fcomp-path "/your/custom/path/fcomp")
+;; (global-set-key (kbd "M-i") 'fcomp-autocomplete)
+
+;; or with use-package
+;; (use-package fcomp
+;; :load-path "/your/custom/path"
+;; :bind (("M-i" . fcomp-autocomplete))
+;; :config
+;; (setq fcomp-path "/your/custom/path/fcomp"))
+
+
+;;; Code:
+
+(require 'ido)
+(require 'subr-x)
+
+(defvar fcomp-path "/usr/local/bin/fcomp")
+(defvar fcomp-min-word-length 3)
+(defvar fcomp-extra-valid-chars "")
+(defvar fcomp-extra-invalid-chars "")
+
+(defun pr ()
+ (message "Status: %s" (process-status "fcomp")))
+
+;; (thing-at-point 'word 'no-properties)
+(defun fcomp-filter (proc str)
+ (let* ((fcomp-pre
+ (if (null (process-get proc 'input-word))
+ nil
+ (format "%s" (process-get proc 'input-word)))))
+ ;; (enable-recursive-minibuffers t))
+ ;; (setq result (substring result (* -1 (- (length result) (length word))) nil))
+ (progn
+ (pr)
+ (setq result
+ (ido-completing-read
+ "Complete:"
+ (remove "" (split-string str "\n"))
+ nil nil
+ fcomp-pre))
+ (if (null result)
+ nil
+ (insert
+ (string-remove-prefix
+ (if (null fcomp-pre)
+ (format "%s" "")
+ (format "%s" fcomp-pre))
+ result))))))
+
+(defun fcomp-autocomplete ()
+ (interactive)
+ (fcomp--autocomplete (thing-at-point 'word 'no-properties)))
+
+(defun fcomp--autocomplete (word)
+ "Do stuff and ac"
+ (let ((term (if (null word)
+ (format "%s" "-au")
+ (format "%s" word)))
+ (input (buffer-substring-no-properties (point-min) (point-max))))
+ (with-temp-buffer
+ (set-process-filter
+ (start-process
+ "fcomp"
+ nil
+ fcomp-path
+ "-w" (format "%s" fcomp-min-word-length)
+ "-F" input
+ "-v" (format "%s" fcomp-extra-valid-chars)
+ "-i" (format "%s" fcomp-extra-invalid-chars)
+ term)
+ #'fcomp-filter)
+ (process-put (get-process "fcomp") 'input-word word))))
+
+(provide 'fcomp)
+;;; fcomp.el ends here