Merge branch 'master' of gitlab.com:rexy712/roflcat

This commit is contained in:
Rexy712 2019-05-13 18:44:10 -07:00
commit ece4b9668d
11 changed files with 73 additions and 107 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ temp
*.d *.d
tester tester
roflcat roflcat
build

24
CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
include(CMakeDependentOption)
cmake_minimum_required(VERSION 3.1)
project(roflcat)
#c++17 without compiler extensions
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Curses REQUIRED)
find_library(TINFO_LIBRARY tinfo)
if(NOT TINFO_LIBRARY)
set(TINFO_LIBRARY "")
endif()
set(INCLUDE_PATH ${CMAKE_SOURCE_DIR}/include)
add_executable (roflcat src/roflcat.cpp src/cmd.cpp)
target_include_directories(roflcat PUBLIC ${INCLUDE_PATH})
target_include_directories(roflcat PUBLIC ${CURSES_INCLUDE_DIRS} ${TINFO_INCLUDE_DIRS})
target_link_libraries(roflcat PRIVATE ${CURSES_LIBRARIES} ${TINFO_LIBRARY})
install(TARGETS roflcat RUNTIME DESTINATION bin)
#uninstall target
add_custom_target(uninstall cat install_manifest.txt | xargs rm)

View File

@ -31,12 +31,16 @@
template<int I> template<int I>
constexpr basic_color_printer<I>::basic_color_printer(const cmd_args& args)noexcept: constexpr basic_color_printer<I>::basic_color_printer(const cmd_args& args)noexcept:
color_printer_base<basic_color_printer<I>>(args), color_printer_base<basic_color_printer<I>>(args, args.invert ? L"\033[38;5;0m\033[48;5;%sm" : L"\033[38;5;%sm"),
m_randomness(rand()%color_lookup_len){} m_randomness(rand()%color_lookup_len){}
template<int I> template<int I>
basic_color_printer<I>& basic_color_printer<I>::_print(const wchar_t s)noexcept{ basic_color_printer<I>& basic_color_printer<I>::_print(const wchar_t s)noexcept{
if(s == L'\n'){ if(s == L'\n'){
inc_line(); inc_line();
if(this->m_invert)
this->reset();
putwchar(L'\n');
return *this;
}else{ }else{
int width = wcwidth(s); int width = wcwidth(s);
if(width > 0) if(width > 0)
@ -49,7 +53,7 @@ basic_color_printer<I>& basic_color_printer<I>::_print(const wchar_t s)noexcept{
new_index += color_lookup_len; new_index += color_lookup_len;
if(new_index != m_index){ if(new_index != m_index){
m_index = new_index; m_index = new_index;
wprintf(L"\033[38;5;%sm", color_lookup_table[m_index]); wprintf(this->m_color_str, color_lookup_table[m_index]);
} }
putwchar(s); putwchar(s);
return *this; return *this;

View File

@ -45,11 +45,12 @@ struct cmd_args{
std::vector<const char*> filenames; std::vector<const char*> filenames;
//lolcat options //lolcat options
long seed = 0;
float freq = 0.2f; float freq = 0.2f;
float spread = 0.3f; float spread = 0.3f;
long seed = 0;
unsigned truecol:1; unsigned truecol:1;
unsigned color:2; unsigned color:2;
unsigned invert:1;
//GNU cat options //GNU cat options
unsigned number:2; unsigned number:2;

View File

@ -27,12 +27,15 @@ template<class Derived>
class color_printer_base : public printer_base<Derived> class color_printer_base : public printer_base<Derived>
{ {
protected: protected:
const wchar_t* const m_color_str;
const float m_freq; const float m_freq;
const float m_spread; const float m_spread;
const bool m_invert;
protected: protected:
constexpr color_printer_base(const cmd_args& args)noexcept: constexpr color_printer_base(const cmd_args& args, const wchar_t* col_str)noexcept:
printer_base<Derived>(args.tabs ? SHOW_TABS_STRING : L" ", args), printer_base<Derived>(args.tabs ? SHOW_TABS_STRING : L" ", args),
m_freq(args.freq), m_spread(m_freq < 0 ? -args.spread : args.spread){} m_color_str(col_str),
m_freq(args.freq), m_spread(m_freq < 0 ? -args.spread : args.spread), m_invert(args.invert){}
Derived& _reset(void){ Derived& _reset(void){
wprintf(L"\033[0m"); wprintf(L"\033[0m");
return static_cast<Derived&>(*this); return static_cast<Derived&>(*this);

View File

@ -49,7 +49,7 @@ private:
color curr = color::red; color curr = color::red;
constexpr color_state(void)noexcept{ color_state(void)noexcept{
switch(rand()%3){ switch(rand()%3){
case 0: case 0:
r = color_max_amount; r = color_max_amount;
@ -95,8 +95,8 @@ private:
} }
}m_line_color = {}, m_color = m_line_color; }m_line_color = {}, m_color = m_line_color;
public: public:
constexpr color_printer_true(const cmd_args& args)noexcept: color_printer_true(const cmd_args& args)noexcept:
color_printer_base<color_printer_true>(args){} color_printer_base<color_printer_true>(args, args.invert ? L"\033[38;5;0m\033[48;2;%s;%s;%sm" : L"\033[38;2;%s;%s;%sm"){}
protected: protected:
color_printer_true& _print(const wchar_t s)noexcept{ color_printer_true& _print(const wchar_t s)noexcept{
@ -104,6 +104,10 @@ protected:
if(s == L'\n'){ if(s == L'\n'){
inc_line(); inc_line();
updated = true; updated = true;
if(m_invert)
reset();
putwchar(L'\n');
return *this;
}else{ }else{
int width = wcwidth(s); int width = wcwidth(s);
if(width > 0) if(width > 0)
@ -112,10 +116,13 @@ protected:
updated = inc_color(1); updated = inc_color(1);
} }
if(updated) if(updated)
wprintf(L"\033[38;2;%s;%s;%sm", lookup_table[m_color.r], lookup_table[m_color.g], lookup_table[m_color.b]); wprintf(m_color_str, lookup_table[m_color.r], lookup_table[m_color.g], lookup_table[m_color.b]);
putwchar(s); putwchar(s);
return *this; return *this;
} }
color_printer_true& _reset(void){
return color_printer_base<color_printer_true>::_reset();
}
constexpr void inc_line(void){ constexpr void inc_line(void){
int amount = m_spread*(float{color_max_amount}/4); int amount = m_spread*(float{color_max_amount}/4);
_do_inc_color(amount, m_line_color); _do_inc_color(amount, m_line_color);

View File

@ -71,11 +71,11 @@ protected:
constexpr printer_base(const wchar_t* tabstr, const cmd_args& args)noexcept; constexpr printer_base(const wchar_t* tabstr, const cmd_args& args)noexcept;
~printer_base(void)noexcept = default; ~printer_base(void)noexcept = default;
public: public:
constexpr Derived& print(wchar_t s)noexcept(noexcept(std::declval<Derived>()._print(s))); Derived& print(wchar_t s)noexcept(noexcept(std::declval<Derived>()._print(s)));
constexpr Derived& print(const wchar_t* s)noexcept(noexcept(std::declval<printer_base<Derived>>().print(std::declval<wchar_t>()))); Derived& print(const wchar_t* s)noexcept(noexcept(std::declval<printer_base<Derived>>().print(std::declval<wchar_t>())));
constexpr Derived& print(char s); Derived& print(char s);
constexpr Derived& print(const char* s); Derived& print(const char* s);
constexpr Derived& reset(void); Derived& reset(void);
}; };
#endif #endif

View File

@ -39,7 +39,7 @@ constexpr printer_base<Derived>::printer_base(const wchar_t* tabstr, const cmd_a
m_tab_size(wcslen(tabstr)){} m_tab_size(wcslen(tabstr)){}
template<class Derived> template<class Derived>
constexpr auto printer_base<Derived>::print(wchar_t s)noexcept(noexcept(std::declval<Derived>()._print(s))) -> Derived&{ auto printer_base<Derived>::print(wchar_t s)noexcept(noexcept(std::declval<Derived>()._print(s))) -> Derived&{
Derived& dv = static_cast<Derived&>(*this); Derived& dv = static_cast<Derived&>(*this);
//suppress repeated blank lines //suppress repeated blank lines
if(m_squeeze_blank){ if(m_squeeze_blank){
@ -88,27 +88,27 @@ constexpr auto printer_base<Derived>::print(wchar_t s)noexcept(noexcept(std::dec
} }
template<class Derived> template<class Derived>
constexpr auto printer_base<Derived>::print(const wchar_t* s)noexcept(noexcept(std::declval<printer_base<Derived>>().print(std::declval<wchar_t>()))) -> Derived&{ auto printer_base<Derived>::print(const wchar_t* s)noexcept(noexcept(std::declval<printer_base<Derived>>().print(std::declval<wchar_t>()))) -> Derived&{
for(;*s != 0;++s){ for(;*s != 0;++s){
print(*s); print(*s);
} }
return static_cast<Derived&>(*this); return static_cast<Derived&>(*this);
} }
template<class Derived> template<class Derived>
constexpr auto printer_base<Derived>::print(char s) -> Derived&{ auto printer_base<Derived>::print(char s) -> Derived&{
wchar_t tmp; wchar_t tmp;
mbstowcs(&tmp, &s, 1); mbstowcs(&tmp, &s, 1);
return print(tmp); return print(tmp);
} }
template<class Derived> template<class Derived>
constexpr auto printer_base<Derived>::print(const char* s) -> Derived&{ auto printer_base<Derived>::print(const char* s) -> Derived&{
for(;*s != 0;++s){ for(;*s != 0;++s){
print(*s); print(*s);
} }
return static_cast<Derived&>(*this); return static_cast<Derived&>(*this);
} }
template<class Derived> template<class Derived>
constexpr auto printer_base<Derived>::reset(void) -> Derived&{ auto printer_base<Derived>::reset(void) -> Derived&{
if constexpr(HAS_FUNC(_reset)<Derived,Derived&>::value){ if constexpr(HAS_FUNC(_reset)<Derived,Derived&>::value){
return static_cast<Derived&>(*this)._reset(); return static_cast<Derived&>(*this)._reset();
}else{ }else{

View File

@ -1,86 +0,0 @@
#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/>.
#Copyright 2018 rexy712
SOURCE_DIRS:=src
OBJDIR:=obj
DEPDIR:=$(OBJDIR)/dep
INCLUDE_DIRS:=include
EXT:=cpp
MAIN_EXECUTABLE:=tester
CXX:=g++
CXXFLAGS:=-g -std=c++17 -Wall -pedantic -Wextra -fno-exceptions -fno-rtti
all: CXXFLAGS+=-O0
release: CXXFLAGS+=-O2
LDFLAGS=
LDLIBS:=-lncurses
STRIP:=strip
memchk:LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
memchk:CXXFLAGS+=-O0 -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
ifeq ($(OS),Windows_NT)
mkdir=mkdir $(subst /,\,$(1)) > NUL 2>&1
rm=del /F $(1) > NUL 2>&1
rmdir=rd /s /q $(1) > NUL 2>&1
move=move /y $(subst /,\,$(1)) $(subst /,\,$(2)) > NUL 2>&1
MAIN_EXECUTABLE:=$(MAIN_EXECUTABLE).exe
LDLIBS:=-lglfw3 -lSOIL -lgl3w -lm -lopengl32 -lglu32 -lgdi32 -lkernel32
else
mkdir=mkdir -p $(1)
rm=rm -f $(1)
rmdir=rm -rf $(1)
move=mv $(1) $(2)
endif
INTERNAL_CXXFLAGS=-c $(foreach dir,$(INCLUDE_DIRS),-I"$(dir)") -MMD -MP -MF"$(DEPDIR)/$(notdir $(patsubst %.o,%.d,$@))"
SOURCES:=$(foreach source,$(SOURCE_DIRS),$(foreach ext,$(EXT),$(wildcard $(source)/*.$(ext))))
OBJECTS:=$(addprefix $(OBJDIR)/,$(subst \,.,$(subst /,.,$(addsuffix .o,$(SOURCES)))))
all: $(MAIN_EXECUTABLE)
memchk: $(MAIN_EXECUTABLE)
$(MAIN_EXECUTABLE): $(OBJECTS)
$(CXX) $(LDFLAGS) $^ -o "$(basename $@)" $(LDLIBS)
.PHONY: release
release: $(OBJECTS)
$(CXX) $(LDFLAGS) $^ -o "$(basename $(MAIN_EXECUTABLE))" $(LDLIBS)
$(STRIP) --strip-all "$(MAIN_EXECUTABLE)"
define GENERATE_OBJECTS
$$(OBJDIR)/$(subst \,.,$(subst /,.,$(1))).%.o: $(1)/%
$$(CXX) $$(CXXFLAGS) $$(INTERNAL_CXXFLAGS) "$$<" -o "$$@"
endef
$(foreach dir,$(SOURCE_DIRS),$(eval $(call GENERATE_OBJECTS,$(dir))))
$(OBJECTS): | $(OBJDIR) $(DEPDIR)
$(OBJDIR):
$(call mkdir,"$@")
$(DEPDIR):
$(call mkdir,"$@")
.PHONY: clean
clean:
$(call rmdir,"$(DEPDIR)")
$(call rmdir,"$(OBJDIR)")
$(call rm,"$(MAIN_EXECUTABLE)")
-include $(wildcard $(DEPDIR)/*.d)

View File

@ -82,6 +82,7 @@ static constexpr const char FREQ_LONG_OPTION[] = "freq" REQ_FLOAT_AR
static constexpr const char TRUECOLOR_LONG_OPTION[] = "truecolor"; static constexpr const char TRUECOLOR_LONG_OPTION[] = "truecolor";
static constexpr const char FORCE_COLOR_LONG_OPTION[] = "force"; static constexpr const char FORCE_COLOR_LONG_OPTION[] = "force";
static constexpr const char DISABLE_COLOR_LONG_OPTION[] = "no-color"; static constexpr const char DISABLE_COLOR_LONG_OPTION[] = "no-color";
static constexpr const char INVERT_LONG_OPTION[] = "invert";
static constexpr const char IGNORE_ANIMATE_LONG_OPTION[] = "animate"; static constexpr const char IGNORE_ANIMATE_LONG_OPTION[] = "animate";
static constexpr const char IGNORE_DURATION_LONG_OPTION[] = "duration" REQ_INTEGER_ARG; static constexpr const char IGNORE_DURATION_LONG_OPTION[] = "duration" REQ_INTEGER_ARG;
@ -96,6 +97,7 @@ static constexpr const char SHOW_ENDS_SHORT_OPTION[] = "E";
static constexpr const char FORCE_COLOR_SHORT_OPTION[] = "f"; static constexpr const char FORCE_COLOR_SHORT_OPTION[] = "f";
static constexpr const char FREQ_SHORT_OPTION[] = "F"; static constexpr const char FREQ_SHORT_OPTION[] = "F";
static constexpr const char USAGE_SHORT_OPTION[] = "h"; static constexpr const char USAGE_SHORT_OPTION[] = "h";
static constexpr const char INVERT_SHORT_OPTION[] = "i";
static constexpr const char NUMBER_LINES_SHORT_OPTION[] = "n"; static constexpr const char NUMBER_LINES_SHORT_OPTION[] = "n";
static constexpr const char DISABLE_COLOR_SHORT_OPTION[] = "N"; static constexpr const char DISABLE_COLOR_SHORT_OPTION[] = "N";
static constexpr const char SPREAD_SHORT_OPTION[] = "p"; static constexpr const char SPREAD_SHORT_OPTION[] = "p";
@ -135,6 +137,7 @@ static constexpr const char TRUECOLOR_DESC[] = "24-bit (truecolor)
static constexpr const char FORCE_COLOR_DESC[] = "Force color even when stdout is not a tty"; static constexpr const char FORCE_COLOR_DESC[] = "Force color even when stdout is not a tty";
static constexpr const char DISABLE_COLOR_DESC_BASE[] = "Suppress color even when stdout is a tty, overrides -"; static constexpr const char DISABLE_COLOR_DESC_BASE[] = "Suppress color even when stdout is a tty, overrides -";
static constexpr const char* DISABLE_COLOR_DESC = concat_many_strs<DISABLE_COLOR_DESC_BASE,FORCE_COLOR_SHORT_OPTION>::str; static constexpr const char* DISABLE_COLOR_DESC = concat_many_strs<DISABLE_COLOR_DESC_BASE,FORCE_COLOR_SHORT_OPTION>::str;
static constexpr const char INVERT_DESC[] = "Change background color instead of foreground";
static constexpr const char* IGNORE_ANIMATE_DESC = IGNORED_DESC; static constexpr const char* IGNORE_ANIMATE_DESC = IGNORED_DESC;
static constexpr const char* IGNORE_DURATION_DESC = IGNORED_DESC; static constexpr const char* IGNORE_DURATION_DESC = IGNORED_DESC;
@ -198,7 +201,7 @@ static constexpr size_t strlen_pre_eq(const char* str){
#define CHECK_VALID_SHORT_ARG(opt, arg, type) \ #define CHECK_VALID_SHORT_ARG(opt, arg, type) \
{ \ { \
if(next_arg == (argc-1) || !is_##type(arg)){ \ if(next_arg == argc || !is_##type(arg)){ \
fwprintf(stderr, L"'-%s' requires an argument of type " #type "\n", opt); \ fwprintf(stderr, L"'-%s' requires an argument of type " #type "\n", opt); \
ret.error = 1; \ ret.error = 1; \
break; \ break; \
@ -223,6 +226,8 @@ cmd_args process_cmd_args(int argc, char** argv){
} }
if(!strcmp(argv[i], "--")){ if(!strcmp(argv[i], "--")){
escaped = true; escaped = true;
}else if(!strcmp(argv[i], "-")){
ret.filenames.push_back(argv[i]);
}else if(IS_SHORT_OPTION(argv[i])){ }else if(IS_SHORT_OPTION(argv[i])){
size_t arg_len = strlen(argv[i]); size_t arg_len = strlen(argv[i]);
int next_arg = i+1; int next_arg = i+1;
@ -274,6 +279,9 @@ cmd_args process_cmd_args(int argc, char** argv){
if(ret.color == COLOR_DEFAULT) if(ret.color == COLOR_DEFAULT)
ret.color = COLOR_FORCE; ret.color = COLOR_FORCE;
break; break;
case SHORT_OPT(INVERT):
ret.invert = 1;
break;
case SHORT_OPT(SEED): case SHORT_OPT(SEED):
CHECK_VALID_SHORT_INT_ARG(SEED, argv[next_arg]); CHECK_VALID_SHORT_INT_ARG(SEED, argv[next_arg]);
ret.seed = atol(argv[next_arg]); ret.seed = atol(argv[next_arg]);
@ -329,6 +337,8 @@ cmd_args process_cmd_args(int argc, char** argv){
}else if(CHECK_LONG_OPTION(FORCE_COLOR, arg)){ }else if(CHECK_LONG_OPTION(FORCE_COLOR, arg)){
if(ret.color == COLOR_DEFAULT) if(ret.color == COLOR_DEFAULT)
ret.color = COLOR_FORCE; ret.color = COLOR_FORCE;
}else if(CHECK_LONG_OPTION(INVERT, arg)){
ret.invert = 1;
}else if(CHECK_LONG_OPTION_WITH_ARG(SEED, arg)){ }else if(CHECK_LONG_OPTION_WITH_ARG(SEED, arg)){
constexpr size_t offset = strlen_pre_eq(SEED_LONG_OPTION); constexpr size_t offset = strlen_pre_eq(SEED_LONG_OPTION);
CHECK_VALID_LONG_INT_ARG(SEED, offset, arg); CHECK_VALID_LONG_INT_ARG(SEED, offset, arg);
@ -381,6 +391,7 @@ const cmd_options cmd_arguments_list[] = {
OPTION(IGNORE_ANIMATE), OPTION(IGNORE_ANIMATE),
OPTION(IGNORE_DURATION), OPTION(IGNORE_DURATION),
OPTION(IGNORE_SPEED), OPTION(IGNORE_SPEED),
OPTION(INVERT),
{nullptr,0,nullptr}, {nullptr,0,nullptr},
OPTION(USAGE), OPTION(USAGE),
OPTION(VERSION) OPTION(VERSION)

View File

@ -34,7 +34,7 @@
#include <chrono> //std::chrono::* #include <chrono> //std::chrono::*
#include <cstdlib> //srand #include <cstdlib> //srand
constexpr const char* version_string = "roflcat version 0.1a"; constexpr const char version_string[] = "roflcat version 1.0";
static constexpr size_t constexpr_strlen(const char* str){ static constexpr size_t constexpr_strlen(const char* str){
size_t i = 0; size_t i = 0;
@ -126,6 +126,7 @@ int print_files(cmd_args& args){
if(in == L'\n') //Only reset on newline to save print overhead if(in == L'\n') //Only reset on newline to save print overhead
p.reset(); p.reset();
} }
clearerr(stdin);
}else{ //everything besides stdin }else{ //everything besides stdin
FILE* fp = fopen(args.filenames[i], "r"); FILE* fp = fopen(args.filenames[i], "r");
if(!fp){ if(!fp){