mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-02 04:20:16 +00:00
Add --filename-format option (fix #519)
This commit is contained in:
parent
9d5d911830
commit
72e2040c58
@ -154,6 +154,7 @@ add_library(app-lib
|
|||||||
file/tga_format.cpp
|
file/tga_format.cpp
|
||||||
file_selector.cpp
|
file_selector.cpp
|
||||||
file_system.cpp
|
file_system.cpp
|
||||||
|
filename_formatter.cpp
|
||||||
flatten.cpp
|
flatten.cpp
|
||||||
gui_xml.cpp
|
gui_xml.cpp
|
||||||
handle_anidir.cpp
|
handle_anidir.cpp
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "app/file/file_formats_manager.h"
|
#include "app/file/file_formats_manager.h"
|
||||||
#include "app/file/palette_file.h"
|
#include "app/file/palette_file.h"
|
||||||
#include "app/file_system.h"
|
#include "app/file_system.h"
|
||||||
|
#include "app/filename_formatter.h"
|
||||||
#include "app/find_widget.h"
|
#include "app/find_widget.h"
|
||||||
#include "app/gui_xml.h"
|
#include "app/gui_xml.h"
|
||||||
#include "app/ini_file.h"
|
#include "app/ini_file.h"
|
||||||
@ -220,6 +221,7 @@ void App::initialize(const AppOptions& options)
|
|||||||
bool splitLayersSaveAs = false;
|
bool splitLayersSaveAs = false;
|
||||||
std::string importLayer;
|
std::string importLayer;
|
||||||
std::string importLayerSaveAs;
|
std::string importLayerSaveAs;
|
||||||
|
std::string filenameFormat;
|
||||||
|
|
||||||
for (const auto& value : options.values()) {
|
for (const auto& value : options.values()) {
|
||||||
const AppOptions::Option* opt = value.option();
|
const AppOptions::Option* opt = value.option();
|
||||||
@ -265,6 +267,10 @@ void App::initialize(const AppOptions& options)
|
|||||||
else if (opt == &options.ignoreEmpty()) {
|
else if (opt == &options.ignoreEmpty()) {
|
||||||
ignoreEmpty = true;
|
ignoreEmpty = true;
|
||||||
}
|
}
|
||||||
|
// --filename-format
|
||||||
|
else if (opt == &options.filenameFormat()) {
|
||||||
|
filenameFormat = value.value();
|
||||||
|
}
|
||||||
// --save-as <filename>
|
// --save-as <filename>
|
||||||
else if (opt == &options.saveAs()) {
|
else if (opt == &options.saveAs()) {
|
||||||
Document* doc = NULL;
|
Document* doc = NULL;
|
||||||
@ -277,30 +283,35 @@ void App::initialize(const AppOptions& options)
|
|||||||
else {
|
else {
|
||||||
ctx->setActiveDocument(doc);
|
ctx->setActiveDocument(doc);
|
||||||
|
|
||||||
|
std::string format = filenameFormat;
|
||||||
|
|
||||||
Command* command = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
|
Command* command = CommandsModule::instance()->getCommandByName(CommandId::SaveFileCopyAs);
|
||||||
if (splitLayersSaveAs) {
|
if (splitLayersSaveAs) {
|
||||||
std::vector<Layer*> layers;
|
std::vector<Layer*> layers;
|
||||||
doc->sprite()->getLayersList(layers);
|
doc->sprite()->getLayersList(layers);
|
||||||
|
|
||||||
|
std::string fn, fmt;
|
||||||
|
if (format.empty()) {
|
||||||
|
if (doc->sprite()->totalFrames() > FrameNumber(1))
|
||||||
|
format = "{path}/{title} ({layer}) {frame}.{extension}";
|
||||||
|
else
|
||||||
|
format = "{path}/{title} ({layer}).{extension}";
|
||||||
|
}
|
||||||
|
|
||||||
// For each layer, hide other ones and save the sprite.
|
// For each layer, hide other ones and save the sprite.
|
||||||
for (Layer* show : layers) {
|
for (Layer* show : layers) {
|
||||||
for (Layer* hide : layers)
|
for (Layer* hide : layers)
|
||||||
hide->setReadable(hide == show);
|
hide->setReadable(hide == show);
|
||||||
|
|
||||||
std::string frameStr;
|
fn = filename_formatter(format,
|
||||||
if (doc->sprite()->totalFrames() > FrameNumber(1))
|
value.value(), show->name());
|
||||||
frameStr += " 1";
|
fmt = filename_formatter(format,
|
||||||
|
value.value(), show->name(), -1, false);
|
||||||
|
|
||||||
std::string fn = value.value();
|
Params params;
|
||||||
fn =
|
params.set("filename", fn.c_str());
|
||||||
base::join_path(
|
params.set("filename-format", fmt.c_str());
|
||||||
base::get_file_path(fn),
|
ctx->executeCommand(command, ¶ms);
|
||||||
base::get_file_title(fn))
|
|
||||||
+ " (" + show->name() + ")" + frameStr + "." +
|
|
||||||
base::get_file_extension(fn);
|
|
||||||
|
|
||||||
static_cast<SaveFileBaseCommand*>(command)->setFilename(fn);
|
|
||||||
ctx->executeCommand(command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -313,8 +324,10 @@ void App::initialize(const AppOptions& options)
|
|||||||
layer->setReadable(layer->name() == importLayerSaveAs);
|
layer->setReadable(layer->name() == importLayerSaveAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<SaveFileBaseCommand*>(command)->setFilename(value.value());
|
Params params;
|
||||||
ctx->executeCommand(command);
|
params.set("filename", value.value().c_str());
|
||||||
|
params.set("filename-format", format.c_str());
|
||||||
|
ctx->executeCommand(command, ¶ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -381,6 +394,9 @@ void App::initialize(const AppOptions& options)
|
|||||||
splitLayers = false;
|
splitLayers = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_exporter && !filenameFormat.empty())
|
||||||
|
m_exporter->setFilenameFormat(filenameFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export
|
// Export
|
||||||
|
@ -49,6 +49,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
|||||||
, m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
|
, m_splitLayers(m_po.add("split-layers").description("Import each layer of the next given sprite as\na separated image in the sheet"))
|
||||||
, m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite"))
|
, m_importLayer(m_po.add("import-layer").requiresValue("<name>").description("Import just one layer of the next given sprite"))
|
||||||
, m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
|
, m_ignoreEmpty(m_po.add("ignore-empty").description("Do not export empty frames/cels"))
|
||||||
|
, m_filenameFormat(m_po.add("filename-format").requiresValue("<fmt>").description("Special format to generate filenames"))
|
||||||
, m_verbose(m_po.add("verbose").description("Explain what is being done"))
|
, m_verbose(m_po.add("verbose").description("Explain what is being done"))
|
||||||
, m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
|
, m_help(m_po.add("help").mnemonic('?').description("Display this help and exits"))
|
||||||
, m_version(m_po.add("version").description("Output version information and exit"))
|
, m_version(m_po.add("version").description("Output version information and exit"))
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
const Option& splitLayers() const { return m_splitLayers; }
|
const Option& splitLayers() const { return m_splitLayers; }
|
||||||
const Option& importLayer() const { return m_importLayer; }
|
const Option& importLayer() const { return m_importLayer; }
|
||||||
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
|
const Option& ignoreEmpty() const { return m_ignoreEmpty; }
|
||||||
|
const Option& filenameFormat() const { return m_filenameFormat; }
|
||||||
|
|
||||||
bool hasExporterParams() const;
|
bool hasExporterParams() const;
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ private:
|
|||||||
Option& m_splitLayers;
|
Option& m_splitLayers;
|
||||||
Option& m_importLayer;
|
Option& m_importLayer;
|
||||||
Option& m_ignoreEmpty;
|
Option& m_ignoreEmpty;
|
||||||
|
Option& m_filenameFormat;
|
||||||
|
|
||||||
Option& m_verbose;
|
Option& m_verbose;
|
||||||
Option& m_help;
|
Option& m_help;
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "app/commands/cmd_save_file.h"
|
||||||
|
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/commands/command.h"
|
#include "app/commands/command.h"
|
||||||
#include "app/commands/params.h"
|
#include "app/commands/params.h"
|
||||||
@ -79,9 +81,11 @@ private:
|
|||||||
FileOp* m_fop;
|
FileOp* m_fop;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void save_document_in_background(Context* context, Document* document, bool mark_as_saved)
|
static void save_document_in_background(Context* context, Document* document,
|
||||||
|
bool mark_as_saved, const std::string& fn_format)
|
||||||
{
|
{
|
||||||
base::UniquePtr<FileOp> fop(fop_to_save_document(context, document));
|
base::UniquePtr<FileOp> fop(fop_to_save_document(context, document,
|
||||||
|
fn_format.c_str()));
|
||||||
if (!fop)
|
if (!fop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -113,111 +117,112 @@ static void save_document_in_background(Context* context, Document* document, bo
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class SaveFileBaseCommand : public Command {
|
SaveFileBaseCommand::SaveFileBaseCommand(const char* short_name, const char* friendly_name, CommandFlags flags)
|
||||||
public:
|
: Command(short_name, friendly_name, flags)
|
||||||
SaveFileBaseCommand(const char* short_name, const char* friendly_name, CommandFlags flags)
|
{
|
||||||
: Command(short_name, friendly_name, flags) {
|
}
|
||||||
|
|
||||||
|
void SaveFileBaseCommand::onLoadParams(Params* params)
|
||||||
|
{
|
||||||
|
m_filename = params->get("filename");
|
||||||
|
m_filenameFormat = params->get("filename-format");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if there is a current sprite to save.
|
||||||
|
// [main thread]
|
||||||
|
bool SaveFileBaseCommand::onEnabled(Context* context)
|
||||||
|
{
|
||||||
|
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveFileBaseCommand::saveAsDialog(const ContextReader& reader, const char* dlgTitle, bool markAsSaved)
|
||||||
|
{
|
||||||
|
const Document* document = reader.document();
|
||||||
|
std::string filename;
|
||||||
|
|
||||||
|
if (!m_filename.empty()) {
|
||||||
|
filename = m_filename;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
filename = document->filename();
|
||||||
|
|
||||||
protected:
|
char exts[4096];
|
||||||
void onLoadParams(Params* params) override {
|
get_writable_extensions(exts, sizeof(exts));
|
||||||
m_filename = params->get("filename");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if there is a current sprite to save.
|
for (;;) {
|
||||||
// [main thread]
|
std::string newfilename = app::show_file_selector(dlgTitle, filename, exts);
|
||||||
bool onEnabled(Context* context) override {
|
if (newfilename.empty())
|
||||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable);
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
void saveAsDialog(const ContextReader& reader, const char* dlgTitle, bool markAsSaved)
|
filename = newfilename;
|
||||||
{
|
|
||||||
const Document* document = reader.document();
|
|
||||||
std::string filename;
|
|
||||||
|
|
||||||
if (!m_filename.empty()) {
|
// Ask if the user wants overwrite the existent file.
|
||||||
filename = m_filename;
|
int ret = 0;
|
||||||
}
|
if (base::is_file(filename)) {
|
||||||
else {
|
ret = ui::Alert::show("Warning<<The file already exists, overwrite it?<<%s||&Yes||&No||&Cancel",
|
||||||
filename = document->filename();
|
base::get_file_name(filename).c_str());
|
||||||
|
|
||||||
char exts[4096];
|
// Check for read-only attribute.
|
||||||
get_writable_extensions(exts, sizeof(exts));
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
std::string newfilename = app::show_file_selector(dlgTitle, filename, exts);
|
|
||||||
if (newfilename.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
filename = newfilename;
|
|
||||||
|
|
||||||
// Ask if the user wants overwrite the existent file.
|
|
||||||
int ret = 0;
|
|
||||||
if (base::is_file(filename)) {
|
|
||||||
ret = ui::Alert::show("Warning<<The file already exists, overwrite it?<<%s||&Yes||&No||&Cancel",
|
|
||||||
base::get_file_name(filename).c_str());
|
|
||||||
|
|
||||||
// Check for read-only attribute.
|
|
||||||
if (ret == 1) {
|
|
||||||
if (!confirmReadonly(filename))
|
|
||||||
ret = 2; // Select file again.
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
// "yes": we must continue with the operation...
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
break;
|
if (!confirmReadonly(filename))
|
||||||
|
ret = 2; // Select file again.
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// "cancel" or <esc> per example: we back doing nothing
|
|
||||||
else if (ret != 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// "no": we must back to select other file-name
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
{
|
// "yes": we must continue with the operation...
|
||||||
ContextWriter writer(reader);
|
if (ret == 1) {
|
||||||
Document* documentWriter = writer.document();
|
break;
|
||||||
std::string oldFilename = documentWriter->filename();
|
}
|
||||||
|
// "cancel" or <esc> per example: we back doing nothing
|
||||||
|
else if (ret != 2)
|
||||||
|
return;
|
||||||
|
|
||||||
// Change the document file name
|
// "no": we must back to select other file-name
|
||||||
documentWriter->setFilename(filename.c_str());
|
|
||||||
m_selectedFilename = filename;
|
|
||||||
|
|
||||||
// Save the document
|
|
||||||
save_document_in_background(writer.context(), documentWriter, markAsSaved);
|
|
||||||
|
|
||||||
if (documentWriter->isModified())
|
|
||||||
documentWriter->setFilename(oldFilename);
|
|
||||||
|
|
||||||
update_screen_for_document(documentWriter);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool confirmReadonly(const std::string& filename)
|
|
||||||
{
|
{
|
||||||
if (!base::has_readonly_attr(filename))
|
ContextWriter writer(reader);
|
||||||
return true;
|
Document* documentWriter = writer.document();
|
||||||
|
std::string oldFilename = documentWriter->filename();
|
||||||
|
|
||||||
int ret = ui::Alert::show("Warning<<The file is read-only, do you really want to overwrite it?<<%s||&Yes||&No",
|
// Change the document file name
|
||||||
base::get_file_name(filename).c_str());
|
documentWriter->setFilename(filename.c_str());
|
||||||
|
m_selectedFilename = filename;
|
||||||
|
|
||||||
if (ret == 1) {
|
// Save the document
|
||||||
base::remove_readonly_attr(filename);
|
save_document_in_background(writer.context(), documentWriter,
|
||||||
return true;
|
markAsSaved, m_filenameFormat);
|
||||||
}
|
|
||||||
else
|
if (documentWriter->isModified())
|
||||||
return false;
|
documentWriter->setFilename(oldFilename);
|
||||||
|
|
||||||
|
update_screen_for_document(documentWriter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string m_filename;
|
//static
|
||||||
std::string m_selectedFilename;
|
bool SaveFileBaseCommand::confirmReadonly(const std::string& filename)
|
||||||
};
|
{
|
||||||
|
if (!base::has_readonly_attr(filename))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int ret = ui::Alert::show("Warning<<The file is read-only, do you really want to overwrite it?<<%s||&Yes||&No",
|
||||||
|
base::get_file_name(filename).c_str());
|
||||||
|
|
||||||
|
if (ret == 1) {
|
||||||
|
base::remove_readonly_attr(filename);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class SaveFileCommand : public SaveFileBaseCommand {
|
class SaveFileCommand : public SaveFileBaseCommand {
|
||||||
public:
|
public:
|
||||||
@ -249,7 +254,8 @@ void SaveFileCommand::onExecute(Context* context)
|
|||||||
if (!confirmReadonly(documentWriter->filename()))
|
if (!confirmReadonly(documentWriter->filename()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
save_document_in_background(context, documentWriter, true);
|
save_document_in_background(context, documentWriter, true,
|
||||||
|
m_filenameFormat.c_str());
|
||||||
update_screen_for_document(documentWriter);
|
update_screen_for_document(documentWriter);
|
||||||
}
|
}
|
||||||
// If the document isn't associated to a file, we must to show the
|
// If the document isn't associated to a file, we must to show the
|
||||||
|
@ -35,10 +35,6 @@ namespace app {
|
|||||||
return m_selectedFilename;
|
return m_selectedFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFilename(const std::string& fn) {
|
|
||||||
m_filename = fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onLoadParams(Params* params) override;
|
void onLoadParams(Params* params) override;
|
||||||
bool onEnabled(Context* context) override;
|
bool onEnabled(Context* context) override;
|
||||||
@ -48,6 +44,7 @@ namespace app {
|
|||||||
static bool confirmReadonly(const std::string& filename);
|
static bool confirmReadonly(const std::string& filename);
|
||||||
|
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
std::string m_filenameFormat;
|
||||||
std::string m_selectedFilename;
|
std::string m_selectedFilename;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "app/document.h"
|
#include "app/document.h"
|
||||||
#include "app/document_api.h"
|
#include "app/document_api.h"
|
||||||
#include "app/file/file.h"
|
#include "app/file/file.h"
|
||||||
|
#include "app/filename_formatter.h"
|
||||||
#include "app/ui_context.h"
|
#include "app/ui_context.h"
|
||||||
#include "base/convert_to.h"
|
#include "base/convert_to.h"
|
||||||
#include "base/path.h"
|
#include "base/path.h"
|
||||||
@ -273,24 +274,28 @@ void DocumentExporter::captureSamples(Samples& samples)
|
|||||||
Document* doc = item.doc;
|
Document* doc = item.doc;
|
||||||
Sprite* sprite = doc->sprite();
|
Sprite* sprite = doc->sprite();
|
||||||
Layer* layer = item.layer;
|
Layer* layer = item.layer;
|
||||||
|
bool hasFrames = (doc->sprite()->totalFrames() > FrameNumber(1));
|
||||||
|
bool hasLayer = (layer != NULL);
|
||||||
|
|
||||||
|
std::string format = m_filenameFormat;
|
||||||
|
if (format.empty()) {
|
||||||
|
if (hasFrames && hasLayer)
|
||||||
|
format = "{title} ({layer}) {frame}.{extension}";
|
||||||
|
else if (hasFrames)
|
||||||
|
format = "{title} {frame}.{extension}";
|
||||||
|
else if (hasLayer)
|
||||||
|
format = "{title} ({layer}).{extension}";
|
||||||
|
else
|
||||||
|
format = "{fullname}";
|
||||||
|
}
|
||||||
|
|
||||||
for (FrameNumber frame=FrameNumber(0);
|
for (FrameNumber frame=FrameNumber(0);
|
||||||
frame<sprite->totalFrames(); ++frame) {
|
frame<sprite->totalFrames(); ++frame) {
|
||||||
std::string filename = doc->filename();
|
std::string filename =
|
||||||
|
filename_formatter(format,
|
||||||
if (sprite->totalFrames() > FrameNumber(1)) {
|
doc->filename(),
|
||||||
std::string path = base::get_file_path(filename);
|
layer ? layer->name(): "",
|
||||||
std::string title = base::get_file_title(filename);
|
(sprite->totalFrames() > FrameNumber(1)) ? frame: FrameNumber(-1));
|
||||||
if (layer) {
|
|
||||||
title += " (";
|
|
||||||
title += layer->name();
|
|
||||||
title += ") ";
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = base::join_path(path, title +
|
|
||||||
base::convert_to<std::string>((int)frame + 1)
|
|
||||||
+ "." + base::get_file_extension(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
Sample sample(doc, sprite, layer, frame, filename);
|
Sample sample(doc, sprite, layer, frame, filename);
|
||||||
|
|
||||||
|
@ -93,6 +93,10 @@ namespace app {
|
|||||||
m_ignoreEmptyCels = ignore;
|
m_ignoreEmptyCels = ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setFilenameFormat(const std::string& format) {
|
||||||
|
m_filenameFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
void addDocument(Document* document, raster::Layer* layer = NULL) {
|
void addDocument(Document* document, raster::Layer* layer = NULL) {
|
||||||
m_documents.push_back(Item(document, layer));
|
m_documents.push_back(Item(document, layer));
|
||||||
}
|
}
|
||||||
@ -133,6 +137,7 @@ namespace app {
|
|||||||
ScaleMode m_scaleMode;
|
ScaleMode m_scaleMode;
|
||||||
bool m_ignoreEmptyCels;
|
bool m_ignoreEmptyCels;
|
||||||
Items m_documents;
|
Items m_documents;
|
||||||
|
std::string m_filenameFormat;
|
||||||
|
|
||||||
DISABLE_COPYING(DocumentExporter);
|
DISABLE_COPYING(DocumentExporter);
|
||||||
};
|
};
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "app/file/file_format.h"
|
#include "app/file/file_format.h"
|
||||||
#include "app/file/file_formats_manager.h"
|
#include "app/file/file_formats_manager.h"
|
||||||
#include "app/file/format_options.h"
|
#include "app/file/format_options.h"
|
||||||
|
#include "app/filename_formatter.h"
|
||||||
#include "app/modules/gui.h"
|
#include "app/modules/gui.h"
|
||||||
#include "app/modules/palettes.h"
|
#include "app/modules/palettes.h"
|
||||||
#include "app/ui/status_bar.h"
|
#include "app/ui/status_bar.h"
|
||||||
@ -122,7 +123,8 @@ int save_document(Context* context, doc::Document* document)
|
|||||||
ASSERT(dynamic_cast<app::Document*>(document));
|
ASSERT(dynamic_cast<app::Document*>(document));
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
FileOp* fop = fop_to_save_document(context, static_cast<app::Document*>(document));
|
FileOp* fop = fop_to_save_document(context,
|
||||||
|
static_cast<app::Document*>(document), "");
|
||||||
if (!fop)
|
if (!fop)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -235,7 +237,7 @@ done:;
|
|||||||
return fop;
|
return fop;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileOp* fop_to_save_document(Context* context, Document* document)
|
FileOp* fop_to_save_document(Context* context, Document* document, const char* fn_format_arg)
|
||||||
{
|
{
|
||||||
FileOp *fop;
|
FileOp *fop;
|
||||||
bool fatal;
|
bool fatal;
|
||||||
@ -359,26 +361,59 @@ FileOp* fop_to_save_document(Context* context, Document* document)
|
|||||||
if (fop->format->support(FILE_SUPPORT_SEQUENCES)) {
|
if (fop->format->support(FILE_SUPPORT_SEQUENCES)) {
|
||||||
fop_prepare_for_sequence(fop);
|
fop_prepare_for_sequence(fop);
|
||||||
|
|
||||||
// To save one frame
|
std::string fn = fop->document->filename();
|
||||||
if (fop->document->sprite()->totalFrames() == 1) {
|
std::string fn_format = fn_format_arg;
|
||||||
fop->seq.filename_list.push_back(fop->document->filename());
|
bool default_format = false;
|
||||||
}
|
|
||||||
// To save more frames
|
|
||||||
else {
|
|
||||||
char left[256], right[256];
|
|
||||||
int width, start_from;
|
|
||||||
|
|
||||||
start_from = split_filename(fop->document->filename().c_str(), left, right, &width);
|
if (fn_format.empty()) {
|
||||||
if (start_from < 0) {
|
if (fop->document->sprite()->totalFrames() == 1)
|
||||||
start_from = 1;
|
fn_format = "{fullname}";
|
||||||
width = 1;
|
else {
|
||||||
|
fn_format = "{path}/{title}{frame}.{extension}";
|
||||||
|
default_format = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save one frame
|
||||||
|
if (fop->document->sprite()->totalFrames() == 1) {
|
||||||
|
fn = filename_formatter(fn_format, fn);
|
||||||
|
fop->seq.filename_list.push_back(fn);
|
||||||
|
}
|
||||||
|
// Save multiple frames
|
||||||
|
else {
|
||||||
|
int width = 0;
|
||||||
|
int start_from = 0;
|
||||||
|
|
||||||
|
if (default_format) {
|
||||||
|
char left[256], right[256];
|
||||||
|
start_from = split_filename(fn.c_str(), left, right, &width);
|
||||||
|
if (start_from < 0) {
|
||||||
|
start_from = 1;
|
||||||
|
width = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fn = left;
|
||||||
|
fn += right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<char> buf(32);
|
||||||
|
std::sprintf(&buf[0], "{frame%0*d}", width, 0);
|
||||||
|
if (default_format)
|
||||||
|
fn_format = set_frame_format(fn_format, &buf[0]);
|
||||||
|
else if (fop->document->sprite()->totalFrames() > 1)
|
||||||
|
fn_format = add_frame_format(fn_format, &buf[0]);
|
||||||
|
|
||||||
|
printf("start_from = %d\n", start_from);
|
||||||
|
printf("fn_format = %s\n", fn_format.c_str());
|
||||||
|
printf("fn = %s\n", fn.c_str());
|
||||||
|
|
||||||
for (FrameNumber frame(0); frame<fop->document->sprite()->totalFrames(); ++frame) {
|
for (FrameNumber frame(0); frame<fop->document->sprite()->totalFrames(); ++frame) {
|
||||||
// Get the name for this frame
|
std::string frame_fn =
|
||||||
char buf[4096];
|
filename_formatter(fn_format, fn, "", start_from+frame);
|
||||||
sprintf(buf, "%s%0*d%s", left, width, start_from+frame, right);
|
|
||||||
fop->seq.filename_list.push_back(buf);
|
printf("frame_fn = %s\n", frame_fn.c_str());
|
||||||
|
fop->seq.filename_list.push_back(frame_fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ namespace app {
|
|||||||
// Low-level routines to load/save documents.
|
// Low-level routines to load/save documents.
|
||||||
|
|
||||||
FileOp* fop_to_load_document(Context* context, const char* filename, int flags);
|
FileOp* fop_to_load_document(Context* context, const char* filename, int flags);
|
||||||
FileOp* fop_to_save_document(Context* context, Document* document);
|
FileOp* fop_to_save_document(Context* context, Document* document, const char* fn_format);
|
||||||
void fop_operate(FileOp* fop, IFileOpProgress* progress);
|
void fop_operate(FileOp* fop, IFileOpProgress* progress);
|
||||||
void fop_done(FileOp* fop);
|
void fop_done(FileOp* fop);
|
||||||
void fop_stop(FileOp* fop);
|
void fop_stop(FileOp* fop);
|
||||||
|
105
src/app/filename_formatter.cpp
Normal file
105
src/app/filename_formatter.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2015 David Capello
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "app/filename_formatter.h"
|
||||||
|
|
||||||
|
#include "base/convert_to.h"
|
||||||
|
#include "base/path.h"
|
||||||
|
#include "base/replace_string.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
std::string filename_formatter(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& filename,
|
||||||
|
const std::string& layerName,
|
||||||
|
int frame, bool replaceFrame)
|
||||||
|
{
|
||||||
|
std::string output = format;
|
||||||
|
base::replace_string(output, "{fullname}", filename);
|
||||||
|
base::replace_string(output, "{path}", base::get_file_path(filename));
|
||||||
|
base::replace_string(output, "{name}", base::get_file_name(filename));
|
||||||
|
base::replace_string(output, "{title}", base::get_file_title(filename));
|
||||||
|
base::replace_string(output, "{extension}", base::get_file_extension(filename));
|
||||||
|
base::replace_string(output, "{layer}", layerName);
|
||||||
|
|
||||||
|
if (replaceFrame) {
|
||||||
|
size_t i = output.find("{frame");
|
||||||
|
if (i != std::string::npos) {
|
||||||
|
size_t j = output.find("}", i+6);
|
||||||
|
if (j != std::string::npos) {
|
||||||
|
std::string from = output.substr(i, j - i + 1);
|
||||||
|
if (frame >= 0) {
|
||||||
|
std::vector<char> to(32);
|
||||||
|
int offset = std::strtol(from.c_str()+6, NULL, 10);
|
||||||
|
|
||||||
|
std::sprintf(&to[0], "%0*d", (int(j)-int(i+6)), frame + offset);
|
||||||
|
base::replace_string(output, from, &to[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
base::replace_string(output, from, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string set_frame_format(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& newFrameFormat)
|
||||||
|
{
|
||||||
|
std::string output = format;
|
||||||
|
|
||||||
|
size_t i = output.find("{frame");
|
||||||
|
if (i != std::string::npos) {
|
||||||
|
size_t j = output.find("}", i+6);
|
||||||
|
if (j != std::string::npos) {
|
||||||
|
output.replace(i, j - i + 1, newFrameFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string add_frame_format(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& newFrameFormat)
|
||||||
|
{
|
||||||
|
std::string output = format;
|
||||||
|
|
||||||
|
size_t i = output.find("{frame");
|
||||||
|
if (i == std::string::npos) {
|
||||||
|
output =
|
||||||
|
base::join_path(
|
||||||
|
base::get_file_path(format),
|
||||||
|
base::get_file_title(format))
|
||||||
|
+ newFrameFormat + "." +
|
||||||
|
base::get_file_extension(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace app
|
44
src/app/filename_formatter.h
Normal file
44
src/app/filename_formatter.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2015 David Capello
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef APP_FILENAME_FORMATTER_H_INCLUDED
|
||||||
|
#define APP_FILENAME_FORMATTER_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
|
||||||
|
std::string filename_formatter(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& filename,
|
||||||
|
const std::string& layerName = "",
|
||||||
|
int frame = -1,
|
||||||
|
bool replaceFrame = true);
|
||||||
|
|
||||||
|
std::string set_frame_format(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& newFrameFormat);
|
||||||
|
|
||||||
|
std::string add_frame_format(
|
||||||
|
const std::string& format,
|
||||||
|
const std::string& newFrameFormat);
|
||||||
|
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
142
src/app/filename_formatter_tests.cpp
Normal file
142
src/app/filename_formatter_tests.cpp
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* Aseprite
|
||||||
|
* Copyright (C) 2001-2015 David Capello
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "app/filename_formatter.h"
|
||||||
|
|
||||||
|
#include "base/path.h"
|
||||||
|
|
||||||
|
using namespace app;
|
||||||
|
|
||||||
|
TEST(FilenameFormatter, Basic)
|
||||||
|
{
|
||||||
|
EXPECT_EQ("C:/temp/file.png",
|
||||||
|
filename_formatter("{fullname}",
|
||||||
|
"C:/temp/file.png"));
|
||||||
|
|
||||||
|
EXPECT_EQ("file.png",
|
||||||
|
filename_formatter("{name}",
|
||||||
|
"C:/temp/file.png"));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/other.png",
|
||||||
|
filename_formatter("{path}/other.png",
|
||||||
|
"C:/temp/file.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FilenameFormatter, WithoutFrame)
|
||||||
|
{
|
||||||
|
EXPECT_EQ("C:/temp/file.png",
|
||||||
|
filename_formatter("{path}/{title}.png",
|
||||||
|
"C:/temp/file.ase"));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file.png",
|
||||||
|
filename_formatter("{path}/{title}{frame}.{extension}",
|
||||||
|
"C:/temp/file.png"));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file{frame}.png",
|
||||||
|
filename_formatter("{path}/{title}{frame}.{extension}",
|
||||||
|
"C:/temp/file.png", "", -1, false));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file (Background).png",
|
||||||
|
filename_formatter("{path}/{title} ({layer}).{extension}",
|
||||||
|
"C:/temp/file.png", "Background"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FilenameFormatter, WithFrame)
|
||||||
|
{
|
||||||
|
EXPECT_EQ("C:/temp/file0.png",
|
||||||
|
filename_formatter("{path}/{title}{frame}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file1.png",
|
||||||
|
filename_formatter("{path}/{title}{frame}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 1));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file10.png",
|
||||||
|
filename_formatter("{path}/{title}{frame}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 10));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file0.png",
|
||||||
|
filename_formatter("{path}/{title}{frame0}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file1.png",
|
||||||
|
filename_formatter("{path}/{title}{frame1}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file2.png",
|
||||||
|
filename_formatter("{path}/{title}{frame1}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 1));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file00.png",
|
||||||
|
filename_formatter("{path}/{title}{frame00}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file01.png",
|
||||||
|
filename_formatter("{path}/{title}{frame01}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file002.png",
|
||||||
|
filename_formatter("{path}/{title}{frame000}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 2));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file0032.png",
|
||||||
|
filename_formatter("{path}/{title}{frame0032}.{extension}",
|
||||||
|
"C:/temp/file.png", "", 0));
|
||||||
|
|
||||||
|
EXPECT_EQ("C:/temp/file-Background-2.png",
|
||||||
|
filename_formatter("{path}/{title}-{layer}-{frame}.{extension}",
|
||||||
|
"C:/temp/file.png", "Background", 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SetFrameFormat, Tests)
|
||||||
|
{
|
||||||
|
EXPECT_EQ("{path}/{title}{frame1}.{extension}",
|
||||||
|
set_frame_format("{path}/{title}{frame}.{extension}",
|
||||||
|
"{frame1}"));
|
||||||
|
|
||||||
|
EXPECT_EQ("{path}/{title}{frame01}.{extension}",
|
||||||
|
set_frame_format("{path}/{title}{frame}.{extension}",
|
||||||
|
"{frame01}"));
|
||||||
|
|
||||||
|
EXPECT_EQ("{path}/{title}{frame}.{extension}",
|
||||||
|
set_frame_format("{path}/{title}{frame01}.{extension}",
|
||||||
|
"{frame}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AddFrameFormat, Tests)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(base::fix_path_separators("{path}/{title}{frame001}.{extension}"),
|
||||||
|
add_frame_format("{path}/{title}.{extension}",
|
||||||
|
"{frame001}"));
|
||||||
|
|
||||||
|
EXPECT_EQ("{path}/{title}{frame1}.{extension}",
|
||||||
|
add_frame_format("{path}/{title}{frame1}.{extension}",
|
||||||
|
"{frame001}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
@ -31,6 +31,7 @@ set(BASE_SOURCES
|
|||||||
mutex.cpp
|
mutex.cpp
|
||||||
path.cpp
|
path.cpp
|
||||||
program_options.cpp
|
program_options.cpp
|
||||||
|
replace_string.cpp
|
||||||
serialization.cpp
|
serialization.cpp
|
||||||
sha1.cpp
|
sha1.cpp
|
||||||
sha1_rfc3174.c
|
sha1_rfc3174.c
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2001-2014 David Capello
|
Copyright (c) 2001-2015 David Capello
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Aseprite Base Library
|
# Aseprite Base Library
|
||||||
*Copyright (C) 2001-2013 David Capello*
|
*Copyright (C) 2001-2015 David Capello*
|
||||||
|
|
||||||
> Distributed under [MIT license](LICENSE.txt)
|
> Distributed under [MIT license](LICENSE.txt)
|
||||||
|
|
||||||
|
33
src/base/replace_string.cpp
Normal file
33
src/base/replace_string.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Aseprite Base Library
|
||||||
|
// Copyright (c) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "base/replace_string.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
|
void replace_string(
|
||||||
|
std::string& subject,
|
||||||
|
const std::string& replace_this,
|
||||||
|
const std::string& with_that)
|
||||||
|
{
|
||||||
|
if (replace_this.empty()) // Do nothing case
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (true) {
|
||||||
|
i = subject.find(replace_this, i);
|
||||||
|
if (i == std::string::npos)
|
||||||
|
break;
|
||||||
|
subject.replace(i, replace_this.size(), with_that);
|
||||||
|
i += with_that.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace base
|
22
src/base/replace_string.h
Normal file
22
src/base/replace_string.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Aseprite Base Library
|
||||||
|
// Copyright (c) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifndef BASE_REPLACE_STRING_H_INCLUDED
|
||||||
|
#define BASE_REPLACE_STRING_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
|
||||||
|
void replace_string(
|
||||||
|
std::string& subject,
|
||||||
|
const std::string& replace_this,
|
||||||
|
const std::string& with_that);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
31
src/base/replace_string_tests.cpp
Normal file
31
src/base/replace_string_tests.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Aseprite Base Library
|
||||||
|
// Copyright (c) 2001-2015 David Capello
|
||||||
|
//
|
||||||
|
// This file is released under the terms of the MIT license.
|
||||||
|
// Read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "base/replace_string.h"
|
||||||
|
|
||||||
|
inline std::string rs(const std::string& s, const std::string& a, const std::string& b) {
|
||||||
|
std::string res = s;
|
||||||
|
base::replace_string(res, a, b);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ReplaceString, Basic)
|
||||||
|
{
|
||||||
|
EXPECT_EQ("", rs("", "", ""));
|
||||||
|
EXPECT_EQ("aa", rs("ab", "b", "a"));
|
||||||
|
EXPECT_EQ("abc", rs("accc", "cc", "b"));
|
||||||
|
EXPECT_EQ("abb", rs("acccc", "cc", "b"));
|
||||||
|
EXPECT_EQ("aabbbbaabbbb", rs("aabbaabb", "bb", "bbbb"));
|
||||||
|
EXPECT_EQ("123123123", rs("111", "1", "123"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user