1 /***************************************************************************
2 * Copyright (C) 2008-2017 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include <boost/algorithm/string/trim.hpp>
26 #include "utility/string.h"
27 #include "utility/wide_string.h"
29 BindingsConfiguration Bindings
;
33 void warning(const char *msg
)
35 std::cerr
<< "WARNING: " << msg
<< "\n";
38 NC::Key::Type
stringToKey(const std::string
&s
);
40 NC::Key::Type
stringToSpecialKey(const std::string
&s
)
42 NC::Key::Type result
= NC::Key::None
;
43 if (!s
.compare(0, 4, "ctrl") && s
.length() == 6 && s
[4] == '-')
45 if (s
[5] >= 'a' && s
[5] <= 'z')
46 result
= NC::Key::Ctrl_A
+ (s
[5] - 'a');
48 result
= NC::Key::Ctrl_LeftBracket
;
49 else if (s
[5] == '\\')
50 result
= NC::Key::Ctrl_Backslash
;
52 result
= NC::Key::Ctrl_RightBracket
;
54 result
= NC::Key::Ctrl_Caret
;
56 result
= NC::Key::Ctrl_Underscore
;
58 else if (!s
.compare(0, 3, "alt") && s
.length() > 3 && s
[3] == '-')
60 result
= NC::Key::Alt
| stringToKey(s
.substr(4));
62 else if (!s
.compare(0, 4, "ctrl") && s
.length() > 4 && s
[4] == '-')
64 result
= NC::Key::Ctrl
| stringToKey(s
.substr(5));
66 else if (!s
.compare(0, 5, "shift") && s
.length() > 5 && s
[5] == '-')
68 result
= NC::Key::Shift
| stringToKey(s
.substr(6));
70 else if (!s
.compare("escape"))
71 result
= NC::Key::Escape
;
72 else if (!s
.compare("mouse"))
73 result
= NC::Key::Mouse
;
74 else if (!s
.compare("up"))
76 else if (!s
.compare("down"))
77 result
= NC::Key::Down
;
78 else if (!s
.compare("page_up"))
79 result
= NC::Key::PageUp
;
80 else if (!s
.compare("page_down"))
81 result
= NC::Key::PageDown
;
82 else if (!s
.compare("home"))
83 result
= NC::Key::Home
;
84 else if (!s
.compare("end"))
85 result
= NC::Key::End
;
86 else if (!s
.compare("space"))
87 result
= NC::Key::Space
;
88 else if (!s
.compare("enter"))
89 result
= NC::Key::Enter
;
90 else if (!s
.compare("insert"))
91 result
= NC::Key::Insert
;
92 else if (!s
.compare("delete"))
93 result
= NC::Key::Delete
;
94 else if (!s
.compare("left"))
95 result
= NC::Key::Left
;
96 else if (!s
.compare("right"))
97 result
= NC::Key::Right
;
98 else if (!s
.compare("tab"))
99 result
= NC::Key::Tab
;
100 else if ((s
.length() == 2 || s
.length() == 3) && s
[0] == 'f')
102 int n
= atoi(s
.c_str() + 1);
103 if (n
>= 1 && n
<= 12)
104 result
= NC::Key::F1
+ n
- 1;
106 else if (!s
.compare("backspace"))
107 result
= NC::Key::Backspace
;
111 NC::Key::Type
stringToKey(const std::string
&s
)
113 NC::Key::Type result
= stringToSpecialKey(s
);
114 if (result
== NC::Key::None
)
116 std::wstring ws
= ToWString(s
);
117 if (ws
.length() == 1)
123 template <typename F
>
124 std::shared_ptr
<Actions::BaseAction
> parseActionLine(const std::string
&line
, F error
)
126 std::shared_ptr
<Actions::BaseAction
> result
;
128 for (; i
< line
.size() && !isspace(line
[i
]); ++i
) { }
129 if (i
== line
.size()) // only action name
131 if (line
== "set_visualizer_sample_multiplier")
133 warning("action 'set_visualizer_sample_multiplier' is deprecated"
134 " and will be removed in 0.9");
135 result
= Actions::get_(Actions::Type::Dummy
);
138 result
= Actions::get_(line
);
140 else // there is something else
142 std::string action_name
= line
.substr(0, i
);
143 if (action_name
== "push_character")
145 // push single character into input queue
146 std::string arg
= getEnclosedString(line
, '"', '"', 0);
147 NC::Key::Type k
= stringToSpecialKey(arg
);
148 if (k
!= NC::Key::None
)
149 result
= std::static_pointer_cast
<Actions::BaseAction
>(
150 std::make_shared
<Actions::PushCharacters
>(
152 std::vector
<NC::Key::Type
>{k
}));
154 error() << "invalid character passed to push_character: '" << arg
<< "'\n";
156 else if (action_name
== "push_characters")
158 // push sequence of characters into input queue
159 std::string arg
= getEnclosedString(line
, '"', '"', 0);
162 // if char is signed, erase 1s from char -> int conversion
163 for (auto it
= arg
.begin(); it
!= arg
.end(); ++it
)
165 result
= std::static_pointer_cast
<Actions::BaseAction
>(
166 std::make_shared
<Actions::PushCharacters
>(
168 std::vector
<NC::Key::Type
>{arg
.begin(), arg
.end()}));
171 error() << "empty argument passed to push_characters\n";
173 else if (action_name
== "require_screen")
175 // require screen of given type
176 std::string arg
= getEnclosedString(line
, '"', '"', 0);
177 ScreenType screen_type
= stringToScreenType(arg
);
178 if (screen_type
!= ScreenType::Unknown
)
179 result
= std::static_pointer_cast
<Actions::BaseAction
>(
180 std::make_shared
<Actions::RequireScreen
>(screen_type
));
182 error() << "unknown screen passed to require_screen: '" << arg
<< "'\n";
184 else if (action_name
== "require_runnable")
186 // require that given action is runnable
187 std::string arg
= getEnclosedString(line
, '"', '"', 0);
188 auto action
= Actions::get_(arg
);
190 result
= std::static_pointer_cast
<Actions::BaseAction
>(
191 std::make_shared
<Actions::RequireRunnable
>(action
));
193 error() << "unknown action passed to require_runnable: '" << arg
<< "'\n";
195 else if (action_name
== "run_external_command")
197 std::string command
= getEnclosedString(line
, '"', '"', 0);
198 if (!command
.empty())
199 result
= std::static_pointer_cast
<Actions::BaseAction
>(
200 std::make_shared
<Actions::RunExternalCommand
>(std::move(command
)));
202 error() << "empty command passed to run_external_command\n";
210 NC::Key::Type
readKey(NC::Window
&w
)
212 NC::Key::Type result
= NC::Key::None
;
215 bool alt_pressed
= false;
219 if (input
== NC::Key::None
)
221 if (input
& NC::Key::Alt
)
223 // Complete the key and reapply the mask at the end.
225 input
&= ~NC::Key::Alt
;
227 if (input
> 255) // NC special character
236 size_t conv_res
= mbrtowc(&wc
, tmp
.c_str(), MB_CUR_MAX
, 0);
237 if (conv_res
== size_t(-1)) // incomplete multibyte character
239 else if (conv_res
== size_t(-2)) // garbage character sequence
241 else // character complete
249 result
|= NC::Key::Alt
;
253 std::wstring
keyToWString(const NC::Key::Type key
)
257 if (key
== NC::Key::Tab
)
259 else if (key
== NC::Key::Enter
)
261 else if (key
== NC::Key::Escape
)
263 else if (key
>= NC::Key::Ctrl_A
&& key
<= NC::Key::Ctrl_Z
)
266 result
+= 'A' + (key
- NC::Key::Ctrl_A
);
268 else if (key
== NC::Key::Ctrl_LeftBracket
)
270 else if (key
== NC::Key::Ctrl_Backslash
)
271 result
+= L
"Ctrl-\\";
272 else if (key
== NC::Key::Ctrl_RightBracket
)
274 else if (key
== NC::Key::Ctrl_Caret
)
276 else if (key
== NC::Key::Ctrl_Underscore
)
278 else if (key
& NC::Key::Alt
)
281 result
+= keyToWString(key
& ~NC::Key::Alt
);
283 else if (key
& NC::Key::Ctrl
)
286 result
+= keyToWString(key
& ~NC::Key::Ctrl
);
288 else if (key
& NC::Key::Shift
)
291 result
+= keyToWString(key
& ~NC::Key::Shift
);
293 else if (key
== NC::Key::Space
)
295 else if (key
== NC::Key::Backspace
)
296 result
+= L
"Backspace";
297 else if (key
== NC::Key::Insert
)
299 else if (key
== NC::Key::Delete
)
301 else if (key
== NC::Key::Home
)
303 else if (key
== NC::Key::End
)
305 else if (key
== NC::Key::PageUp
)
307 else if (key
== NC::Key::PageDown
)
308 result
+= L
"PageDown";
309 else if (key
== NC::Key::Up
)
311 else if (key
== NC::Key::Down
)
313 else if (key
== NC::Key::Left
)
315 else if (key
== NC::Key::Right
)
317 else if (key
== NC::Key::EoF
)
319 else if (key
>= NC::Key::F1
&& key
<= NC::Key::F9
)
322 result
+= '1' + (key
- NC::Key::F1
);
324 else if (key
>= NC::Key::F10
&& key
<= NC::Key::F12
)
327 result
+= '0' + (key
- NC::Key::F10
);
330 result
+= std::wstring(1, key
);
335 bool BindingsConfiguration::read(const std::string
&file
)
337 enum class InProgress
{ None
, Command
, Key
};
341 std::ifstream
f(file
);
346 InProgress in_progress
= InProgress::None
;
349 Binding::ActionChain actions
;
351 // def_key specific variables
352 NC::Key::Type key
= NC::Key::None
;
355 // def_command specific variables
356 bool cmd_immediate
= false;
357 std::string cmd_name
;
359 auto error
= [&]() -> std::ostream
& {
360 std::cerr
<< file
<< ":" << line_no
<< ": error: ";
361 in_progress
= InProgress::None
;
366 auto bind_in_progress
= [&]() -> bool {
367 if (in_progress
== InProgress::Command
)
369 if (!actions
.empty())
371 m_commands
.insert(std::make_pair(cmd_name
, Command(std::move(actions
), cmd_immediate
)));
377 error() << "definition of command '" << cmd_name
<< "' cannot be empty\n";
381 else if (in_progress
== InProgress::Key
)
383 if (!actions
.empty())
391 error() << "definition of key '" << strkey
<< "' cannot be empty\n";
398 const char def_command
[] = "def_command";
399 const char def_key
[] = "def_key";
401 while (!f
.eof() && ++line_no
)
404 if (line
.empty() || line
[0] == '#')
407 // beginning of command definition
408 if (!line
.compare(0, const_strlen(def_command
), def_command
))
410 if (!bind_in_progress())
412 in_progress
= InProgress::Command
;
413 cmd_name
= getEnclosedString(line
, '"', '"', 0);
414 if (cmd_name
.empty())
416 error() << "command must have non-empty name\n";
419 if (m_commands
.find(cmd_name
) != m_commands
.end())
421 error() << "redefinition of command '" << cmd_name
<< "'\n";
424 std::string cmd_type
= getEnclosedString(line
, '[', ']', 0);
425 if (cmd_type
== "immediate")
426 cmd_immediate
= true;
427 else if (cmd_type
== "deferred")
428 cmd_immediate
= false;
431 error() << "invalid type of command: '" << cmd_type
<< "'\n";
435 // beginning of key definition
436 else if (!line
.compare(0, const_strlen(def_key
), def_key
))
438 if (!bind_in_progress())
440 in_progress
= InProgress::Key
;
441 strkey
= getEnclosedString(line
, '"', '"', 0);
442 key
= stringToKey(strkey
);
443 if (key
== NC::Key::None
)
445 error() << "invalid key: '" << strkey
<< "'\n";
449 else if (isspace(line
[0])) // name of action to be bound
452 auto action
= parseActionLine(line
, error
);
454 actions
.push_back(action
);
457 error() << "unknown action: '" << line
<< "'\n";
463 error() << "invalid line: '" << line
<< "'\n";
472 bool BindingsConfiguration::read(const std::vector
<std::string
> &binding_paths
)
475 binding_paths
.begin(),
477 [&](const std::string
&binding_path
) {
478 return read(binding_path
);
483 void BindingsConfiguration::generateDefaults()
485 NC::Key::Type k
= NC::Key::None
;
486 bind(NC::Key::EoF
, Actions::Type::Quit
);
487 if (notBound(k
= stringToKey("mouse")))
488 bind(k
, Actions::Type::MouseEvent
);
489 if (notBound(k
= stringToKey("up")))
490 bind(k
, Actions::Type::ScrollUp
);
491 if (notBound(k
= stringToKey("shift-up")))
492 bind(k
, Binding::ActionChain({Actions::get_(Actions::Type::SelectItem
), Actions::get_(Actions::Type::ScrollUp
)}));
493 if (notBound(k
= stringToKey("down")))
494 bind(k
, Actions::Type::ScrollDown
);
495 if (notBound(k
= stringToKey("shift-down")))
496 bind(k
, Binding::ActionChain({Actions::get_(Actions::Type::SelectItem
), Actions::get_(Actions::Type::ScrollDown
)}));
497 if (notBound(k
= stringToKey("[")))
498 bind(k
, Actions::Type::ScrollUpAlbum
);
499 if (notBound(k
= stringToKey("]")))
500 bind(k
, Actions::Type::ScrollDownAlbum
);
501 if (notBound(k
= stringToKey("{")))
502 bind(k
, Actions::Type::ScrollUpArtist
);
503 if (notBound(k
= stringToKey("}")))
504 bind(k
, Actions::Type::ScrollDownArtist
);
505 if (notBound(k
= stringToKey("page_up")))
506 bind(k
, Actions::Type::PageUp
);
507 if (notBound(k
= stringToKey("page_down")))
508 bind(k
, Actions::Type::PageDown
);
509 if (notBound(k
= stringToKey("home")))
510 bind(k
, Actions::Type::MoveHome
);
511 if (notBound(k
= stringToKey("end")))
512 bind(k
, Actions::Type::MoveEnd
);
513 if (notBound(k
= stringToKey("insert")))
514 bind(k
, Actions::Type::SelectItem
);
515 if (notBound(k
= stringToKey("enter")))
517 bind(k
, Actions::Type::EnterDirectory
);
518 bind(k
, Actions::Type::ToggleOutput
);
519 bind(k
, Actions::Type::RunAction
);
520 bind(k
, Actions::Type::PlayItem
);
522 if (notBound(k
= stringToKey("space")))
524 bind(k
, Actions::Type::AddItemToPlaylist
);
525 bind(k
, Actions::Type::ToggleLyricsUpdateOnSongChange
);
526 bind(k
, Actions::Type::ToggleVisualizationType
);
528 if (notBound(k
= stringToKey("delete")))
530 bind(k
, Actions::Type::DeletePlaylistItems
);
531 bind(k
, Actions::Type::DeleteBrowserItems
);
532 bind(k
, Actions::Type::DeleteStoredPlaylist
);
534 if (notBound(k
= stringToKey("right")))
536 bind(k
, Actions::Type::NextColumn
);
537 bind(k
, Actions::Type::SlaveScreen
);
538 bind(k
, Actions::Type::VolumeUp
);
540 if (notBound(k
= stringToKey("+")))
541 bind(k
, Actions::Type::VolumeUp
);
542 if (notBound(k
= stringToKey("left")))
544 bind(k
, Actions::Type::PreviousColumn
);
545 bind(k
, Actions::Type::MasterScreen
);
546 bind(k
, Actions::Type::VolumeDown
);
548 if (notBound(k
= stringToKey("-")))
549 bind(k
, Actions::Type::VolumeDown
);
550 if (notBound(k
= stringToKey(":")))
551 bind(k
, Actions::Type::ExecuteCommand
);
552 if (notBound(k
= stringToKey("tab")))
553 bind(k
, Actions::Type::NextScreen
);
554 if (notBound(k
= stringToKey("shift-tab")))
555 bind(k
, Actions::Type::PreviousScreen
);
556 if (notBound(k
= stringToKey("f1")))
557 bind(k
, Actions::Type::ShowHelp
);
558 if (notBound(k
= stringToKey("1")))
559 bind(k
, Actions::Type::ShowPlaylist
);
560 if (notBound(k
= stringToKey("2")))
562 bind(k
, Actions::Type::ShowBrowser
);
563 bind(k
, Actions::Type::ChangeBrowseMode
);
565 if (notBound(k
= stringToKey("3")))
567 bind(k
, Actions::Type::ShowSearchEngine
);
568 bind(k
, Actions::Type::ResetSearchEngine
);
570 if (notBound(k
= stringToKey("4")))
572 bind(k
, Actions::Type::ShowMediaLibrary
);
573 bind(k
, Actions::Type::ToggleMediaLibraryColumnsMode
);
575 if (notBound(k
= stringToKey("5")))
576 bind(k
, Actions::Type::ShowPlaylistEditor
);
577 if (notBound(k
= stringToKey("6")))
578 bind(k
, Actions::Type::ShowTagEditor
);
579 if (notBound(k
= stringToKey("7")))
580 bind(k
, Actions::Type::ShowOutputs
);
581 if (notBound(k
= stringToKey("8")))
582 bind(k
, Actions::Type::ShowVisualizer
);
583 if (notBound(k
= stringToKey("=")))
584 bind(k
, Actions::Type::ShowClock
);
585 if (notBound(k
= stringToKey("@")))
586 bind(k
, Actions::Type::ShowServerInfo
);
587 if (notBound(k
= stringToKey("s")))
588 bind(k
, Actions::Type::Stop
);
589 if (notBound(k
= stringToKey("p")))
590 bind(k
, Actions::Type::Pause
);
591 if (notBound(k
= stringToKey(">")))
592 bind(k
, Actions::Type::Next
);
593 if (notBound(k
= stringToKey("<")))
594 bind(k
, Actions::Type::Previous
);
595 if (notBound(k
= stringToKey("ctrl-h")))
597 bind(k
, Actions::Type::JumpToParentDirectory
);
598 bind(k
, Actions::Type::ReplaySong
);
600 if (notBound(k
= stringToKey("backspace")))
602 bind(k
, Actions::Type::JumpToParentDirectory
);
603 bind(k
, Actions::Type::ReplaySong
);
605 if (notBound(k
= stringToKey("f")))
606 bind(k
, Actions::Type::SeekForward
);
607 if (notBound(k
= stringToKey("b")))
608 bind(k
, Actions::Type::SeekBackward
);
609 if (notBound(k
= stringToKey("r")))
610 bind(k
, Actions::Type::ToggleRepeat
);
611 if (notBound(k
= stringToKey("z")))
612 bind(k
, Actions::Type::ToggleRandom
);
613 if (notBound(k
= stringToKey("y")))
615 bind(k
, Actions::Type::SaveTagChanges
);
616 bind(k
, Actions::Type::StartSearching
);
617 bind(k
, Actions::Type::ToggleSingle
);
619 if (notBound(k
= stringToKey("R")))
620 bind(k
, Actions::Type::ToggleConsume
);
621 if (notBound(k
= stringToKey("Y")))
622 bind(k
, Actions::Type::ToggleReplayGainMode
);
623 if (notBound(k
= stringToKey("T")))
624 bind(k
, Actions::Type::ToggleAddMode
);
625 if (notBound(k
= stringToKey("|")))
626 bind(k
, Actions::Type::ToggleMouse
);
627 if (notBound(k
= stringToKey("#")))
628 bind(k
, Actions::Type::ToggleBitrateVisibility
);
629 if (notBound(k
= stringToKey("Z")))
630 bind(k
, Actions::Type::Shuffle
);
631 if (notBound(k
= stringToKey("x")))
632 bind(k
, Actions::Type::ToggleCrossfade
);
633 if (notBound(k
= stringToKey("X")))
634 bind(k
, Actions::Type::SetCrossfade
);
635 if (notBound(k
= stringToKey("u")))
636 bind(k
, Actions::Type::UpdateDatabase
);
637 if (notBound(k
= stringToKey("ctrl-s")))
639 bind(k
, Actions::Type::SortPlaylist
);
640 bind(k
, Actions::Type::ToggleBrowserSortMode
);
641 bind(k
, Actions::Type::ToggleMediaLibrarySortMode
);
643 if (notBound(k
= stringToKey("ctrl-r")))
644 bind(k
, Actions::Type::ReversePlaylist
);
645 if (notBound(k
= stringToKey("ctrl-f")))
646 bind(k
, Actions::Type::ApplyFilter
);
647 if (notBound(k
= stringToKey("ctrl-_")))
648 bind(k
, Actions::Type::SelectFoundItems
);
649 if (notBound(k
= stringToKey("/")))
651 bind(k
, Actions::Type::Find
);
652 bind(k
, Actions::Type::FindItemForward
);
654 if (notBound(k
= stringToKey("?")))
656 bind(k
, Actions::Type::Find
);
657 bind(k
, Actions::Type::FindItemBackward
);
659 if (notBound(k
= stringToKey(".")))
660 bind(k
, Actions::Type::NextFoundItem
);
661 if (notBound(k
= stringToKey(",")))
662 bind(k
, Actions::Type::PreviousFoundItem
);
663 if (notBound(k
= stringToKey("w")))
664 bind(k
, Actions::Type::ToggleFindMode
);
665 if (notBound(k
= stringToKey("e")))
667 bind(k
, Actions::Type::EditSong
);
668 bind(k
, Actions::Type::EditLibraryTag
);
669 bind(k
, Actions::Type::EditLibraryAlbum
);
670 bind(k
, Actions::Type::EditDirectoryName
);
671 bind(k
, Actions::Type::EditPlaylistName
);
672 bind(k
, Actions::Type::EditLyrics
);
674 if (notBound(k
= stringToKey("i")))
675 bind(k
, Actions::Type::ShowSongInfo
);
676 if (notBound(k
= stringToKey("I")))
677 bind(k
, Actions::Type::ShowArtistInfo
);
678 if (notBound(k
= stringToKey("g")))
679 bind(k
, Actions::Type::JumpToPositionInSong
);
680 if (notBound(k
= stringToKey("l")))
681 bind(k
, Actions::Type::ShowLyrics
);
682 if (notBound(k
= stringToKey("ctrl-v")))
683 bind(k
, Actions::Type::SelectRange
);
684 if (notBound(k
= stringToKey("v")))
685 bind(k
, Actions::Type::ReverseSelection
);
686 if (notBound(k
= stringToKey("V")))
687 bind(k
, Actions::Type::RemoveSelection
);
688 if (notBound(k
= stringToKey("B")))
689 bind(k
, Actions::Type::SelectAlbum
);
690 if (notBound(k
= stringToKey("a")))
691 bind(k
, Actions::Type::AddSelectedItems
);
692 if (notBound(k
= stringToKey("c")))
694 bind(k
, Actions::Type::ClearPlaylist
);
695 bind(k
, Actions::Type::ClearMainPlaylist
);
697 if (notBound(k
= stringToKey("C")))
699 bind(k
, Actions::Type::CropPlaylist
);
700 bind(k
, Actions::Type::CropMainPlaylist
);
702 if (notBound(k
= stringToKey("m")))
704 bind(k
, Actions::Type::MoveSortOrderUp
);
705 bind(k
, Actions::Type::MoveSelectedItemsUp
);
707 if (notBound(k
= stringToKey("n")))
709 bind(k
, Actions::Type::MoveSortOrderDown
);
710 bind(k
, Actions::Type::MoveSelectedItemsDown
);
712 if (notBound(k
= stringToKey("M")))
713 bind(k
, Actions::Type::MoveSelectedItemsTo
);
714 if (notBound(k
= stringToKey("A")))
715 bind(k
, Actions::Type::Add
);
716 if (notBound(k
= stringToKey("S")))
717 bind(k
, Actions::Type::SavePlaylist
);
718 if (notBound(k
= stringToKey("o")))
719 bind(k
, Actions::Type::JumpToPlayingSong
);
720 if (notBound(k
= stringToKey("G")))
722 bind(k
, Actions::Type::JumpToBrowser
);
723 bind(k
, Actions::Type::JumpToPlaylistEditor
);
725 if (notBound(k
= stringToKey("~")))
726 bind(k
, Actions::Type::JumpToMediaLibrary
);
727 if (notBound(k
= stringToKey("E")))
728 bind(k
, Actions::Type::JumpToTagEditor
);
729 if (notBound(k
= stringToKey("U")))
730 bind(k
, Actions::Type::TogglePlayingSongCentering
);
731 if (notBound(k
= stringToKey("P")))
732 bind(k
, Actions::Type::ToggleDisplayMode
);
733 if (notBound(k
= stringToKey("\\")))
734 bind(k
, Actions::Type::ToggleInterface
);
735 if (notBound(k
= stringToKey("!")))
736 bind(k
, Actions::Type::ToggleSeparatorsBetweenAlbums
);
737 if (notBound(k
= stringToKey("L")))
738 bind(k
, Actions::Type::ToggleLyricsFetcher
);
739 if (notBound(k
= stringToKey("F")))
740 bind(k
, Actions::Type::FetchLyricsInBackground
);
741 if (notBound(k
= stringToKey("alt-l")))
742 bind(k
, Actions::Type::ToggleFetchingLyricsInBackground
);
743 if (notBound(k
= stringToKey("ctrl-l")))
744 bind(k
, Actions::Type::ToggleScreenLock
);
745 if (notBound(k
= stringToKey("`")))
747 bind(k
, Actions::Type::ToggleLibraryTagType
);
748 bind(k
, Actions::Type::RefetchLyrics
);
749 bind(k
, Actions::Type::AddRandomItems
);
751 if (notBound(k
= stringToKey("ctrl-p")))
752 bind(k
, Actions::Type::SetSelectedItemsPriority
);
753 if (notBound(k
= stringToKey("q")))
754 bind(k
, Actions::Type::Quit
);
757 const Command
*BindingsConfiguration::findCommand(const std::string
&name
)
759 const Command
*ptr
= nullptr;
760 auto it
= m_commands
.find(name
);
761 if (it
!= m_commands
.end())
766 BindingsConfiguration::BindingIteratorPair
BindingsConfiguration::get(const NC::Key::Type
&k
)
768 std::pair
<BindingIterator
, BindingIterator
> result
;
769 auto it
= m_bindings
.find(k
);
770 if (it
!= m_bindings
.end()) {
771 result
.first
= it
->second
.begin();
772 result
.second
= it
->second
.end();
774 auto list_end
= m_bindings
.begin()->second
.end();
775 result
.first
= list_end
;
776 result
.second
= list_end
;