edit_linting.sh 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # @yaml
  2. # signature: |-
  3. # edit <start_line>:<end_line>
  4. # <replacement_text>
  5. # end_of_edit
  6. # docstring: replaces lines <start_line> through <end_line> (inclusive) with the given text in the open file. The replacement text is terminated by a line with only end_of_edit on it. All of the <replacement text> will be entered, so make sure your indentation is formatted properly. Python files will be checked for syntax errors after the edit. If the system detects a syntax error, the edit will not be executed. Simply try to edit the file again, but make sure to read the error message and modify the edit command you issue accordingly. Issuing the same command a second time will just lead to the same error message again.
  7. # end_name: end_of_edit
  8. # arguments:
  9. # start_line:
  10. # type: integer
  11. # description: the line number to start the edit at
  12. # required: true
  13. # end_line:
  14. # type: integer
  15. # description: the line number to end the edit at (inclusive)
  16. # required: true
  17. # replacement_text:
  18. # type: string
  19. # description: the text to replace the current selection with
  20. # required: true
  21. edit() {
  22. if [ -z "$CURRENT_FILE" ]
  23. then
  24. echo 'No file open. Use the `open` command first.'
  25. return
  26. fi
  27. local start_line="$(echo $1: | cut -d: -f1)"
  28. local end_line="$(echo $1: | cut -d: -f2)"
  29. if [ -z "$start_line" ] || [ -z "$end_line" ]
  30. then
  31. echo "Usage: edit <start_line>:<end_line>"
  32. return
  33. fi
  34. local re='^[0-9]+$'
  35. if ! [[ $start_line =~ $re ]]; then
  36. echo "Usage: edit <start_line>:<end_line>"
  37. echo "Error: start_line must be a number"
  38. return
  39. fi
  40. if ! [[ $end_line =~ $re ]]; then
  41. echo "Usage: edit <start_line>:<end_line>"
  42. echo "Error: end_line must be a number"
  43. return
  44. fi
  45. local linter_cmd="flake8 --isolated --select=F821,F822,F831,E111,E112,E113,E999,E902"
  46. local linter_before_edit=$($linter_cmd "$CURRENT_FILE" 2>&1)
  47. # Bash array starts at 0, so let's adjust
  48. local start_line=$((start_line - 1))
  49. local end_line=$((end_line))
  50. local line_count=0
  51. local replacement=()
  52. while IFS= read -r line
  53. do
  54. replacement+=("$line")
  55. ((line_count++))
  56. done
  57. # Create a backup of the current file
  58. cp "$CURRENT_FILE" "/root/$(basename "$CURRENT_FILE")_backup"
  59. # Read the file line by line into an array
  60. mapfile -t lines < "$CURRENT_FILE"
  61. local new_lines=("${lines[@]:0:$start_line}" "${replacement[@]}" "${lines[@]:$((end_line))}")
  62. # Write the new stuff directly back into the original file
  63. printf "%s\n" "${new_lines[@]}" >| "$CURRENT_FILE"
  64. # Run linter
  65. if [[ $CURRENT_FILE == *.py ]]; then
  66. _lint_output=$($linter_cmd "$CURRENT_FILE" 2>&1)
  67. lint_output=$(_split_string "$_lint_output" "$linter_before_edit" "$((start_line+1))" "$end_line" "$line_count")
  68. else
  69. # do nothing
  70. lint_output=""
  71. fi
  72. # if there is no output, then the file is good
  73. if [ -z "$lint_output" ]; then
  74. export CURRENT_LINE=$start_line
  75. _constrain_line
  76. _print
  77. echo "File updated. Please review the changes and make sure they are correct (correct indentation, no duplicate lines, etc). Edit the file again if necessary."
  78. else
  79. echo "Your proposed edit has introduced new syntax error(s). Please read this error message carefully and then retry editing the file."
  80. echo ""
  81. echo "ERRORS:"
  82. echo "$lint_output"
  83. echo ""
  84. # Save original values
  85. original_current_line=$CURRENT_LINE
  86. original_window=$WINDOW
  87. # Update values
  88. export CURRENT_LINE=$(( (line_count / 2) + start_line )) # Set to "center" of edit
  89. export WINDOW=$((line_count + 10)) # Show +/- 5 lines around edit
  90. echo "This is how your edit would have looked if applied"
  91. echo "-------------------------------------------------"
  92. _constrain_line
  93. _print
  94. echo "-------------------------------------------------"
  95. echo ""
  96. # Restoring CURRENT_FILE to original contents.
  97. cp "/root/$(basename "$CURRENT_FILE")_backup" "$CURRENT_FILE"
  98. export CURRENT_LINE=$(( ((end_line - start_line + 1) / 2) + start_line ))
  99. export WINDOW=$((end_line - start_line + 10))
  100. echo "This is the original code before your edit"
  101. echo "-------------------------------------------------"
  102. _constrain_line
  103. _print
  104. echo "-------------------------------------------------"
  105. # Restore original values
  106. export CURRENT_LINE=$original_current_line
  107. export WINDOW=$original_window
  108. echo "Your changes have NOT been applied. Please fix your edit command and try again."
  109. echo "You either need to 1) Specify the correct start/end line arguments or 2) Correct your edit code."
  110. echo "DO NOT re-run the same failed edit command. Running it again will lead to the same error."
  111. fi
  112. # Remove backup file
  113. rm -f "/root/$(basename "$CURRENT_FILE")_backup"
  114. }