С точки зрения чистой архитектуры стоило бы переложить интерфейсы туда, где лежат их реализации ( в одну директорию), но добавить в каждый слой, подслой core (т. е. ядро именно для этого слоя), куда бы мы и положили интерфейсы?Можно хоть так хоть так. Кто-то кладет все "вертикально" (все слои одного домена), кто-то "горизонтально" (по слоям). У обоих подходов есть плюсы и минусы.
2) класс, ответственный за конвертацию пользовательского объекта в словарь и обратноПридумают же тащить джаву в питон... По пункту 2 достаточно описать Protocol и просто реализовывать методы в классе без всей этой ментальной гимнастики. По 3 пункту вообще не понимаю в чем смысл целого класса чтобы формировать id, но как будто достаточно просто создать функцию и при необходимости заменить ее реализацию.
3) класс, ответственный за то, по какому алгоритму будет формироваться новый id для добавления записи в бд;
NOTIFICATION.FILESAVED, на которое можно повесить git add и git commit. Отдельный watcher или NppExec для этого не нужен.Plugins → Plugins Admin....Plugins → PythonScript → Configuration....ATSTARTUP. Заодно полезно включить Automatically open console on error, чтобы ошибки скрипта сразу были видны.Plugins → PythonScript → Scripts и startup (User). Если пользовательского startup.py ещё нет — создать через Plugins → PythonScript → New Script файл с именем startup.py.from Npp import notepad, NOTIFICATION
import os
import subprocess
import datetime
def on_save(args):
filename = notepad.getBufferFilename(args["bufferID"])
file_dir = os.path.dirname(filename)
try:
repo = subprocess.check_output([
"git", "-C", file_dir,
"rev-parse", "--show-toplevel"
]).strip()
except subprocess.CalledProcessError:
return
rel_file = os.path.relpath(filename, repo)
subprocess.call([
"git", "-C", repo,
"add", "--", rel_file
])
changed = subprocess.call([
"git", "-C", repo,
"diff", "--cached", "--quiet",
"--", rel_file
])
if changed != 0:
message = "autosave " + datetime.datetime.now().strftime(
"%Y-%m-%d %H:%M:%S"
)
subprocess.call([
"git", "-C", repo,
"commit",
"-m", message,
"--", rel_file
])
notepad.callback(on_save, [NOTIFICATION.FILESAVED])git rev-parse --show-toplevel определяет его Git-репозиторий;git должен быть установлен и доступен через PATH, а файл должен находиться внутри уже созданного Git-репозитория.Settings → Preferences → Backup → Backup on save → Verbose backuppush — это история версий, но не полноценный backup. При потере диска вместе с рабочей папкой пропадёт и каталог .git. Если нужна именно резервная копия, репозиторий надо периодически отправлять во внешнее хранилище. $var = Dire::{$string};$var = constant(Dire::class . '::' . $string);$var = eval('return Dire::' . $string . ';'); enum Dire: string {
case Left = 'Left';
case Right = 'Right';
}
$string = 'Left';
$const = Dire::class . '::' . $string;
$var = defined($const) ? constant($const) : null;
var_dump($var); // enum(Dire::Left)enum Dire: string {
case Left = 'Left';
case Right = 'Right';
public static function tryFromName(string $name): ?self
{
foreach (self::cases() as $case) {
if ($case->name === $name) {
return $case;
}
}
return null;
}
}
$string = 'Left';
$var = Dire::tryFromName($string);
var_dump($var); // enum(Dire::Left)enum Dire: string {
case Left = 'Left';
case Right = 'Right';
}
$string = 'Left';
$refEnum = new ReflectionEnum(Dire::class);
$var = $refEnum->hasCase($string) ? $refEnum->getConstant($string) : null;
var_dump($var); // enum(Dire::Left) sudo efibootmgr --create --disk /dev/sdX --part N --loader /EFI/GRUB/grubx64.efi --label "grub", диск и номер раздела N смотри через lsblk. после этого пункт вернётся и в Boot Priority При старте экран чёрный (так и задумано на этом этапе), но клавиатура реагирует на клавишу ESC — код отрабатывает корректно.
Прерывания будто блокируются после первого-второго вызова.
dummy_handler_asm, который вызывается по таймеру, но не завершается отправкой кода окончания обработки прерывания в PIC.diff --git a/system/drivers/interrupts.asm b/system/drivers/interrupts.asm
index 75ea06c4bc2f..17ac87fa6b06 100644
--- a/system/drivers/interrupts.asm
+++ b/system/drivers/interrupts.asm
@@ -98,5 +98,7 @@ dummy_handler_asm:
push rax
mov rax, 0xFEE000B0
mov dword [rax], 0
+ mov al, 0x20
+ out 0x20, al
pop rax
iretqbs->AllocatePages(2, 4, ...), а 2 -- это AllocateAddress, т.е. запрос на выделение памяти по фиксированному тобой адресу. У меня этот код сразу возвращает ошибку, а вот bs->AllocatePages(0, 4, ...) -- работает:diff --git a/boot/bootloader.c b/boot/bootloader.c
index 377e907c1728..5ae82dca7fc0 100644
--- a/boot/bootloader.c
+++ b/boot/bootloader.c
@@ -59,7 +59,7 @@ EFIAPI long long efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
// 1. Выделяем память под скрытый буфер экрана (1024 * 768 * 4 байта = 3145728 байт = 768 страниц по 4КБ)
unsigned long long v_buffer_addr = 0;
// 2 = EfiAllocateAnyPages, 4 = EfiRuntimeServicesData (чтобы ядро гарантированно видело эту память)
- long long status = bs->AllocatePages(2, 4, 768, &v_buffer_addr);
+ long long status = bs->AllocatePages(0, 4, 768, &v_buffer_addr);
if (status != 0) {
while(1) { __asm__ __volatile__("hlt"); }
}
@@ -85,7 +85,7 @@ EFIAPI long long efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
unsigned long long map_buffer = 0;
// Выделяем временную память под саму карту памяти (округлим map_size до страниц)
- bs->AllocatePages(2, 4, (map_size / 4096) + 1, &map_buffer);
+ bs->AllocatePages(0, 4, (map_size / 4096) + 1, &map_buffer);
// Получаем финальную карту памяти и MapKey
status = bs->GetMemoryMap(&map_size, (void*)map_buffer, &map_key, &desc_size, &desc_ver);
И даже в многоступенчатых составных ЭП можно обходиться без этих резисторов:
GetDC(nullptr) уже выдает виртуальный дисплей со всеми мониторами. Потом через EnumDisplayDevices можно получить координаты нужного вам дисплея и обрезать по ним: https://source.chromium.org/chromium/chromium/src/...