From d55070754d6ebb288f738136ec6c91ab010b6298 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Wed, 12 Sep 2012 21:44:27 +0200 Subject: [PATCH] settings: support customizable tags separator --- doc/config | 2 ++ doc/ncmpcpp.1 | 3 +++ src/actions.cpp | 2 +- src/browser.cpp | 4 ++-- src/cmdargs.cpp | 2 +- src/display.cpp | 6 +++--- src/lyrics.cpp | 4 ++-- src/media_library.cpp | 5 +++-- src/mutable_song.h | 2 +- src/playlist.cpp | 8 ++++---- src/playlist_editor.cpp | 4 ++-- src/search_engine.cpp | 4 ++-- src/settings.cpp | 6 ++++++ src/settings.h | 1 + src/song.cpp | 16 ++++++++-------- src/song.h | 6 +++--- src/song_info.cpp | 2 +- src/status.cpp | 8 ++++---- src/tag_editor.cpp | 14 +++++++------- src/tiny_tag_editor.cpp | 7 ++++--- src/utility/comparators.cpp | 4 ++-- 21 files changed, 62 insertions(+), 48 deletions(-) diff --git a/doc/config b/doc/config index 064be27a..f9274fe0 100644 --- a/doc/config +++ b/doc/config @@ -429,6 +429,8 @@ # #empty_tag_marker = "" # +#tags_separator = " | " +# #tag_editor_extended_numeration = "no" # #media_library_display_date = "yes" diff --git a/doc/ncmpcpp.1 b/doc/ncmpcpp.1 index 136910f6..b03f68f3 100644 --- a/doc/ncmpcpp.1 +++ b/doc/ncmpcpp.1 @@ -348,6 +348,9 @@ Default tag type for left column in media library. Legend for possible letters i .B empty_tag_marker = TEXT Text that will be displayed, if requested tag is not set. .TP +.B tags_separator = TEXT +Separator that is placed between tags. Also interpreted by tag editor which splits input string into separate tags using it. +.TP .B empty_tag_color = COLOR Color of empty tag marker. .TP diff --git a/src/actions.cpp b/src/actions.cpp index 44a86001..f9b55a0a 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -1362,7 +1362,7 @@ void EditLibraryTag::Run() for (auto s = songs.begin(); s != songs.end(); ++s) { MPD::MutableSong es = *s; - es.setTags(set, new_tag); + es.setTags(set, new_tag, Config.tags_separator); Statusbar::msg("Updating tags in \"%s\"...", es.getName().c_str()); std::string path = Config.mpd_music_dir + es.getURI(); if (!TagEditor::WriteTags(es)) diff --git a/src/browser.cpp b/src/browser.cpp index 8d3fa390..463e9929 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -616,9 +616,9 @@ std::string ItemToString(const MPD::Item &item) break; case MPD::itSong: if (Config.columns_in_browser) - result = item.song->toString(Config.song_in_columns_to_string_format); + result = item.song->toString(Config.song_in_columns_to_string_format, Config.tags_separator); else - result = item.song->toString(Config.song_list_format_dollar_free); + result = item.song->toString(Config.song_list_format_dollar_free, Config.tags_separator); break; case MPD::itPlaylist: result = Config.browser_playlist_prefix.str() + getBasename(item.name); diff --git a/src/cmdargs.cpp b/src/cmdargs.cpp index 0e458557..9367ff12 100644 --- a/src/cmdargs.cpp +++ b/src/cmdargs.cpp @@ -189,7 +189,7 @@ void ParseArgv(int argc, char **argv) } } std::cout << IConv::utf8ToLocale( - Mpd.GetCurrentlyPlayingSong().toString(now_playing_format)) << "\n"; + Mpd.GetCurrentlyPlayingSong().toString(now_playing_format, Config.tags_separator)) << "\n"; } exit(0); } diff --git a/src/display.cpp b/src/display.cpp index c69cd21e..19a3cf62 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -109,7 +109,7 @@ void showSongs(NC::Menu &menu, const MPD::Song &s, HasSongs &screen, const st setProperties(menu, s, screen, separate_albums, is_now_playing, is_selected, discard_colors); size_t y = menu.getY(); - std::string line = s.toString(format, "$"); + std::string line = s.toString(format, Config.tags_separator, "$"); for (auto it = line.begin(); it != line.end(); ++it) { if (*it == '$') @@ -223,7 +223,7 @@ void showSongsInColumns(NC::Menu &menu, const MPD::Song &s, HasSongs &screen) for (size_t i = 0; i < it->type.length(); ++i) { MPD::Song::GetFunction get = charToGetFunction(it->type[i]); - tag = ToWString(get ? s.getTags(get) : ""); + tag = ToWString(get ? s.getTags(get, Config.tags_separator) : ""); if (!tag.empty()) break; } @@ -365,7 +365,7 @@ void Display::Tags(NC::Menu &menu) size_t i = myTagEditor->TagTypes->choice(); if (i < 11) { - ShowTag(menu, s.getTags(SongInfo::Tags[i].Get)); + ShowTag(menu, s.getTags(SongInfo::Tags[i].Get, Config.tags_separator)); } else if (i == 12) { diff --git a/src/lyrics.cpp b/src/lyrics.cpp index e71282b9..f222910a 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -152,7 +152,7 @@ void Lyrics::SwitchTo() std::wstring Lyrics::Title() { std::wstring result = L"Lyrics: "; - result += Scroller(ToWString(itsSong.toString("{%a - %t}")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length())); + result += Scroller(ToWString(itsSong.toString("{%a - %t}", ", ")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length())); return result; } @@ -175,7 +175,7 @@ void Lyrics::DownloadInBackground(const MPD::Song &s) f.close(); return; } - Statusbar::msg("Fetching lyrics for \"%s\"...", s.toString(Config.song_status_format_no_colors).c_str()); + Statusbar::msg("Fetching lyrics for \"%s\"...", s.toString(Config.song_status_format_no_colors, Config.tags_separator).c_str()); MPD::Song *s_copy = new MPD::Song(s); pthread_mutex_lock(&itsDIBLock); diff --git a/src/media_library.cpp b/src/media_library.cpp index 3a664d2c..fe6be16e 100644 --- a/src/media_library.cpp +++ b/src/media_library.cpp @@ -85,7 +85,8 @@ public: }}), m_cmp(std::locale(), Config.ignore_leading_the) { } bool operator()(const MPD::Song &a, const MPD::Song &b) { for (auto get = m_gets.begin(); get != m_gets.end(); ++get) { - int ret = m_cmp(a.getTags(*get), b.getTags(*get)); + int ret = m_cmp(a.getTags(*get, Config.tags_separator), + b.getTags(*get, Config.tags_separator)); if (ret != 0) return ret < 0; } @@ -902,7 +903,7 @@ std::string AlbumToString(const SearchConstraints &sc) std::string SongToString(const MPD::Song &s) { - return s.toString(Config.song_library_format); + return s.toString(Config.song_library_format, Config.tags_separator); } bool TagEntryMatcher(const Regex &rx, const std::string &tag) diff --git a/src/mutable_song.h b/src/mutable_song.h index 4e244303..b73bb479 100644 --- a/src/mutable_song.h +++ b/src/mutable_song.h @@ -63,7 +63,7 @@ struct MutableSong : public Song virtual unsigned getDuration() const; void setDuration(unsigned duration); - void setTags(SetFunction set, const std::string &value, const std::string &delimiter = ""); + void setTags(SetFunction set, const std::string &value, const std::string &delimiter); bool isModified() const; void clearModifications(); diff --git a/src/playlist.cpp b/src/playlist.cpp index 71f72d71..5e56e4af 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -203,7 +203,7 @@ void Playlist::EnterPressed() std::function iter_swap, quick_sort; auto song_cmp = [&cmp](const MPD::Song &a, const MPD::Song &b) -> bool { for (size_t i = 0; i < SortOptions; ++i) - if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second))) + if (int ret = cmp(a.getTags((*SortDialog)[i].value().second, Config.tags_separator), b.getTags((*SortDialog)[i].value().second, Config.tags_separator))) return ret < 0; return a.getPosition() < b.getPosition(); }; @@ -518,7 +518,7 @@ bool Playlist::Add(const MPD::Song &s, bool play, int position) int id = Mpd.AddSong(s, position); if (id >= 0) { - Statusbar::msg("Added to playlist: %s", s.toString(Config.song_status_format_no_colors).c_str()); + Statusbar::msg("Added to playlist: %s", s.toString(Config.song_status_format_no_colors, Config.tags_separator).c_str()); if (play) Mpd.PlayID(id); return true; @@ -621,9 +621,9 @@ std::string songToString(const MPD::Song &s) { std::string result; if (Config.columns_in_playlist) - result = s.toString(Config.song_in_columns_to_string_format); + result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator); else - result = s.toString(Config.song_list_format_dollar_free); + result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator); return result; } diff --git a/src/playlist_editor.cpp b/src/playlist_editor.cpp index 0ab0ae06..5db14da4 100644 --- a/src/playlist_editor.cpp +++ b/src/playlist_editor.cpp @@ -521,9 +521,9 @@ std::string SongToString(const MPD::Song &s) { std::string result; if (Config.columns_in_playlist_editor) - result = s.toString(Config.song_in_columns_to_string_format); + result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator); else - result = s.toString(Config.song_list_format_dollar_free); + result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator); return result; } diff --git a/src/search_engine.cpp b/src/search_engine.cpp index 1a254078..942e2f2f 100644 --- a/src/search_engine.cpp +++ b/src/search_engine.cpp @@ -588,9 +588,9 @@ std::string SEItemToString(const SEItem &ei) if (ei.isSong()) { if (Config.columns_in_search_engine) - result = ei.song().toString(Config.song_in_columns_to_string_format); + result = ei.song().toString(Config.song_in_columns_to_string_format, Config.tags_separator); else - result = ei.song().toString(Config.song_list_format_dollar_free); + result = ei.song().toString(Config.song_list_format_dollar_free, Config.tags_separator); } else result = ei.buffer().str(); diff --git a/src/settings.cpp b/src/settings.cpp index f955aeeb..421bbaae 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -161,6 +161,7 @@ void Configuration::SetDefaults() { mpd_host = "localhost"; empty_tag = ""; + tags_separator = " | "; song_list_columns_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t|f} (30)[red]{b}"; song_list_format = "{{%a - }{%t}|{$8%f$9}$R{$3(%l)$9}}"; song_list_format_dollar_free = RemoveDollarFormatting(song_list_format); @@ -882,6 +883,11 @@ void Configuration::Read() { empty_tag = v; // is this case empty string is allowed } + else if (name == "tags_separator") + { + if (!v.empty()) + tags_separator = v; + } else if (name == "empty_tag_color") { if (!v.empty()) diff --git a/src/settings.h b/src/settings.h index 2c4c2e07..6f17791b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -64,6 +64,7 @@ struct Configuration std::string visualizer_fifo_path; std::string visualizer_output_name; std::string empty_tag; + std::string tags_separator; std::string song_list_columns_format; std::string song_list_format; std::string song_list_format_dollar_free; diff --git a/src/song.cpp b/src/song.cpp index 6ae89d56..372e4cc5 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -193,7 +193,7 @@ std::string Song::getPriority(unsigned idx) const return unsignedIntTo::apply(getPrio()); } -std::string MPD::Song::getTags(GetFunction f, const std::string &tag_separator) const +std::string MPD::Song::getTags(GetFunction f, const std::string &tags_separator) const { assert(m_song); unsigned idx = 0; @@ -201,7 +201,7 @@ std::string MPD::Song::getTags(GetFunction f, const std::string &tag_separator) for (std::string tag; !(tag = (this->*f)(idx)).empty(); ++idx) { if (!result.empty()) - result += tag_separator; + result += tags_separator; result += tag; } return result; @@ -261,11 +261,11 @@ bool Song::empty() const return m_song.get() == 0; } -std::string Song::toString(const std::string &fmt, const std::string &tag_separator, const std::string &escape_chars) const +std::string Song::toString(const std::string &fmt, const std::string &tags_separator, const std::string &escape_chars) const { assert(m_song); std::string::const_iterator it = fmt.begin(); - return ParseFormat(it, tag_separator, escape_chars); + return ParseFormat(it, tags_separator, escape_chars); } std::string Song::ShowTime(unsigned length) @@ -313,7 +313,7 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt) return true; } -std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tag_separator, +std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tags_separator, const std::string &escape_chars) const { std::string result; @@ -323,7 +323,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string { while (*it == '{') { - std::string tags = ParseFormat(it, tag_separator, escape_chars); + std::string tags = ParseFormat(it, tags_separator, escape_chars); if (!tags.empty()) { has_some_tags = 1; @@ -352,7 +352,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string if (get) { - std::string tag = getTags(get, tag_separator); + std::string tag = getTags(get, tags_separator); if (!escape_chars.empty()) // prepend format escape character to all given chars to escape { for (size_t i = 0; i < escape_chars.length(); ++i) @@ -384,7 +384,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string --brace_counter; } if (*++it == '|') - return ParseFormat(++it, tag_separator, escape_chars); + return ParseFormat(++it, tags_separator, escape_chars); else return ""; } diff --git a/src/song.h b/src/song.h index 6ac19e7c..8338bf39 100644 --- a/src/song.h +++ b/src/song.h @@ -57,7 +57,7 @@ struct Song virtual std::string getLength(unsigned idx = 0) const; virtual std::string getPriority(unsigned idx = 0) const; - virtual std::string getTags(GetFunction f, const std::string &tag_separator = ", ") const; + virtual std::string getTags(GetFunction f, const std::string &tags_separator) const; virtual unsigned getHash() const; virtual unsigned getDuration() const; @@ -71,7 +71,7 @@ struct Song virtual bool empty() const; - virtual std::string toString(const std::string &fmt, const std::string &tag_separator = ", ", + virtual std::string toString(const std::string &fmt, const std::string &tags_separator, const std::string &escape_chars = "") const; static std::string ShowTime(unsigned length); @@ -81,7 +81,7 @@ struct Song private: const char *getTag(mpd_tag_type type, unsigned idx) const; - std::string ParseFormat(std::string::const_iterator &it, const std::string &tag_separator, + std::string ParseFormat(std::string::const_iterator &it, const std::string &tags_separator, const std::string &escape_chars) const; std::shared_ptr m_song; diff --git a/src/song_info.cpp b/src/song_info.cpp index 0978972f..56fe44f5 100644 --- a/src/song_info.cpp +++ b/src/song_info.cpp @@ -134,6 +134,6 @@ void SongInfo::PrepareSong(MPD::Song &s) for (const Metadata *m = Tags; m->Name; ++m) { *w << NC::fmtBold << '\n' << ToWString(m->Name) << L": " << NC::fmtBoldEnd; - ShowTag(*w, s.getTags(m->Get)); + ShowTag(*w, s.getTags(m->Get, Config.tags_separator)); } } diff --git a/src/status.cpp b/src/status.cpp index 5dddeebb..7371e1f3 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -65,7 +65,7 @@ char mpd_db_updating; void drawTitle(const MPD::Song &np) { assert(!np.empty()); - windowTitle(np.toString(Config.song_window_title_format)); + windowTitle(np.toString(Config.song_window_title_format, Config.tags_separator)); } } @@ -345,8 +345,8 @@ void Status::Changes::elapsedTime() } NC::WBuffer first, second; - stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_first_line, "$"))), first); - stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_second_line, "$"))), second); + stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_first_line, Config.tags_separator, "$"))), first); + stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_second_line, Config.tags_separator, "$"))), second); size_t first_len = wideLength(first.str()); size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2; @@ -397,7 +397,7 @@ void Status::Changes::elapsedTime() tracklength += "]"; } NC::WBuffer np_song; - stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.song_status_format, "$"))), np_song); + stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.song_status_format, Config.tags_separator, "$"))), np_song); *wFooter << NC::XY(0, 1) << wclrtoeol << NC::fmtBold << player_state << NC::fmtBoldEnd; np_song.write(*wFooter, playing_song_scroll_begin, wFooter->getWidth()-player_state.length()-tracklength.length(), L" ** "); *wFooter << NC::fmtBold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::fmtBoldEnd; diff --git a/src/tag_editor.cpp b/src/tag_editor.cpp index 7f00d57f..94ec5d23 100644 --- a/src/tag_editor.cpp +++ b/src/tag_editor.cpp @@ -526,19 +526,19 @@ void TagEditor::EnterPressed() { Statusbar::lock(); Statusbar::put() << NC::fmtBold << TagTypes->current().value() << NC::fmtBoldEnd << ": "; - std::string new_tag = wFooter->getString(Tags->current().value().getTags(get)); + std::string new_tag = wFooter->getString(Tags->current().value().getTags(get, Config.tags_separator)); Statusbar::unlock(); for (auto it = EditedSongs.begin(); it != EditedSongs.end(); ++it) - (*it)->setTags(set, new_tag); + (*it)->setTags(set, new_tag, Config.tags_separator); } else if (w == Tags) { Statusbar::lock(); Statusbar::put() << NC::fmtBold << TagTypes->current().value() << NC::fmtBoldEnd << ": "; - std::string new_tag = wFooter->getString(Tags->current().value().getTags(get)); + std::string new_tag = wFooter->getString(Tags->current().value().getTags(get, Config.tags_separator)); Statusbar::unlock(); - if (new_tag != Tags->current().value().getTags(get)) - Tags->current().value().setTags(set, new_tag); + if (new_tag != Tags->current().value().getTags(get, Config.tags_separator)) + Tags->current().value().setTags(set, new_tag, Config.tags_separator); Tags->scroll(NC::wDown); } } @@ -1254,7 +1254,7 @@ MPD::MutableSong::SetFunction IntoSetFunction(char c) std::string GenerateFilename(const MPD::MutableSong &s, const std::string &pattern) { - std::string result = s.toString(pattern); + std::string result = s.toString(pattern, Config.tags_separator); removeInvalidCharsFromFilename(result); return result; } @@ -1306,7 +1306,7 @@ std::string ParseFilename(MPD::MutableSong &s, std::string mask, bool preview) { MPD::MutableSong::SetFunction set = IntoSetFunction(it->first); if (set) - s.setTags(set, it->second); + s.setTags(set, it->second, Config.tags_separator); } else result << "%" << it->first << ": " << it->second << "\n"; diff --git a/src/tiny_tag_editor.cpp b/src/tiny_tag_editor.cpp index 78681fca..c7b5db6c 100644 --- a/src/tiny_tag_editor.cpp +++ b/src/tiny_tag_editor.cpp @@ -111,10 +111,11 @@ void TinyTagEditor::EnterPressed() { size_t pos = option-8; Statusbar::put() << NC::fmtBold << SongInfo::Tags[pos].Name << ": " << NC::fmtBoldEnd; - itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->getString(itsEdited.getTags(SongInfo::Tags[pos].Get))); + itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->getString( + itsEdited.getTags(SongInfo::Tags[pos].Get, Config.tags_separator)), Config.tags_separator); w->at(option).value().clear(); w->at(option).value() << NC::fmtBold << SongInfo::Tags[pos].Name << ':' << NC::fmtBoldEnd << ' '; - ShowTag(w->at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get)); + ShowTag(w->at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get, Config.tags_separator)); } else if (option == 20) { @@ -228,7 +229,7 @@ bool TinyTagEditor::getTags() for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos) { w->at(pos).value() << NC::fmtBold << m->Name << ":" << NC::fmtBoldEnd << ' '; - ShowTag(w->at(pos).value(), itsEdited.getTags(m->Get)); + ShowTag(w->at(pos).value(), itsEdited.getTags(m->Get, Config.tags_separator)); } w->at(20).value() << NC::fmtBold << "Filename:" << NC::fmtBoldEnd << ' ' << itsEdited.getName(); diff --git a/src/utility/comparators.cpp b/src/utility/comparators.cpp index 76cfc53a..0420b006 100644 --- a/src/utility/comparators.cpp +++ b/src/utility/comparators.cpp @@ -74,8 +74,8 @@ bool LocaleBasedItemSorting::operator()(const MPD::Item &a, const MPD::Item &b) result = a.song->getMTime() > b.song->getMTime(); break; case smCustomFormat: - result = m_cmp(a.song->toString(Config.browser_sort_format), - b.song->toString(Config.browser_sort_format)); + result = m_cmp(a.song->toString(Config.browser_sort_format, Config.tags_separator), + b.song->toString(Config.browser_sort_format, Config.tags_separator)); break; } break;