Minor favorites refactoring and blacklist skeleton.

This commit is contained in:
Martin Dvorak 2015-04-28 08:56:59 +02:00
parent 8dc27fac20
commit f82800ae5d
6 changed files with 308 additions and 8 deletions

158
DOCUMENTATION.md Normal file
View file

@ -0,0 +1,158 @@
This document is an unfinished draft.
HSTR DOCUMENTATION
==================
Table of contents:
* Installation
* Distribution
* Source code
* Ubuntu
* Debian
* Mint
* Arch
* Mac OS
* Configuration
* Keyboard shortcut
* Colors
* View
* Verbosity
* Shell specific
* Bash
* Zsh
* Features
* History views
* Ranking
* Raw
* Favorites
* History filtering
* Choosing a command
* Favorite commands
* Blacklist
* Examples
Features
--------
`hh` is typically started by pressing `Ctrl-r` after
you configure it for this shorcut for your shell. However,
you can run it as a normal program just by typing:
```bash
hh
```
It opens a page with a history view (ranking view is default).
Alternatively you can run `hh` in non-interactive mode -
commands are just listed on standard output based on history
view:
```bash
hh --non-interactive
```
Filtering pattern can be optionally specified as well:
```bash
hh -i git
```
Prints history items containing `git` to standard output and
exits.
### History filtering
When `hh` starts in interative mode, a view of commands
is shown. This list of commands can be filtered just by typing
a string pattern.
### Choosing a command
When you filtered the view of history items enough, you can
move around it with `UP` and `DOWN` arrow keys. Selected history
items is highlighted. Once you are done with your choice:
* press `ENTER` to choose the command and execute it
* or press `TAB` or `RIGHT` arrow key to choose the command and edit it on command line after exiting `hh`
* or press `LEFT` arrow key to choose the command and open it in editor (Bash `fc` i.e. fix command)
Favorite Commands
-----------------
`hh` allows you to store and manage your favorite
commands.
A new favorite command can be added from
ranking or raw history view by pressing `Ctrl-f`.
You can check your favorite commands by choosing
favorite view - rotate views using `Ctrl-/` or start
`hh` by adding `favorites` to `HH_CONFIG` environment
property. A favorite command can be choosen just
by pressing `ENTER` when on command in favorite view.
Last chosen favorite commands appears as the first
one (at the top of the page) in the favorite view.
You can delete a favorite command with `DEL` key.
Tips:
* Favorite commands are stored in `~/.hh_favorites`
* Suffix your favorite commands with comments
describing their purpose. For example
`printf "\e[?2004l" # fix terminal copy/paste`
Such comment can be used for normal commands
as well and may serve as a way how to **tag**
commands.
Blacklist
---------
`hh` allows you to specify a set of commands to be
skipped from all the views. Blacklist typically contains
frequently used commands whose completion from history
has a little or no value. The default blacklist looks
like this:
```bash
pwd
cd
cd ..
ls
hh
mc
```
Tips:
* Blacklist of commands is stored in `~/.hh_blacklist`
If the file doesn't exist, you may create it and complete
it with your own blacklist.
* You can skip any command from history just by
prefixing it with `SPACE`. For example:
` echo "Skip this from history"` It's a Bash
option that is configured using
`HISTCONTROL=ignorespace` environment variable.
Examples
--------
Get more colors when running `hh`:
```bash
export HH_CONFIG=hicolor
```
Start `hh` in configured view and filter out history items
containing 'git':
```bash
hh git
```
Print history items containing 'git' to standard output and exit:
```bash
hh --non-interactive git
```
Append default `hh` configuration to your Bash profile:
```bash
hh --show-configuration >> ~/.bashrc
```
Check `hh` man page:
```bash
man hh
```

View file

@ -869,6 +869,7 @@ void loop_to_select(Hstr *hstr)
deletedOccurences=remove_from_history_model(msg, hstr);
result=hstr_print_selection(maxHistoryItems, pattern, hstr);
print_cmd_deleted_label(msg, deletedOccurences, hstr);
free(msg);
move(y, basex+strlen(pattern));
printDefaultLabel=TRUE;
print_history_label(hstr);

104
src/hstr_blacklist.c Normal file
View file

@ -0,0 +1,104 @@
/*
============================================================================
Name : hstr_blacklist.c
Author : martin.dvorak@midforger.com
Copyright : Apache 2.0
Description : Commands to be skipped from history.
============================================================================
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "include/hstr_blacklist.h"
static const char *implicitCommandBlacklist[] = {
"ls", "pwd", "cd", "cd ..", "hh", "mc",
"ls ", "pwd ", "cd ", "cd .. ", "hh ", "mc "
};
void blacklist_init(Blacklist *blacklist)
{
blacklist->loaded=false;
blacklist->implicit=false;
blacklist->set=malloc(sizeof(HashSet));
hashset_init(blacklist->set);
}
char* blacklist_get_filename()
{
char *home = getenv(ENV_VAR_HOME);
char *fileName = (char*) malloc(strlen(home) + 1 + strlen(FILE_HH_BLACKLIST) + 1);
strcpy(fileName, home);
strcat(fileName, "/");
strcat(fileName, FILE_HH_BLACKLIST);
return fileName;
}
void blacklist_get(Blacklist *blacklist)
{
if(!blacklist->loaded) {
char* fileName = favorites_get_filename();
char *file_contents=NULL;
if(access(fileName, F_OK) != -1) {
long input_file_size;
FILE *input_file = fopen(fileName, "rb");
fseek(input_file, 0, SEEK_END);
input_file_size = ftell(input_file);
rewind(input_file);
file_contents = malloc((input_file_size + 1) * (sizeof(char)));
if(fread(file_contents, sizeof(char), input_file_size, input_file)==-1) {
exit(EXIT_FAILURE);
}
fclose(input_file);
file_contents[input_file_size] = 0;
if(file_contents && strlen(file_contents)) {
char *p=strchr(file_contents,'\n');
while (p!=NULL) {
p=strchr(p+1,'\n');
}
char *pb=file_contents, *pe, *s;
pe=strchr(file_contents, '\n');
while(pe!=NULL) {
*pe=0;
if(!hashset_contains(blacklist->set,pb)) {
s=hstr_strdup(pb);
hashset_add(blacklist->set,s);
}
pb=pe+1;
pe=strchr(pb, '\n');
}
free(file_contents);
}
} else {
// blacklist not found - use default one (flushed on exit)
blacklist->loaded=true;
blacklist->implicit=true;
int i, length=sizeof(implicitCommandBlacklist)/sizeof(implicitCommandBlacklist[0]);
for(i=0; i<length; i++) {
hashset_add(blacklist->set, implicitCommandBlacklist[i]);
}
}
free(fileName);
}
}
bool blacklist_in(Blacklist *blacklist, char *cmd)
{
return hashset_contains(blacklist->set, cmd);
}
void blacklist_destroy(Blacklist *blacklist)
{
if(blacklist) {
if(blacklist->implicit) {
// TODO save blacklist to file if implicit
}
hashset_destroy(blacklist->set, false);
free(blacklist->set);
free(blacklist);
}
}

View file

@ -22,6 +22,7 @@ void favorites_init(FavoriteItems *favorites)
favorites->count=0;
favorites->loaded=false;
favorites->set=malloc(sizeof(HashSet));
hashset_init(favorites->set);
}
void favorites_show(FavoriteItems *favorites)
@ -39,10 +40,10 @@ void favorites_show(FavoriteItems *favorites)
char* favorites_get_filename()
{
char *home = getenv(ENV_VAR_HOME);
char *fileName = (char*) malloc(strlen(home) + 1 + strlen(FILE_HH_RC) + 1);
char *fileName = (char*) malloc(strlen(home) + 1 + strlen(FILE_HH_FAVORITES) + 1);
strcpy(fileName, home);
strcat(fileName, "/");
strcat(fileName, FILE_HH_RC);
strcat(fileName, FILE_HH_FAVORITES);
return fileName;
}
@ -74,17 +75,15 @@ void favorites_get(FavoriteItems *favorites)
}
favorites->items = malloc(sizeof(char*) * favorites->count);
favorites->count=0;
favorites->count = 0;
char *pb=file_contents, *pe, *s;
pe=strchr(file_contents, '\n');
HashSet set;
hashset_init(&set);
while(pe!=NULL) {
*pe=0;
if(!hashset_contains(&set,pb)) {
if(!hashset_contains(favorites->set,pb)) {
s=hstr_strdup(pb);
favorites->items[favorites->count++]=s;
hashset_add(&set,s);
hashset_add(favorites->set,s);
}
pb=pe+1;
pe=strchr(pb, '\n');
@ -139,6 +138,7 @@ void favorites_add(FavoriteItems *favorites, char *newFavorite)
}
favorites_save(favorites);
hashset_add(favorites->set, newFavorite);
}
void favorites_choose(FavoriteItems *favorites, char *choice)
@ -178,6 +178,7 @@ bool favorites_remove(FavoriteItems *favorites, char *almostDead)
}
}
favorites_save(favorites);
// kept in set and removed/freed on favs destroy
return true;
} else {
return false;
@ -187,11 +188,14 @@ bool favorites_remove(FavoriteItems *favorites, char *almostDead)
void favorites_destroy(FavoriteItems *favorites)
{
if(favorites) {
// TODO hashset destroys keys - no need to destroy items!
int i;
for(i=0; i<favorites->count; i++) {
free(favorites->items[i]);
}
// TODO hashset destroys keys - no need to destroy items!
hashset_destroy(favorites->set, false);
free(favorites->set);
free(favorites);
}
}

View file

@ -0,0 +1,33 @@
/*
============================================================================
Name : hstr_blacklist.h
Author : martin.dvorak@midforger.com
Copyright : Apache 2.0
Description : Commands to be skipped from history.
============================================================================
*/
#ifndef HSTR_BLACKLIST_H_
#define HSTR_BLACKLIST_H_
#include <stdlib.h>
#include <stdbool.h>
#include "hashset.h"
#define ENV_VAR_USER "USER"
#define ENV_VAR_HOME "HOME"
#define FILE_HH_BLACKLIST ".hh_blacklist"
typedef struct {
bool loaded;
bool implicit;
HashSet *set;
} Blacklist;
void blacklist_init(Blacklist *blacklist);
void blacklist_get(Blacklist *blacklist);
bool blacklist_in(Blacklist *blacklist, char *cmd);
void blacklist_destroy(Blacklist *blacklist);
#endif

View file

@ -17,7 +17,7 @@
#define ENV_VAR_USER "USER"
#define ENV_VAR_HOME "HOME"
#define FILE_HH_RC ".hh_favorites"
#define FILE_HH_FAVORITES ".hh_favorites"
typedef struct {
char **items;