GNU Readline is GPL and so I can't link to it from this MIT-license project.
Including editline as a submodule.
+[submodule "lib/editline"]
+ path = lib/editline
+ url = https://github.com/troglobit/editline.git
project(MouseTrackerForCubism_project)
-find_library(xdo_LIBS NAMES xdo libxdo PATHS /usr/lib REQUIRED)
+find_library(xdo_LIBS NAMES xdo PATHS /usr/lib REQUIRED)
find_library(pulse_LIBS NAMES pulse PATHS /usr/lib REQUIRED)
-find_library(readline_LIBS NAMES readline libreadline /usr/lib REQUIRED)
-include_directories(include)
+include(ExternalProject)
+ExternalProject_Add(editline
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/editline/src
+ BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/editline
+ CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/editline/autogen.sh COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/lib/editline/configure --prefix=<INSTALL_DIR>
+ BUILD_COMMAND ${MAKE})
+
+ExternalProject_Get_Property(editline install_dir)
+set(editline_INSTALL_DIR ${install_dir})
+
+include_directories(include ${CMAKE_CURRENT_SOURCE_DIR}/lib/editline/include)
add_library(
MouseTrackerForCubism STATIC
include/mouse_cursor_tracker.h
)
-target_link_libraries(MouseTrackerForCubism ${xdo_LIBS} ${pulse_LIBS} pulse-simple ${readline_LIBS})
+target_link_libraries(MouseTrackerForCubism ${xdo_LIBS} ${pulse_LIBS} pulse-simple ${editline_INSTALL_DIR}/lib/libeditline.a)
1. Install dependencies.
You will require a recent C/C++ compiler, `make`, `patch`, CMake >= 3.16,
- libxdo, PulseAudio, and readline. To compile the example
+ libxdo, and PulseAudio. To compile the example
program you will also require the OpenGL library (and its dev headers)
among other libraries required for the example program. The libraries I
had to install (this list may not be exhaustive) are:
- libxdo-dev libpulse-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev libreadline-dev
+ libxdo-dev libpulse-dev libgl1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libglu1-mesa-dev
-2. Clone this repository
+2. Clone this repository including its submodule (editline)
- git clone https://github.com/adrianiainlam/mouse-tracker-for-cubism.git
+ git clone --recurse-submodules https://github.com/adrianiainlam/mouse-tracker-for-cubism.git
3. To build the library only: (Skip this step if you want to build the example
program. It will be done automatically.)
./build.sh
+ Note: I have observed that sometimes, on the first build, a failure
+ will be reported, such as:
+
+ [ 98%] Completed 'editline'
+ [ 98%] Built target editline
+ Makefile:149: recipe for target 'all' failed
+ make: *** [all] Error 2
+
+ I have no idea why, but seems like running build.sh again solves the
+ issue. Please open an issue / contact me if not.
+
7. Now try running the example program. From the "example" directory:
cd ./demo_build/build/make_gcc/bin/Demo/
The license text can be found in LICENSE-MIT.txt, and also at the top of
the .cpp and .h files.
+This library depends on "editline" which is included here as a git
+submodule. The fork used here was originally written by Simmule
+Turner and Rick Salz, made available under the Spencer License 94,
+now maintained by Joachim Wiberg. See "lib/editline/LICENSE" for more
+information.
+
+(Note: An earlier version of this library linked to GNU Readline as
+a dependency. I have made a mistake and assumed GNU Readline was LGPL,
+when in fact it was GPL. This has been corrected within 24 hours, by
+replacing GNU Readline with editline instead. I apologize to the
+copyright holders of GNU Readline.)
+
The example program is a patched version of the sample program provided
by Live2D (because there's really no point in reinventing the wheel),
and as such, as per the licensing restrictions by Live2D, is still the
--- /dev/null
+Subproject commit 62bba782585c6c18d7a2b27beeb60a45db9abb43
{
#include <xdo.h>
#include <pulse/simple.h>
-#include <readline/readline.h>
-#include <readline/history.h>
+#include <string.h> // strdup
+#include "editline.h"
}
#include "mouse_cursor_tracker.h"
std::vector<std::string> MCT_expressions;
std::map<std::string, double> *MCT_overrideMap;
-static char **cliCompletionFunction(const char *textCStr, int start, int end)
+static int cliListPossible(char *token, char ***av)
{
// Reference: https://github.com/eliben/code-for-blog/blob/master/2016/readline-samples/readline-complete-subcommand.cpp
- rl_attempted_completion_over = 1;
std::string line(rl_line_buffer);
{
constructed.push_back(std::to_string(i));
}
+ break; // No need to loop through the list, all motions have the same set of priorities
}
}
if (!vocab)
{
- return nullptr;
+ return 0;
}
- std::string text(textCStr);
+ std::string text(token);
std::vector<std::string> matches;
std::copy_if(vocab->begin(), vocab->end(), std::back_inserter(matches),
[&text](const std::string &s)
s.compare(0, text.size(), text) == 0);
});
- if (matches.empty())
+ *av = static_cast<char **>(malloc(matches.size() * sizeof (**av)));
+ if (!*av) return 0;
+ for (std::size_t i = 0; i < matches.size(); i++)
{
- return nullptr;
+ (*av)[i] = strdup(matches[i].c_str());
}
+ return matches.size();
+}
+
+static char *cliComplete(char *token, int *match)
+{
+ char **av;
+ int numMatches = cliListPossible(token, &av);
+
+ *match = 0;
+ if (numMatches == 0) return nullptr;
- char** array =
- static_cast<char**>(malloc((2 + matches.size()) * sizeof(*array)));
- array[0] = strdup(longest_common_prefix(text, matches).c_str());
- size_t ptr = 1;
- for (const auto& m : matches) {
- array[ptr++] = strdup(m.c_str());
+ std::vector<std::string> list;
+
+ for (std::size_t i = 0; i < numMatches; i++)
+ {
+ list.push_back(std::string(av[i]));
+ free(av[i]);
}
- array[ptr] = nullptr;
- return array;
+ free(av);
+
+ if (numMatches == 1)
+ {
+ *match = 1;
+ std::string result = list[0] + " ";
+ return strdup(result.c_str() + strlen(token));
+ }
+
+ std::string lcp = longest_common_prefix(token, list);
+
+ if (lcp.size() > strlen(token))
+ {
+ *match = 1;
+ return strdup(lcp.c_str() + strlen(token));
+ }
+
+ return nullptr;
}
MouseCursorTracker::MouseCursorTracker(std::string cfgPath,
void MouseCursorTracker::cliLoop(void)
{
- rl_catch_signals = 0;
- rl_attempted_completion_function = cliCompletionFunction;
+ rl_set_complete_func(&cliComplete);
+ rl_set_list_possib_func(&cliListPossible);
while (!m_stop)
{
char *buf = readline(">> ");
{
std::cerr << "std::stod failed" << std::endl;
}
-
- std::cerr << "Debug: setting " << cmdSplit[i] << std::endl;
}
}
else if (cmdSplit[0] == "clear")