서버에서 yy p로 복붙할 때 바로 입력되지 않음
Waiting for OSC 52 response from the terminal
Wezterm에 있던 걸 복사하기 위해 :set clipboard=unnamedplus 같은 설정을 해놨다면,
neovim이 복붙할 때 nvim 내부가 아니라 클립보드랑 내용을 소통함
로컬로 복사할 때는 nvim이 wezterm에 OSC52로 내용을 보내주는게 가능한데,
역으로 붙여넣을 때 wezterm이 nvim이 있는 서버로 내용을 보내주는게 불가능함
vim.schedule(function()
-- 기본 레지스터(")는 시스템 클립보드에 매핑하지 않음
vim.o.clipboard = ''
-- Neovim 0.10 내장 OSC52 copy 전용 사용
local osc52 = require 'vim.ui.clipboard.osc52'
vim.g.clipboard = {
name = 'osc52',
copy = {
['+'] = osc52.copy '+',
['*'] = osc52.copy '*',
},
-- paste는 굳이 클립보드에 묻지 않고 내부 레지스터(") 내용만 돌려줌
paste = {
['+'] = function()
return { vim.fn.split(vim.fn.getreg('"'), '\n'), vim.fn.getregtype('"') }
end,
['*'] = function()
return { vim.fn.split(vim.fn.getreg('"'), '\n'), vim.fn.getregtype('"') }
end,
},
}
end)
init.lua의 clipboard 설정 코드를 이걸로 바꾸기
로컬에서 서버로 붙여넣을 땐 Ctrl+Shift+V 사용
서버 내부 nvim에서 yy → p 같이 내부 동작할 때도 정상 작동
리눅스는 소켓 조작을 파일 조작과 동일하게 간주.
파일 입출력 함수를 소켓 입출력에 사용 가능.
윈도우는 파일과 소켓을 구분.
파일 디스크립터 : 파일 또는 소켓에 부여된 정수
int open(const char *path, int flag); // 데이터를 읽거나 쓰기 위해 파일 열 때 사용
int close(int fd); // 파일 닫기
ssize_t write(int fd, const void * buf, size_t nbytes); // 파일에 데이터 출력
ssize_t read(int fd, void *buf, size_t nbytes); // 성공 시 수신한 바이트 수
_t 붙는 이유 : 시스템 바뀌어서 비트 바뀌면 typedef 지정된 자료형을 바꿔서 컴파일하여 맞추기 위해 별도 이름 붙인 것

헤더 파일 winsock2.h 포함
#include <winsock2.h>
#include <ws2tcpip.h> // IPv6, getaddrinfo 같은 함수 쓰려면 필요
// #include <windows.h> 보다 반드시 먼저 포함
ws2_32.lib 라이브러리 링크
#pragma comment(lib, "ws2_32.lib")
또는 프로젝트 속성 → Linker → Input → Additional Dependencies에 ws2_32.lib 추가.
이건 visual studio가 아니면 의미가 없음.
직접 컴파일할 땐 gcc server.c util.c -o server.exe -lws2_32 처럼 뒤에 라이브러리 링크를 붙여야 한다.
winsock의 초기화
#include<winsock2.h>
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
윈도우 소켓 초기화 함수
int main(int argc, char* argv[])
{
WSADATA wsaData;
....
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!:);
....
return 0;
}
사용 예시
int WSACleanup(void);
초기화된 라이브러리 해제
SOCKET socket(int af, int type, int protocol); // 소켓 생성
int bind(SOCKET s, const struct sockaddr * name, int namelen); // IP주소와 PORT 번호 할당
int listen(SOCKET s, int backlog); // 소켓이 클라 연결 요청 받을 준비
SOCKET accept(SOCKET s, struct sockaddr * addr, int * addrlen); // 연결 수락
int connect(SOCKET s, const struct sockaddr * name, int namelen); // 연결 요청
int closesocket(SOCKET s); // 소켓 닫기
리눅스는 소켓도 파일 취급. 파일 디스크립터가 할당됨.
윈도우는 파일 생성할 때 핸들 반환. 근데 파일 핸들과 소켓 핸들 구분함.
SOCKET : 정수로 표현되는 소켓 핸들 값 저장 위해 typdef로 재정의된 자료형
int send(SOCKET s, const char * buf, int len, int flags); // 소켓에 데이터 전송 (이건 리눅스에도 존재)
int recv(SOCKET s, const char * buf, int len, int flgas); // 소켓에서 데이터 수신
#include<stdio.h>
#include<stdlib.h>
#include<winsock2.h>
void ErrorHandling(char* message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hServSock, hClntSock;
SOCKADDR_IN servAddr, clntAddr;
int szClntAddr;
char message[] = "Hello World!";
if (argc != 2)
{
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hServSock = socket(PF_INET, SOCK_STREAM, 0);
if (hServSock == INVALID_SOCKET)
ErrorHandling("socket() error");
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(atoi(argv[1]));
if (bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
ErrorHandling("bind() error");
if (listen(hServSock, 5) == SOCKET_ERROR)
ErrorHandling("listen() error");
szClntAddr = sizeof(clntAddr);
hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
if (hClntSock == INVALID_SOCKET)
ErrorHandling("aceept() error");
send(hClntSock, message, sizeof(message), 0);
closesocket(hClntSock);
closesocket(hServSock);
WSACleanup();
return 0;
}
void ErrorHandling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
서버 예제
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char* message);
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAddr;
char message[30];
int strLen;
if(argc != 3)
{
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
ErrorHandling("WSAStartup() error!");
hSocket=socket(PF_INET, SOCK_STREAM, 0);
if(hSocket==INVALID_SOCKET)
ErrorHandling("WSAStartup() error!");
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=inet_addr(argv[1]);
servAddr.sin_port=htons(atoi(argv[2]));
if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
ErrorHandling("connect() error");
strLen=recv(hSocket, message, sizeof(message)-1, 0);
if(strLen==-1)
ErrorHandling("read() error!");
printf("Message from server: %s \n", message);
closesocket(hSocket);
WSACleanup();
return 0;
}
void ErrorHandling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}

Craftring UI
Esc 동작 관련