Show more

Бывают ситуации в когда нужно переключиться из Insert в Normal mode для выполнения одной команды и оставаться в Insert'е. Для выполнение этого есть следующая команда:
<C-o> [команда]

Например, я нахожусь в Insert режиме и мне нужно переместиться на строку выше и редактировать её:
<C-o> k

Снова про

Начал постоянно использовать команду cit - изменение внутри значения тега и удаление до искомого сочетания. Примеры:

1. Есть следующая строка:
<a href="example.com">link to site</a>
курсор находится на символе `h` (в href).
Команда cit (change inside tag - изменить внутри тега) удалит `link to site` и перейдёт в режим вставки для ввода нового значения тега.

2. В следующем json файле:
{
"colors" : [ "red", "green", "blue" ],
"old_colors" : [ "yellow", "grey" ]
}
курсор находится на символе `r` (в слове red). Необходимо в "colors" получить значения "old_colors" и удалить "old_colors".
Команда d/yel и нажатие Enter преобразуют json файл в следущий вид:
{
"colors" : [ "yellow", "grey" ]
}

d - delete (удалить), / - найти, слово начинающееся на yel. Важно заметить, что сам слово которое ищется не удаляется.

Хочу рассказать про интересную конструкцию в C++, которая появилась начиная с 11-го стандарта. Называется using конструктор (встречал еще название Inheriting constructors). Лучше всего её продемонстрировать на примере:

<iostream>
<cstdint>

namespace legacy
{

struct Configuration
{
// Empty for simplicity
};

}

struct Configuration
{
// Empty for simplicity
};

class Server
{
public:
explicit Server(legacy::Configuration)
{
std::cout << "Creating server using legacy config" << std::endl;
}

explicit Server(Configuration)
{
std::cout << "Creating server using config" << std::endl;
}

explicit Server(const std::string& config)
{
std::cout << "Creating server using text config" << std::endl;
}
};

class MockServer : public Server
{
using Server::Server;
};

int main()
{
Server s1{legacy::Configuration{}};
Server s2{Configuration{}};
Server s3{"127.0.0.1:8080"};
std::cout << "----------" << std::endl;

MockServer s4{legacy::Configuration{}};
MockServer s5{Configuration{}};
MockServer s6{"127.0.0.1:8080"};
return 0;
}

Вывод в stdout будет следующий:
Creating server using legacy config
Creating server using config
Creating server using text config
----------
Creating server using legacy config
Creating server using config
Creating server using text config

Есть объект класса Server, в MockServer пишем:
using Server::Server;

В результате объекты класса MockServer можно будет создать с точно такими же конструкторами, как и объекты класса Server, при этом конструкторы явно реализовывать не требуется.

Данная возможность порой очень полезна при написании различных Mock классов в тестах.

Сочетание команд:
f' или F'
;
ci'
для быстрого перемещения внутри строки и её редактирования впечатляет в

Небольшой C++ tip:
Создавать объекты std::optional лучше всего через std::make_optional или вызов emplace(), тогда при создании объекта будет один вызов конструктора.

Написал небольшой пример:
<iostream>
<optional>

class Element
{
public:
Element()
{
std::cout << "Default CNTR" << std::endl;
}
Element(const Element&)
{
std::cout << "Copy CNTR" << std::endl;
}
Element(Element&&)
{
std::cout << "Move CNTR" << std::endl;
}
~Element()
{
std::cout << "DSTR" << std::endl;
}
void TraceData() const
{
std::cout << "[" << posX << ":" << posY << "] " << (visible ? "visible" : "hidden") << "\n";
}
private:
int posX{0};
int posY{0};
bool visible{false};
};

int main()
{
// One constructor call and one destructor call
{
auto element = std::make_optional<Element>();
element->TraceData();
}
std::cout << "-------------\n";
// One constructor call and one destructor call
{
std::optional<Element> element;
auto& elem = element.emplace();
elem.TraceData();
}
std::cout << "-------------\n";
// Two constructor calls and two destructor calls
{
auto element = std::optional<Element>(Element{});
element->TraceData();
}
return 0;
}

Вывод будет следующий:
Default CNTR
[0:0] hidden
DSTR
-------------
Default CNTR
[0:0] hidden
DSTR
-------------
Default CNTR
Move CNTR
DSTR
[0:0] hidden
DSTR

Видно что в третьем случае создался объект через default'ный конструктор, а потом вызвался конструктор переноса и далее лишний деструктор.

Впервые появилась необходимость использования std::call_once в плюсах (до этого как-то не приходилось совсем). Чтобы поэкспериментировать как работает написал небольшой сэмпл:
<iostream>
<mutex>
<chrono>
<thread>
<vector>

std::once_flag once_work_call;
std::mutex cout_lock;

void init()
{
std::this_thread::sleep_for(std::chrono::seconds(5));
std::scoped_lock guard(cout_lock);
std::cout << "init finished" << std::endl;
}

void work(int i)
{
std::call_once(once_work_call, init);
std::scoped_lock guard(cout_lock);
std::cout << "finish work [" << i << "]" << std::endl;
}

int main()
{
std::vector<std::thread> threads;
for(int i = 0; i < 5; ++i)
{
threads.emplace_back(work, i);
}

for(auto& t: threads)
{
t.join();
}

return 0;
}

Пока функция, переданная в std::call_once (в данном случае init), успешно не отработает на одном из потоков, остальные потоки будут ожидать, когда дойдут до вызова std::call_once, понятное дело что вызова std::call_once с одним и тем же флагом (в данном случае once_work_call).

Небольшие успехи в изучении :
- постоянно передвигаюсь внутри строки с помощью
f<символ> - вперёд и далее переход на следующее совпадение символа с помощью ;
F<символ> - назад к интересующему символу.

В целом очень удобно. Раньше я в основном по строке перемещался по словам с помощью w и W - вперёд, b и B - назад.

Плюс заметил за собой, что всё чаще на новую строку перемещаюсь с помощью <номер строки>G.

Одной из ближайших целей как разработчика у меня является научиться эффективно работать в vim. Очень давно хотел приступить к этому, но не получалось выделять достаточно времени (типичная проблема разработчиков). Плюс тяжело в рабочих задачах использовать этот редактор, т.к. значительно снижалась скорость работы и чувствовалась подсознательно нехватка возможностей редактора (просто по причине низкого уровня знакомства с инструментом). Тут нужно понимать, что у vim крайне высокий порог входа и довольно нескоро ты начинаешь им проникаться. Пока вижу что без серьезных предварительных тренировок к использованию в работе не перейти.
Осознал что любимая и самая часто используемая у меня команда это ciw - удаление слова под курсором и переход во вставку. И конечно же перемещение по файлу с помощью <C-u> <C-d>.

Появилось желание вести блог о разработке в виде регулярных, небольших заметок. Надеюсь это поможет самому немного структурировать новые знания, плюс чувствую интерес к тому, чтобы делиться ими с людьми.

Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.