레이블이 neovim인 게시물을 표시합니다. 모든 게시물 표시
레이블이 neovim인 게시물을 표시합니다. 모든 게시물 표시

change nvim glibc library path

# rocky8 의 기본 glibc 는 2.28 다.
# glibc 2.28
ldd --version
ldd (GNU libc) 2.28

# 최신 nvim(0.10.x)부터는 glibc 2.29 이상이 필요해 nvim 0.9.5 버전을 사용하고 있었다.
# 그런데 nvim 플러그인에서 에러가 많이 발생해 nvim 0.10.x 으로 교체가 필요했다.

# 최신 nvim(0.10.x)을 $HOME 에 설치하고 환경변수 PATH 에 추가했다.
export PATH=$HOME/nvim-linux-x86_64/bin:$PATH

# nvim 실행하면 다음과 같이 /lib64 에 없는 glibc 2.29 버전을 찾으려 해서 실행되지 않는다.
nvim: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by nvim)

# nvim 0.10.x 에서 사용하는 shared library 를 확인해보자.
# 필요한 shared library 확인
readelf -d ~/nvim-linux-x86_64/bin/nvim

# 필요한 shared library 경로까지 확인하려면
ldd nvim-linux-x86_64/bin/nvim
nvim-linux-x86_64/bin/nvim: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by nvim-linux-x86_64/bin/nvim)
        linux-vdso.so.1 (0x00007fff849d5000)
        libm.so.6 => /lib64/libm.so.6 (0x00007fa9f40f8000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fa9f3ef4000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa9f3cd4000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fa9f3abc000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fa9f36e6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa9f4b5f000)
        libutil.so.1 => /lib64/libutil.so.1 (0x00007fa9f34e2000)

# rocky8 의 기본 빌드환경(gcc,glibc...)은 유지가 필요해 최신 glibc(2.41)을 $HOME 에 설치한다.

# nvim 에서 libgcc_s.so.1 도 필요해 최신 gcc(14.2.0) 로 $HOME 에 설치한다.

# libgcc_s.so.1 는 gcc 를 별도 설치후 glibc lib 에 복사해둔다.
cp -v ~/gcc-14.2.0/lib64/libgcc_s.so.1  ~/glibc-2.41/build/lib

# LD_LIBRARY_PATH 로 shared library path 을 다음과 같이 변경하면 현재 시스템 기본 ld(동적 라이브러리 링크/로드) 2.28 버전과 맞지 않아 프롬프트가 갱신될 때마다 다음과 같은 에러가 발생한다.
export LD_LIBRARY_PATH=$HOME/glibc-2.41/build/lib
date: /lib64/ld-linux-x86-64.so.2: version `GLIBC_2.35' not found (required by /home/ysoftman/glibc-2.41/build/lib/libc.so.6)

# 방법1 - 실행은 되지만 비정상 종료
# 다음과 같이 수동설치된 glibc ld 로 library path 를 지정해서 nvim 을 실행
~/glibc-2.41/build/lib/ld-linux-x86-64.so.2 --library-path ~/glibc-2.41/build/lib ~/nvim-linux-x86_64/bin/nvim

# 방법2
# 현재 시스템의 동적 링크 환경을 변경하지 않고 nvim 자체의 동적 링크를 변경해보자.
# patchelf 툴을 사용하면 ELF(Executable and Linkable Format) 의 동적링크 경로등을 수정할 수 있다.
sudo dnf install patchelf

# patchelf 로 rpath(LD_LIBRARY_PATH보다 먼저 검색된다)를 변경하면 모두 변경된다.
# 참고로 rpath 설정시 경로에 해당 파일이 없으면 그 파일은 변경이 안된다.
patchelf --set-rpath ~/glibc-2.41/build/lib ~/nvim-linux-x86_64/bin/nvim

# 실행하면 nvim > glibc 를 사용하는데 glibc 에서 /lib64 경로를 바라 보고 있어 에러가 발생한다.
nvim: /lib64/ld-linux-x86-64.so.2: version `GLIBC_2.35' not found (required by /home/ysoftman/glibc-2.41/build/lib/libc.so.6)

# glibc > libc.so.6 는 변경이 안되고 nvim 에서 ld-linux-x86-64.so.2 를 다음으로 수정한다.
patchelf --set-interpreter ~/glibc-2.41/build/lib/ld-linux-x86-64.so.2 ~/nvim-linux-x86_64/bin/nvim

# 이제 ldd 로 보면 /home/ysoftman/glibc-2.41/build/lib/ld-linux-x86-64.so.2 로 변경되었다.
# libc.so.6 에서 not found 에러가 나도 nvim 을 ld-linux-x86.so.2 경로를 변경해서 실행할 수 있다.
ldd ~/nvim-linux-x86_64/bin/nvim
/home/ysoftman/nvim-linux-x86_64/bin/nvim: /lib64/ld-linux-x86-64.so.2: version `GLIBC_2.35' not found (required by /home/ysoftman/glibc-2.41/build/lib/libc.so.6)
        linux-vdso.so.1 (0x00007ffc6fdc3000)
        libm.so.6 => /home/ysoftman/glibc-2.41/build/lib/libm.so.6 (0x00007f6ceebc9000)
        libdl.so.2 => /home/ysoftman/glibc-2.41/build/lib/libdl.so.2 (0x00007f6cee9c7000)
        libpthread.so.0 => /home/ysoftman/glibc-2.41/build/lib/libpthread.so.0 (0x00007f6cee7c5000)
        libgcc_s.so.1 => /home/ysoftman/glibc-2.41/build/lib/libgcc_s.so.1 (0x00007f6cee598000)
        libc.so.6 => /home/ysoftman/glibc-2.41/build/lib/libc.so.6 (0x00007f6cee1b8000)
        /home/ysoftman/glibc-2.41/build/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f6cef993000)
        libutil.so.1 => /home/ysoftman/glibc-2.41/build/lib/libutil.so.1 (0x00007f6cedfb6000)

# 이제 실행하면 잘된다. 
nvim

gopls modernize

# gopls 0.18 부터 modernize 기능 추가됐다.
# modernize 분석은 최신 go 기능을 사용해 간단하고 명확한 코드로 제안(변경)한다.
# modernize 항목들에 대한 설명은 다음 문서에 명시돼 있다.

# nvim(lazyvim)에서 사용하기
# gopls 0.18 이상 최신 버전을 다시 설치
:MasonInstall gopls

# lsp 플러그인에서 analyses > modernize 사용 여부를 설정(디폴트: true)
  {
    "neovim/nvim-lspconfig",
    opts = {
      servers = {
        gopls = {
          settings = {
            gopls = {
              analyses = {
                modernize = true,
... 생략

# nvim 에서 사용시 해당 코드라인에서 -> code -> code action 으로 modernize 적용

#####

# cli 에서 사용하기
# gopls 커맨드 설치
go install golang.org/x/tools/gopls@latest

# 체크 리스트 확인
gopls check $(fd --type file .go)

# 소스 파일 전체에 대해 modernize 방식으로 일괄 변경
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest -test -fix ./...

golang staticcheck

# nvim+golang 개발환경에서 다음 2개의 툴을 사용하고 있었는데,
# golangc-lint : lint
# gopls : hint, staticcheck, hints...
# diagnostics 로 나오는 staticcheck 를 모두 모아 보고 싶어 staticcheck 커맨드를 별도 설치해서 돌려봤다.
# 설치
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck -checks inherit,-ST1005 ./...

# QF(QuickFix)xxx 결과는 보이지 않고, 실제 체크리스트에서 QF 는 없다.
staticcheck -list-checks

# 알고보니 QF 는 nvim,vscode 등의 IDE 환경에서 gopls 로 staticcheck 를 사용시에만 IDE 로 보인다고 한다.
# 참고로 nvim(lazyvim) 에 gopls 설정

# 테스트
# staticcheck 커맨드에선 QF 결과가 없다.
staticcheck ./...
ysoftman.go:7:5: don't use Yoda conditions (ST1017)

# nvim(lazyvim) 에서 <leader> -> x(diagnostics/quickfix) -> x(diagnostics) 보면 QF도 같이 보인다.

# 문제가 있는 라인으로 커서 이동후 <leader> -> c(code) -> a(code action) 으로 수정할 수 있다.
# yoda conditions 수정하기 (https://staticcheck.dev/docs/checks#ST1017)
# golang 에서는 if 내에서 = 로 할당이 안되기 때문에 c++ 처럼 값을 왼쪽에 명시해 할당 실수를 방지하는 스타일로 짜지 않아도 된다. golang 에서도 빌드는 문제 없지만 이런식은 자연스럽지 않다고 요렇게 st 로 정해두고 있다.
# 참고로 스타워즈 yoda 가 어순을 바꿔 말하는데서 유래됐다고 한다.

# 공통 변수에 대해 if / else if 문을 switch 로 수정하기  (https://staticcheck.dev/docs/checks#QF1003)
# switch 로 바꾸면 가독성이 더 좋아 보인다.

nvim taplo toml format error

# nvim(lazyvim)에 .air.toml 처럼 air 이름의 toml 파일을 열면 다음과 같은 diagnostics 에러가 발생한다.
additional properties are not allowed

# 다른 이름의 toml 파일은 문제가 없다.
# lazyvim 에서 기본적으로 toml 파일에 대해 lsp(Language Server Protocol), lint, format 을 위해 taplo(https://github.com/tamasfe/taplo, even better toml) 툴을 설치해 사용한다.
{ import = "lazyvim.plugins.extras.lang.toml" },

# toml 파일을 열면 taplo lsp 프로세스가 생성되어 처리한다.
hwatch -n 1 "ps -ef | rg -i taplo"
/Users/ysoftman/.local/share/nvim/mason/bin/taplo lsp stdio --log-spans

# lsp 사용 정보
:LspInfo

# 해결방법
# nvim-lspconfig > schema 를 비활성화
return {
  {
    "neovim/nvim-lspconfig",
    -- https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md
    opts = {
      servers = {
        taplo = {
          enabled = true,
          settings = {
            evenBetterToml = {
              -- .air.toml 에서 diagnostics 에러가 발생해 비활성화
              schema = { enabled = false },
              formatter = {
                indentString = "  ",
              },
            },
          },
        },
...

# 참고
# toml 파일들 일괄 포멧팅
fd .toml | ~/.local/share/nvim/mason/bin/taplo format --log-spans

# toml 내용 stdin 입력 포맷팅
cat typos.toml | ~/.local/share/nvim/mason/bin/taplo format -

nvim with llama

# LLM 으로 프로그래밍시 도움을 받고 싶은데, 보안상 외부 서비스는 사용할 수 없고 해서
# 로컬에서 ollama 으로 llama 모델을 사용해 보자.
brew install --cask ollama

# 참고로 M1 MAX 을 사용중인데
# Llama3.3 --> 70B(parameters) 43GB(size) --> 메모리 풀 사용으로 결과 출력이 안돼 포기
# Llama3.2 --> 3B(parameters) 2.0GB(size) --> 빠르게 잘 나온다.
# Mistral --> 7B(parameters) 4.1GB(size) --> llama3.2 와 비슷한 성능

# 모델 다운로드
# 모델은 ~/.ollama/models 에 저장되고 (ollama rm 으로 지울 수 있다.)
ollama pull llama3.2
ollama pull mistral

# 참고로 터미널에서 별도 프롬프트로 사용할 경우
ollama run llama3.2

# ollama 이 떠 있는 상태에서 curl 요청하면 토큰들이 json 응답으로 온다.
curl http://localhost:11434/api/generate -d '{
  "model": "llama3.2",
  "prompt":"Why is the sky blue?"
}'

# nvim 에서 ollama 연결을 위한 플러그인 설치(Lazy 플러그인 매니저 사용)
# 참고로 ollama 띄워져 있지 않으면 자동으로 띄운다.
# 이제 Gen 커맨드로 Ask, Change Code, Enhance Code, Review Code 등의 기능을 사용할 수 있다.
# 현재 버퍼 코드 리뷰 하는 경우
:Gen Review_Code

# 특정 부분만 코드리뷰
코드 블럭 선택:Gen Review_Code

# 한글 chat 으로 코드리뷰  
:Gen Chat > $text 코드리뷰해줘

# vscode, jetbrains 에서는 continue 를 설치하고 ollama 로 연결
# 설치 후 continue 탭에서 llama 3.2 및 localhost 를 명시한다.
# 사용 예시) review @파일명

# 한국어 사용시

gofumpt

neovim(nvim) gopls 설정을 업데이트한 후 .go 파일을 저장하면
var 로 선언된 변수가 := 로 간단하게 변경된다.

찾아보니 gopls 설정에 gofumpt(https://github.com/mvdan/gofumpt) 활성화되어 있었다.

gofumpt 는 gofmt, goimports 기능을 포함하면서 더 엄격한 포맷팅 규칙을 적용하는 확장된 포맷팅 방식이다.
그래서 gofumpt 포맷팅된 코드는 gofmt, goimports 검사를 통과한다고 한다.
요런 규칙들이 있다.
- 복합 리터럴에서 선행 또는 후행 빈 줄 제거
- 할당 연산자 다음의 불필요한 빈 줄 제거
- 인터페이스에서 불필요한 빈 줄 제거
- 가독성을 위해 함수에서 빈 줄 대신 ) { 라인 사용

# 바이너리 설치
go install mvdan.cc/gofumpt@latest

# 이전의 .go 파일들에 대해 포맷팅을 해봤는데 개인적으로 깔끔해져서 가독성에 더 좋은것 같다.
gofumpt -w -l $(fd --type file .go)

# 참고, gopls 체크사항 확인
gopls check $(fd --type file .go)

vim-gitgutter auto refresh

# 커밋전 코드 변경을 표시하기 위해 vim-gitgutter 플러그인을 사용중이다.
# 원래 커밋 후에는 변경표시(-,+등)이 사라져야 한다.
# 그런데 언제부터인가 커밋 후에도 변경 표시가 남아 있다.
# 임시 방편으로 현재 버퍼(파일) 저장시 :GitgutterAll(모든 버퍼 내용을 갱신) 명령을 설정해 사용하고 있었다.
autocmd BufWritePost * GitGutterAll

# neovim(nvim) 에서는 커밋 후에는 정상적으로 변경 표시가 사라진다.
# vim, nvim 모두 같은 gitgutter 설정을 사용한다.
# 원인 파악을 위해 다음과 같이 설정하면 gitgutter 플러그인 소스 위치에 gitgutter.log 를 생성한다.
let g:gitgutter_log = 1

# 변경내용 커밋 후 nvim 에 포커스를 옮기면 다음과 같이 gitgutter#all 함수가 수행된다.

# 반면 vim 에서는 다음과 같이 FocusGained 이벤트가 발생되지 않아 gitgutter#all이 수행되지 않고 있었다.

# 다음과 같이 vim 에 포커스 이벤트 액션을 설정하면, nvim 에서는 동작하지만 vim 에서 동작하지 않는다.
autocmd FocusGained * echo 'Vim has gained focus'
autocmd FocusLost * echo 'Vim has lost focus'

# iterm 내에서는 vim 포커스 이벤트가 동작한다.
# 찾아 보니 alacritty 에서 focus 이벤트가 동작하지 않는다는 이슈가 있었다.
# 다음과 같이 alacritty 사용시 터미널코드를 별도 설정하면 된다.
# 참고로 :set termcap 으로 설정된 터미널 코드 확인
if &term =~ "alacritty"
  let &t_fe = "\<Esc>[?1004h"
  let &t_fd = "\<Esc>[?1004l"
endif

vscode c++ formatting

# vscode cpp extenstion 을 설치하고 코드 포맷팅을 하면 엉뚱하게 포맷팅이 된다.
# 이유는 포맷팅 환경이 설정되어 있지 않아서다.
# 우선 clang-format 을 설치하자.
brew install clang-format

# settings.json 을 열어 다음과 같이 설정한다.
"C_Cpp.clang_format_path": "/usr/local/bin/clang-format",

# file 이라고 명시하면 현재 프로젝트의 루트 경로의 .clang-format 파일을 읽어 들인다.
"C_Cpp.clang_format_style": "file",

# format_style 실패시 기본 셋팅(Visual Studio, LLVM, Google, Chromium, Mozilla, WebKit)
"C_Cpp.clang_format_fallbackStyle": "Visual Studio"

# lazyvim(neovim)에서는 conform 플러그인에 cpp 포맷터로 clang-format 을 설정한다.
return {
  "stevearc/conform.nvim", -- For formatting
  opts = {
    -- formatters by file type
    formatters_by_ft = {
      cpp = { "clang-format" },
    },
  },
}

# 프로젝트 루트 위치에 .clang-format 파일을 다음과 같이 설정해 사용할 수 도 있다.
# 사용중인 .clang-format 파일
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
# BreakBeforeBraces: Allman # Always break before braces.
BreakBeforeBraces: Attach # Always attach braces to surrounding context.

# 참고로 현재 경로의 모든 c/cpp 파일 포맷팅 적용
# --style=file 로 지정하면 .clanf-format 파일을 참고한다.
# -i 옵션을 주면 변경된 스타일이 파일에 적용된다.
fd ".c$|.cpp$" --exec clang-format --style=file -i

# 포맷 스타일 결과 비교, main 함수만 발췌
# 개인적으로 visualstudio 또는 google 스타일이 좋은것 같다.

# Visual Studio 는 Clang-format 기본스타일 종류에는 없고 다음과 같이 설정해야한다.
# clang-format --style="{UseTab: Never,IndentWidth: 4,
BreakBeforeBraces: Allman,
AllowShortIfStatementsOnASingleLine: false,
IndentCaseLabels: false,
ColumnLimit: 0}" hello_world.cpp
# 들여쓰기 탭, 시작 중괄호 한줄 차지
int main()
{
    string a = "1";
    if (a == "1")
    {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="google" hello_world.cpp
# 들여쓰기 공백2, 시작 중괄호 같은 라인에 시작
int main() {
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}

# clang-format --style="webkit" hello_world.cpp
# 들여쓰기 공백4, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
int main()
{
    string a = "1";
    if (a == "1") {
        cout << "hello world" << endl;
    }
    return 0;
}

# clang-format --style="mozilla" hello_world.cpp
# 들여쓰기 공백2, 함수 시작 중괄호만 한줄, 함수내에서는 같은 라인에 시작
# 함수 리턴 타임 한줄 차지
int
main()
{
  string a = "1";
  if (a == "1") {
    cout << "hello world" << endl;
  }
  return 0;
}