Merge branch 'master' of gitlab.com:rexy712/roflcat
This commit is contained in:
commit
ece4b9668d
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ temp
|
||||
*.d
|
||||
tester
|
||||
roflcat
|
||||
build
|
||||
|
||||
24
CMakeLists.txt
Normal file
24
CMakeLists.txt
Normal 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)
|
||||
@ -31,12 +31,16 @@
|
||||
|
||||
template<int I>
|
||||
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){}
|
||||
template<int I>
|
||||
basic_color_printer<I>& basic_color_printer<I>::_print(const wchar_t s)noexcept{
|
||||
if(s == L'\n'){
|
||||
inc_line();
|
||||
if(this->m_invert)
|
||||
this->reset();
|
||||
putwchar(L'\n');
|
||||
return *this;
|
||||
}else{
|
||||
int width = wcwidth(s);
|
||||
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;
|
||||
if(new_index != m_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);
|
||||
return *this;
|
||||
|
||||
@ -45,11 +45,12 @@ struct cmd_args{
|
||||
std::vector<const char*> filenames;
|
||||
|
||||
//lolcat options
|
||||
long seed = 0;
|
||||
float freq = 0.2f;
|
||||
float spread = 0.3f;
|
||||
long seed = 0;
|
||||
unsigned truecol:1;
|
||||
unsigned color:2;
|
||||
unsigned invert:1;
|
||||
|
||||
//GNU cat options
|
||||
unsigned number:2;
|
||||
|
||||
@ -27,12 +27,15 @@ template<class Derived>
|
||||
class color_printer_base : public printer_base<Derived>
|
||||
{
|
||||
protected:
|
||||
const wchar_t* const m_color_str;
|
||||
const float m_freq;
|
||||
const float m_spread;
|
||||
const bool m_invert;
|
||||
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),
|
||||
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){
|
||||
wprintf(L"\033[0m");
|
||||
return static_cast<Derived&>(*this);
|
||||
|
||||
@ -49,7 +49,7 @@ private:
|
||||
color curr = color::red;
|
||||
|
||||
|
||||
constexpr color_state(void)noexcept{
|
||||
color_state(void)noexcept{
|
||||
switch(rand()%3){
|
||||
case 0:
|
||||
r = color_max_amount;
|
||||
@ -95,8 +95,8 @@ private:
|
||||
}
|
||||
}m_line_color = {}, m_color = m_line_color;
|
||||
public:
|
||||
constexpr color_printer_true(const cmd_args& args)noexcept:
|
||||
color_printer_base<color_printer_true>(args){}
|
||||
color_printer_true(const cmd_args& args)noexcept:
|
||||
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:
|
||||
color_printer_true& _print(const wchar_t s)noexcept{
|
||||
@ -104,6 +104,10 @@ protected:
|
||||
if(s == L'\n'){
|
||||
inc_line();
|
||||
updated = true;
|
||||
if(m_invert)
|
||||
reset();
|
||||
putwchar(L'\n');
|
||||
return *this;
|
||||
}else{
|
||||
int width = wcwidth(s);
|
||||
if(width > 0)
|
||||
@ -112,10 +116,13 @@ protected:
|
||||
updated = inc_color(1);
|
||||
}
|
||||
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);
|
||||
return *this;
|
||||
}
|
||||
color_printer_true& _reset(void){
|
||||
return color_printer_base<color_printer_true>::_reset();
|
||||
}
|
||||
constexpr void inc_line(void){
|
||||
int amount = m_spread*(float{color_max_amount}/4);
|
||||
_do_inc_color(amount, m_line_color);
|
||||
|
||||
@ -71,11 +71,11 @@ protected:
|
||||
constexpr printer_base(const wchar_t* tabstr, const cmd_args& args)noexcept;
|
||||
~printer_base(void)noexcept = default;
|
||||
public:
|
||||
constexpr 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>())));
|
||||
constexpr Derived& print(char s);
|
||||
constexpr Derived& print(const char* s);
|
||||
constexpr Derived& reset(void);
|
||||
Derived& print(wchar_t s)noexcept(noexcept(std::declval<Derived>()._print(s)));
|
||||
Derived& print(const wchar_t* s)noexcept(noexcept(std::declval<printer_base<Derived>>().print(std::declval<wchar_t>())));
|
||||
Derived& print(char s);
|
||||
Derived& print(const char* s);
|
||||
Derived& reset(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -39,7 +39,7 @@ constexpr printer_base<Derived>::printer_base(const wchar_t* tabstr, const cmd_a
|
||||
m_tab_size(wcslen(tabstr)){}
|
||||
|
||||
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);
|
||||
//suppress repeated blank lines
|
||||
if(m_squeeze_blank){
|
||||
@ -88,27 +88,27 @@ constexpr auto printer_base<Derived>::print(wchar_t s)noexcept(noexcept(std::dec
|
||||
}
|
||||
|
||||
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){
|
||||
print(*s);
|
||||
}
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
template<class Derived>
|
||||
constexpr auto printer_base<Derived>::print(char s) -> Derived&{
|
||||
auto printer_base<Derived>::print(char s) -> Derived&{
|
||||
wchar_t tmp;
|
||||
mbstowcs(&tmp, &s, 1);
|
||||
return print(tmp);
|
||||
}
|
||||
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){
|
||||
print(*s);
|
||||
}
|
||||
return static_cast<Derived&>(*this);
|
||||
}
|
||||
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){
|
||||
return static_cast<Derived&>(*this)._reset();
|
||||
}else{
|
||||
|
||||
86
makefile
86
makefile
@ -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)
|
||||
|
||||
13
src/cmd.cpp
13
src/cmd.cpp
@ -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 FORCE_COLOR_LONG_OPTION[] = "force";
|
||||
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_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 FREQ_SHORT_OPTION[] = "F";
|
||||
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 DISABLE_COLOR_SHORT_OPTION[] = "N";
|
||||
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 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 INVERT_DESC[] = "Change background color instead of foreground";
|
||||
|
||||
static constexpr const char* IGNORE_ANIMATE_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) \
|
||||
{ \
|
||||
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); \
|
||||
ret.error = 1; \
|
||||
break; \
|
||||
@ -223,6 +226,8 @@ cmd_args process_cmd_args(int argc, char** argv){
|
||||
}
|
||||
if(!strcmp(argv[i], "--")){
|
||||
escaped = true;
|
||||
}else if(!strcmp(argv[i], "-")){
|
||||
ret.filenames.push_back(argv[i]);
|
||||
}else if(IS_SHORT_OPTION(argv[i])){
|
||||
size_t arg_len = strlen(argv[i]);
|
||||
int next_arg = i+1;
|
||||
@ -274,6 +279,9 @@ cmd_args process_cmd_args(int argc, char** argv){
|
||||
if(ret.color == COLOR_DEFAULT)
|
||||
ret.color = COLOR_FORCE;
|
||||
break;
|
||||
case SHORT_OPT(INVERT):
|
||||
ret.invert = 1;
|
||||
break;
|
||||
case SHORT_OPT(SEED):
|
||||
CHECK_VALID_SHORT_INT_ARG(SEED, 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)){
|
||||
if(ret.color == COLOR_DEFAULT)
|
||||
ret.color = COLOR_FORCE;
|
||||
}else if(CHECK_LONG_OPTION(INVERT, arg)){
|
||||
ret.invert = 1;
|
||||
}else if(CHECK_LONG_OPTION_WITH_ARG(SEED, arg)){
|
||||
constexpr size_t offset = strlen_pre_eq(SEED_LONG_OPTION);
|
||||
CHECK_VALID_LONG_INT_ARG(SEED, offset, arg);
|
||||
@ -381,6 +391,7 @@ const cmd_options cmd_arguments_list[] = {
|
||||
OPTION(IGNORE_ANIMATE),
|
||||
OPTION(IGNORE_DURATION),
|
||||
OPTION(IGNORE_SPEED),
|
||||
OPTION(INVERT),
|
||||
{nullptr,0,nullptr},
|
||||
OPTION(USAGE),
|
||||
OPTION(VERSION)
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
#include <chrono> //std::chrono::*
|
||||
#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){
|
||||
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
|
||||
p.reset();
|
||||
}
|
||||
clearerr(stdin);
|
||||
}else{ //everything besides stdin
|
||||
FILE* fp = fopen(args.filenames[i], "r");
|
||||
if(!fp){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user